我有一个自定义的IActionFilter
,可以像这样向我的应用程序注册:
services.AddControllers(options => options.Filters.Add(new HttpResponseExceptionFilter()));
该类看起来像这样:
public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order { get; set; } = int.MaxValue - 10;
public void OnActionExecuting(ActionExecutingContext context)
{
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception == null) return;
var attempt = Attempt<string>.Fail(context.Exception);
if (context.Exception is AttemptException exception)
{
context.Result = new ObjectResult(attempt)
{
StatusCode = exception.StatusCode,
};
}
else
{
context.Result = new ObjectResult(attempt)
{
StatusCode = (int)HttpStatusCode.InternalServerError,
};
}
context.ExceptionHandled = true;
}
}
我希望验证时会调用OnActionExecuting
方法。所以我添加了这段代码:
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
并且我在方法的开头放置了一个断点,但是当我运行我的应用程序并尝试发布无效的模型时,我得到了这个响应:
{
"errors": {
"Url": [
"'Url' is invalid. It should start with 'https://www.youtube.com/embed'",
"'Url' is invalid. It should have the correct parameter '?start='"
]
},
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|87e96062-42181357ba1ef8c5."
}
如何强制FluentValidation使用我的过滤器?
当应用[ApiController]
属性时,ASP.NET Core通过返回一个400的以ModelState作为响应主体的错误请求来自动处理模型验证错误:
要禁用自动400行为,请将SuppressModelStateInvalidFilter
属性设置为true:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
我发现的最佳解决方案是:
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var messages = context.ModelState.Values
.Where(x => x.ValidationState == ModelValidationState.Invalid)
.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage)
.ToList();
return new BadRequestObjectResult(
Attempt<string>.Fail(
new AttemptException(string.Join($"{Environment.NewLine}", messages))));
};
})