WebAPI OData 验证失败未返回 ModelState 对象

Posted

技术标签:

【中文标题】WebAPI OData 验证失败未返回 ModelState 对象【英文标题】:WebAPI OData failed validation ModelState object not returned 【发布时间】:2014-06-20 01:44:45 【问题描述】:

我正在创建一个 AngularJS Web 表单,以使用 WebAPI 设置作为 OData 执行 POST(插入)到表中。我正在尝试取回验证失败的 ModelState 对象(以 JSON 格式)以验证表单上的相应字段。

我得到的只是一个字符串,其中包含所有详细信息作为字符串(不是 JSON 可解析格式)


  "odata.error":
    "code":"","message":
      "lang":"en-US","value":"The request is invalid."
    ,"innererror":
      "message":"application.ApplicationName : The ApplicationName field is required.\r\n","type":"","stacktrace":""
    
  

我的 post 方法如下所示:

 public async Task<IHttpActionResult> Post(Application application)
        
           if (!ModelState.IsValid)
            
                return BadRequest(ModelState);
            

            db.Applications.Add(application);
            await db.SaveChangesAsync();

            return Created(application);
        

我什至尝试过将其抽象为 ActionFilterAttribute,但结果仍然相同

public class ValidateModelAttribute : ActionFilterAttribute
    
        public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
        
            if (actionContext.ModelState.IsValid == false)
            

                var modelState = actionContext.ModelState;

                if (!modelState.IsValid)
                    actionContext.Response = actionContext.Request
                         .CreateErrorResponse(HttpStatusCode.BadRequest, modelState);

            
        
    

我的WebApi启动方法有如下配置:

public static class WebApiConfig
    
        public static void Register(HttpConfiguration config)
        

            config.Routes.MapHttpRoute(
               name: "DefaultApi",
               routeTemplate: "api/controller/id",
               defaults: new  id = RouteParameter.Optional 
            );

            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<Application>("DataApplications");
            config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel());


            config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings()  NullValueHandling = NullValueHandling.Include ;

            Configure(config);

            config.EnableQuerySupport();

            // Use camel case for JSON data.
            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

这是我想要实现的(与我上面的示例不匹配):


    "Message": "The request is invalid.",
    "ModelState":  
        "car": [
            "Required property 'Make' not found in JSON. Path '', line 1, position 57."
        ],
        "car.Make" : [
            "The Make field is required."
        ], 
        "car.Price": [
            "The field Price must be between 0 and 200000."
        ]
    

我需要返回 ModelState,以便在适当的字段中定位验证反馈。

任何想法我可以检查/更改以使其按需要工作?

谢谢。

更新 1 - 在 asp.net 上找到的参考

http://www.asp.net/aspnet/overview/aspnet-and-visual-studio-2012/aspnet-and-web-tools-20122-release-notes

OData 错误响应不包含模型状态错误

当使用 CreateErrorResponse 扩展方法或 HttpErrors 直接创建错误响应时,错误将映射到 OData 错误响应。错误响应中的任何模型状态错误都不会传播到 OData 错误响应。要在 OData 错误响应中保留模型状态错误,请直接使用 CreateODataErrorResponse 扩展方法或 ODataError,并将模型状态错误的描述添加到 OData 错误消息中。

【问题讨论】:

您找到解决方案了吗? 如果找到了可以分享一下解决方法吗? 【参考方案1】:

OData 使用ODataError 作为错误响应。 ODataErrorHttpEror 之间的区别在于 HttpError 派生自 Dictionary&lt;string, object&gt; 所以当它用 ModelStateDictionary 实例化时,所有模型错误都设置为 ModelState 属性。但是,当您请求 OData 时,HttpError 对象会映射到 ODataError,并且所有验证错误都会连接到 InnterError 属性中。

【讨论】:

以上是关于WebAPI OData 验证失败未返回 ModelState 对象的主要内容,如果未能解决你的问题,请参考以下文章

使用 EF 和 WebAPI,如何返回 ViewModel 并支持 IQueryable/OData? [复制]

OData 和 WebAPI:模型上不存在导航属性

对 DTO 的 ASP.NET WebApi OData 支持

OData v4 WebAPI 响应中的项目计数

OData WebAPI,内存可查询和区分大小写

武装你的WEBAPI-OData聚合查询