繁体   English   中英

ModelState 无效时触发 InvalidModelStateResponseFactory

[英]Triggering InvalidModelStateResponseFactory when ModelState is invalid

我正在使用 asp.net 核心 3.0 编写 API 并为我的应用程序配置了所有控制器的以下行为:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers()                    
                .ConfigureApiBehaviorOptions(setupAction =>
                {                        
                    setupAction.InvalidModelStateResponseFactory = context =>
                    {
                        var problemDetails = new ValidationProblemDetails(context.ModelState)
                        {
                            Type = "https://courselibrary.com/modelvalidationproblem",
                            Title = "One or more model validation errors occurred.",
                            Status = StatusCodes.Status422UnprocessableEntity,
                            Detail = "See the errors property for details",
                            Instance = context.HttpContext.Request.Path
                        };

                        problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);

                        return new UnprocessableEntityObjectResult(problemDetails)
                        {
                            ContentTypes = { "application/problem+json" }
                        };
                    };
                });
        ...  
    }

这适用于我的输入(例如: [Required] )类的属性上的数据注释。 如果任何注释失败,它会返回一个 422 Unprocessable Entity 响应,如下所示:

{
    "type": "https://courselibrary.com/modelvalidationproblem",
    "title": "One or more model validation errors occurred.",
    "status": 422,
    "detail": "See the errors property for details",
    "instance": "/api/songbooks/21924d66-dac6-43a5-beee-206de4d35216/songs",
    "traceId": "0HLQFGSFIFL5L:00000001",
    "errors": {
        "Title": [
            "The Title field is required."
        ]
    }
}

但是,我在我的 controller 中实现 FluentValudation,如下所示:

if (!newSong.IsValid)
{
    newSong.Validate().AddToModelState(ModelState, null);
    _logger.LogWarning("{method} failed model validation (ModelState: {@modelState}), returning Unprocessable Entity", nameof(Post), ModelState.Values.SelectMany(v => v.Errors));
    return UnprocessableEntity(ModelState);                
}

但是,这不会像内置验证那样触发InvalidModelStateResponseFactory

有谁知道我如何从我的 controller 中触发相同类型的事件来使用这个方便的处理程序?

事实上,有一个非常简单的答案。 通过使用这个 ValidationProblem 模式,您可以简单地返回ValidationProblem(ModelState) ,而不是返回Ok()BadRequest()或诸如此类的ActionResult ,它将使用Startup.cs Api 配置中的工厂设置!

所以这就是我可以做的:

if (!newSong.IsValid)
{
    newSong.Validate().AddToModelState(ModelState, null);
    _logger.LogWarning("{method} failed model validation (ModelState: {@modelState}), returning Unprocessable Entity", nameof(Post), ModelState.Values.SelectMany(v => v.Errors));
    return ValidationProblem(ModelState);                
}

此外,您需要像这样覆盖行为以将其从您的启动中拉出(感谢 Kevin Dockx 的这个想法):

public override ActionResult ValidationProblem([ActionResultObjectValue] ModelStateDictionary modelStateDictionary)
    {
        var options = HttpContext.RequestServices.GetRequiredService<IOptions<ApiBehaviorOptions>>();
        return (ActionResult)options.Value.InvalidModelStateResponseFactory(ControllerContext);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM