如何识别模型绑定错误和模型验证错误?

时间:2017-08-29 14:06:38

标签: asp.net-core-mvc model-binding model-validation

我正在使用ASP.NET Core MVC 2.0实现REST API项目,如果模型绑定失败(因为请求语法错误)和422状态,我想返回400状态代码代码如果模型验证失败(因为请求在语法上是正确的但包含不可接受的值)。

举个例子,给出像

这样的动作
[HttpPut("{id}")]
public async Task<IActionResult> UpdateAsync(
    [FromRoute] int id,
    [FromBody] ThingModel model)

当路由中的id参数包含非数字字符或者在请求中未指定正文时,我想返回400状态代码,当属性中有422状态代码时,我想返回400状态代码ThingModel包含无效值。

从我所看到的IValueProviderIModelBinder实施中,我们将错误添加到请求的ModelStateDictionary,就像验证器一样,并且没有办法在绑定和验证之间注入代码。

我该如何实现这样的行为?

2 个答案:

答案 0 :(得分:1)

尚未检查选项#1,但是:

  • ModelState。ValidationState 具有4个可能的值(未验证,无效,有效,已跳过),如果出现模型绑定错误,我会得到未验证作为值
  • 还可以考虑使用 ApiBehaviorOptions (请参见示例here)来自动返回新的BadRequestObjectResult(actionContext.ModelState)-因为发生绑定错误时NULL绑定值无所作为,如果发生验证错误,我们也可能无能为力。

ApiBehaviorOptions的快速注释:

  • 必须使用ApiController属性(它也需要在控制器级别上具有路由属性,并且确实会改变绑定的工作方式)
  • 具有ApiController属性的默认行为将返回BadRequestObjectResult(actionContext.ModelState),而无需任何额外的代码和配置
  • 如果您决定使用自己的ApiBehaviorOptions-必须在service.AddMvc之后对其进行初始化,或者需要使用具有类似效果的services.PostConfigure(o => {})
  • ApiBehaviorOptions SuppressModelStateInvalidFilter必须为false,InvalidModelStateResponseFactory才能正常工作

因此,在某些情况下,自定义过滤器是更好的解决方案(更改较少)。

答案 1 :(得分:0)

在项目中添加以下属性

public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);

        if (!context.ModelState.IsValid)
            context.Result = new BadRequestObjectResult(new
            {
                message = context.ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage))
            });
    }
}

像这样改变你的api

[HttpPut("{id}")]
[ValidateModel]
public async Task<IActionResult> UpdateAsync(
    [FromRoute] int id,
    [FromBody] ThingModel model)

id包含非数字=&gt; 400

model未在=&gt;内传递注释验证400

如果您想在模型中使用422代码拒绝不可接受的值,请在您的控制器中实现