FluentValidation使用自定义IActionFilter

问题描述 投票:0回答:2

我有一个自定义的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使用我的过滤器?

c# asp.net-core fluentvalidation action-filter
2个回答
0
投票

当应用[ApiController]属性时,ASP.NET Core通过返回一个400的以ModelState作为响应主体的错误请求来自动处理模型验证错误:

Automatic HTTP 400 responses

要禁用自动400行为,请将SuppressModelStateInvalidFilter属性设置为true:

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

0
投票

我发现的最佳解决方案是:

.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))));
    };
})
© www.soinside.com 2019 - 2024. All rights reserved.