ASP.NET Core模型绑定行为切换

时间:2019-04-24 07:32:06

标签: c# asp.net-core .net-core asp.net-core-2.2 .net-core-2.2

在对API进行大量重构期间,似乎我改变了一些影响模型绑定/模型验证行为的东西。

我试图调查这些变化,但我不知道变化是由什么引起的。

我有一个MyApiController继承自ControllerBaseMyApiController的post方法接收一个请求模型(使用默认的API模板创建,而没有HTTPS为您提供典型的ValuesController)。

  using Microsoft.AspNetCore.Mvc;
  using Microsoft.Extensions.Logging;
  using Newtonsoft.Json;
  using System;
  using System.Threading.Tasks;

  namespace XperimentModelBinding.Controllers
  {

    [ApiController]
    [Route("api/[controller]")]
    public class MyApiController : ControllerBase
    {

      public ILogger<MyApiController> Logger { get; }

      public MyApiController(ILogger<MyApiController> logger)
      {
        Logger = logger ?? throw new ArgumentNullException(nameof(logger));
      }


      [HttpPost()]
      public async Task<IActionResult> PostModel([FromBody] MyCreateRequestModel request)
      {

        Logger.LogInformation("PostModel: " + JsonConvert.SerializeObject(request, Formatting.None));

        if (!ModelState.IsValid) return BadRequest(ModelState);

        return Ok();

      }
    }
  }

我使用的模型是:

  using System.ComponentModel.DataAnnotations;

  namespace XperimentModelBinding
  {

    public class MyCreateRequestModel
    {

      [Required]
      [StringLength(10)]
      public string Name { get; set; }

      [Required]
      [Range(1, 5)]
      public int Value { get; set; }

    }

  }

启动它并在记录器上设置一个断点。

与邮递员一起测试:

测试1:

  {
    "Name": "1234567890",
    "Value": 1
  }

击中断点,返回200 OK(按预期)。

测试2:

  {
    "Name": null,
    "Value": 1
  }

断点未命中,返回的模型为:

  {
    "errors": {
        "Name": [
            "The Name field is required."
        ]
    },
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "80000006-0000-ff00-b63f-84710c7967bb"
  }

预期结果是调用了该方法,命中了换行符,到目前为止,我已经有了响应模型(似乎只包含错误):

{
    "Name": [
        "The Name field is required."
    ]
}

改变的是:给定一个无效模型的请求,我的方法被调用,我用ModelState.IsValid检查是否有错误。太好了,因为我以这种方式创建了自定义响应模型。

现在我的方法不再被调用,并且模型绑定直接返回其自己的模型。

什么改变了我的方法不再被调用?

2 个答案:

答案 0 :(得分:4)

它已连接到link的[ApiController]属性

  

Web API控制器如果具有> [ApiController]属性,则不必检查ModelState.IsValid。在这种情况下,当模型状态无效时,将返回包含问题详细信息的自动HTTP 400响应。有关更多信息,请参阅HTTP 400自动响应。

答案 1 :(得分:1)

您可能想在ConfigureApiBehaviorOptionsservices.AddMvc()内使用Startup.cs来为无效的模型请求设置自定义错误消息。

services.AddMvc()
    .ConfigureApiBehaviorOptions(options => {
        options.InvalidModelStateResponseFactory = actionContext =>
        {
            var modelState = actionContext.ModelState.Values;
            return new BadRequestObjectResult(new ErrorResult(modelState));
        };
    });
});

并根据需要定义ErrorResult类,例如:

public class ErrorResult
{
    public int code { get; set; }
    public string message { get; set; }

    public ErrorResult()
    {
    }

    public ErrorResult(ModelStateDictionary.ValueEnumerable modelState)
    {
        // This will take the error message coming directly from modelState
        foreach (var value in modelState)
        {
            if (value.Errors.Count > 0)
            {
                code = 900; // Or use a code handler or whatever
                message = value.Errors.FirstOrDefault().ErrorMessage;
                break;
            }
        }
    }
}