BindModel在ActionFilterAttribute

时间:2016-04-20 01:05:05

标签: asp.net-mvc asp.net-mvc-4 model-binding action-filter custom-action-filter

我开始遇到一个奇怪的问题。

我有ASP.NET项目,其中我有一个API,它接受POST参数。由于我使用了一个接口,我使用自定义反序列化器来读取POST对象。它工作正常,直到最后几天。 但是,有一天我开始得到500 - 内部服务器错误说"无法创建接口的实例。 ...通过CreateModel"。那时,我正在使用PostMan应用程序。由于代码几乎没有变化,我认为可能是PostMan App被破坏了。

我不确定,所以我在Fiddler上尝试了相同的查询,但它运行良好。现在,3-4天之后,Fiddler也停止了同样的错误。

经过挖掘,我发现了某种方式' BindModel'已经开始在ActionFilterAttribute之前执行 可能 。我不知道怎么可能。有没有解决这种情况的解决方法? 我的帖子http调用只是没有输入JsonFilter的OnActionExecuting方法

错误消息:

  

[MissingMethodException:无法创建接口的实例。]
  System.RuntimeTypeHandle.CreateInstance(...)
  System.RuntimeType.CreateInstanceSlow(...)
  System.Activator.CreateInstance(...)
  System.Activator.CreateInstance(...)
  System.Web.Mvc.DefaultModelBinder.CreateModel(...)

     

[MissingMethodException:无法创建接口的实例。   对象类型' MyCommonObj.IMyInterface'。]
  System.Web.Mvc.DefaultModelBinder.CreateModel(...)
  System.Web.Mvc.DefaultModelBinder.BindComplexModel(...)
  System.Web.Mvc.DefaultModelBinder.BindModel(...)

代码段:

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 () {}
}

1 个答案:

答案 0 :(得分:0)

操作过滤器始终在模型绑定器之后运行。如果您需要在模型绑定器之前运行过滤器,则应使用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();
            }
        }
    }
}