在模型状态无效时触发无效的模型状态响应工厂



我正在使用 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 无法处理的实体响应:

{
"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."
]
}
}

但是,我在我的控制器中实现了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

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

事实上,有一个非常简单的答案。通过使用这个 ValidationProblem 模式,您可以简单地返回ValidationProblem(ModelState),它将使用Startup.csAPI 配置中设置的出厂设置,而不是返回Ok()BadRequest()或其他什么ActionResult

所以这是我可以做的:

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);
}

相关内容

最新更新