【问题标题】:ASP.NET Core 6 WebAPI, invalid model does not reach the action method, instead instantly returns with HTTP 400ASP.NET Core 6 WebAPI,无效模型未到达操作方法,而是立即返回 HTTP 400
【发布时间】:2023-02-15 11:20:40
【问题描述】:

我使用 .NET 6 在 VS 2022 中创建了一个 WebAPI 项目 我用 [MaxLength(5)][MinLength(5)] 属性注释了模型的客户类 CustomerId 属性。

[Route("api/[controller]")]
[ApiController]
public class CustomerController : ControllerBase
{
    private readonly NorthwindContext _ctx;
    // ...
    [HttpPost]
    public Customer Insert(Customer customer)
    {
        // Method never called. Somewhere the pipeline instantly 
        // sends the HTTP 400 response with the correct error message.
        if (!ModelState.IsValid)
        {

        }

如果我使用无效数据调用 API,比如 4 或 6 长度的 CustomerId,则永远不会调用 Insert 方法。管道在某处立即发送 HTTP 400 响应正确的验证错误信息

问题

不清楚,那么 ModelState.IsValid 什么时候会为假?我可以配置管道以允许调用该方法吗?

【问题讨论】:

  • 400 可能意味着请求根本无法解析为控制器操作/路由,您将发布到哪个目标 URL?
  • 绝对不是这样。那将是 404。此外,如果我发出完全相同的请求但具有有效数据,则会调用该方法。我还在我的 OP 中写道,400 中的错误消息是正确的。
  • ...但现在我编辑它以更正验证消息...更明确
  • 这可能是您的路线,但如果没有任何客户端代码,很难说清楚。

标签: c# validation asp.net-core-webapi


【解决方案1】:

由于 .Net 6/.Net 7 中的可空性,您发送到 Web API 的数据必须与模型匹配,否则就会发生这种情况。

public class MyModel
{
    public int SomeId { get; set; }
    public int? ForeignId { get; set; }
    public string? SomeName { get; set; }
    public string RequiredName{ get; set; }
}

MyModel myData = new() 
{
 SomeId = 5,
 ForeignId = 9,
 SomeName = "Test",
 RequiredName = null
}

var myResult = MyWebAPICall(myData);

由于 RequiredName 被定义为不可为 null,Web API 将拒绝它并发回 400。

您必须检查模型/DTO,并确保您定义的内容与您的数据源(数据库等)相匹配,以便正确保存并关注哪些字段需要允许空值。可空性确实迫使您经历一切。

【讨论】:

    【解决方案2】:

    不清楚,那么 ModelState.IsValid 什么时候会为假?

    好吧,简而言之,在 MVC 控制器中;如果默认情况下您没有在属性上设置任何注释,则它的必需意味着不为空。因此,如果您不传递该值,您的 ModelState.IsValid 将始终为 false。通常模型状态表示来自两个子系统的错误。

    例如,model bindingmodel validation 这意味着请求首先进入模型验证器,一旦它满足条件,然后它路由到特定的控制器,控制器不会被击中。

    因此,当您需要设置任何属性时,您的ModelState.IsValid 将始终为 false,并且在您为场景 Insert 提交请求时不会传递该值。所以,是的,任何不可以为 nullable ? 的属性都需要在请求提交期间通过,而不是你的 ModelState.IsValid 始终是 false

    让我们考虑一下,你的Customer Class如果不为空,你已经对 CustomerId 设置了一些验证约束;它首先会到达模型绑定,如果它不符合您的条件,它将从那里抛出验证消息并且它不会命中控制器。

    因此,如果您不传递不可为 null 的属性的值,或者您的属性违反任何条件,它将限制您提交请求。

    为什么你的 ModelState.IsValid 没有达到?

    当您使用 Web API 控制器和 Web API 控制器时,如果它们具有 ApiController attribute,则不必检查 ModelState.IsValid。在这种情况下,当模型状态无效时,将返回包含错误详细信息的自动 HTTP 400 响应。

    我可以配置管道以允许调用该方法吗?

    当然可以。在那种情况下,你必须disable the automatic 400 behavior。您可能知道 builder.Services.AddControllers 中的 ConfigureApiBehaviorOptions,您将获得一个名为 SuppressModelStateInvalidFilter 的属性,我们必须将此属性设置为 true。请查看以下代码 sn-p:

    builder.Services.AddControllers()
        .ConfigureApiBehaviorOptions(options =>
        {
            options.SuppressModelStateInvalidFilter = true;
        });
    

    输出:

    笔记:

    如果您想了解有关Model state Validationautomatic 400 response 的更多详细信息,您可以check our official document here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-12
      • 1970-01-01
      • 2022-11-08
      • 2019-07-28
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 2018-11-29
      相关资源
      最近更新 更多