微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 ModelState 返回不同的结果以及如何解决它?

如何解决为什么 ModelState 返回不同的结果以及如何解决它?

Asp.net 核心 3.1 WebApi。

我有一个具有所需属性的模型。

1.如果模型无效,则响应包含数据 喜欢:

{
    "errors": {
        "Name": [
            "Update model can't have all properties as null."
        ],"Color": [
            "Update model can't have all properties as null."
        ]
    },"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1","title": "One or more validation errors occurred.","status": 400,"traceId": "|f032f1c9-4c36d1e62aa60ead."
}

这对我来说看起来不错。

但是如果我向 modelState.AddModelError("statusId","Invalid order status id.") 添加一些自定义验证,那么它会返回不同的结构:

[
    {
        "childNodes": null,"children": null,"key": "statusId","subKey": {
            "buffer": "statusId","offset": 0,"length": 8,"value": "statusId","hasValue": true
        },"isContainerNode": false,"rawValue": "11202","attemptedValue": "11202","errors": [
            {
                "exception": null,"errorMessage": "Invalid order status id."
            }
        ],"validationState": 1
    }
]

看起来 ModelState.IsValid 对控制器来说实际上不再是了,因为错误的请求甚至在它以无效模式进入控制器之前就被返回了。或者是否有通过 ModelSate 进行全局验证的标志?

为什么结构不同? 怎么弄得一样? 在 MVC 中,如何强制访问 api 控制器内部的 ModelState.IsValid 方法

更新:



    [Route("....")]
    [Authorize]
    [ApiController]
    public class StatusesController : ApiControllerBase
    {


        [HttpPut,Route("{statusId}")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status409Conflict)]
        [Produces("application/json")]
        public async Task<ObjectResult> UpdateStatusAsync(int statusId,[FromBody] StatusUpdateDto orderStatusUpdateDto)
        {

            int companyId = User.Identity.GetClaimValue<int>(ClaimTypes.CompanyId);

            const string errorNotFound  = "There is not order status with this id for such company";
            if (statusId <= 0)
            {
                Logger.LogError(errorNotFound);
                ModelState.AddErrorModel(nameof(statusId),"Invalid order status id")
                throw new NotFound(ModelState);
            }
            
            if (orderStatusUpdateDto == null)
            {
                const string error = "Invalid (null) order status can't be added";
                Logger.LogError(error);
                throw new ArgumentNullException(error);
            }

            if (ModelState.IsValid == false) // also this code is always true or returns 400 before this line
            {
                return BadRequest(ModelState); 
            }

           ....
            return result;
        }

}

解决方法

ApiController 属性向控制器添加了一些特定的自以为是的行为。其中之一是如果模型无效则返回 400 错误。 可以禁用此行为,但仅限于全局级别。

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

我认为您有以下选择:

  • 禁用此行为并自行检查 ModelState.IsValid。使用 ValidationProblem 方法产生相同的响应
  • 将此检查添加到模型的验证器
  • 保持原样。但是在控制器方法中使用 ValidationProblem 返回验证错误。

有关信息,请参阅https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.1#automatic-http-400-responses

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。