asp.net mvc - BindModel gets executed before ActionFilterAttribute -
i have started running weird problem.
i have asp.net project in have api takes post params. since use interface, used custom deserializer read post object. worked till last few days. but, 1 day started getting 500 - internal server error saying "cannot create instance of interface. ... through createmodel". @ time, using postman app. there virtually no change in code, thought may postman app got corrupted.
i wasn't sure, had tried same query on fiddler , worked fine. now, after 3-4 days, fiddler stopped working same error.
after digging through, found somehow 'bindmodel' has started executing may be before actionfilterattribute. i'm not sure how possible. there workaround overcome situation? post http call not entering jsonfilter's onactionexecuting method
error msg:
[missingmethodexception: cannot create instance of interface.]
system.runtimetypehandle.createinstance(...)
system.runtimetype.createinstanceslow(...)
system.activator.createinstance(...)
system.activator.createinstance(...)
system.web.mvc.defaultmodelbinder.createmodel(...)[missingmethodexception: cannot create instance of interface. object type 'mycommonobj.imyinterface'.]
system.web.mvc.defaultmodelbinder.createmodel(...)
system.web.mvc.defaultmodelbinder.bindcomplexmodel(...)
system.web.mvc.defaultmodelbinder.bindmodel(...)
code snippet:
public class jsonfilter : actionfilterattribute { public string parameter { get; set; } public type jsondatatype { get; set; } public override void onactionexecuting(actionexecutingcontext filtercontext) { if (filtercontext.httpcontext.request.contenttype.contains("application/json")) { string inputcontent; filtercontext.httpcontext.request.inputstream.position = 0; using (var sr = new streamreader(filtercontext.httpcontext.request.inputstream)) { inputcontent = sr.readtoend(); }; var jsonserializersettings = new jsonserializersettings() { typenamehandling = typenamehandling.all }; if (jsondatatype == typeof(myclass)) { var result = jsonconvert.deserializeobject<myclass>(inputcontent, jsonserializersettings); filtercontext.actionparameters[parameter] = result; } else { throw new notimplementedexception(); } } } } [httppost] [jsonfilter(parameter = "config", jsondatatype = typeof(myclass))] public actionresult executeapi(myclass config) { var result = dosomething(config); return json(result); } public interface imyinterface { string getvalue(); } public class myderivedclass : imyinterface { public string value { get; set; } public myderivedclass(string v) { value = v; } public string getvalue() { return value; } } public class query { [jsonproperty(typenamehandling = typenamehandling.all)] public imyinterface type { get; set; } public query () {} } public class myclass { list<query> mylist { get; set; } public myclass () {} }
action filters always run after model binder. if need filter run before model binder, should use iauthorizationfilter
.
[attributeusage(attributetargets.method | attributetargets.class, allowmultiple = false)] public class jsonfilter : attribute, iauthorizationfilter { public string parameter { get; set; } public type jsondatatype { get; set; } public void onauthorization(authorizationcontext filtercontext) { if (filtercontext.httpcontext.request.contenttype.contains("application/json")) { string inputcontent; filtercontext.httpcontext.request.inputstream.position = 0; using (var sr = new streamreader(filtercontext.httpcontext.request.inputstream)) { inputcontent = sr.readtoend(); }; var jsonserializersettings = new jsonserializersettings() { typenamehandling = typenamehandling.all }; if (jsondatatype == typeof(myclass)) { var result = jsonconvert.deserializeobject<myclass>(inputcontent, jsonserializersettings); filtercontext.actionparameters[parameter] = result; } else { throw new notimplementedexception(); } } } }
Comments
Post a Comment