I have a custom IActionFilter
which I register with my application like so:
services.AddControllers(options => options.Filters.Add(new HttpResponseExceptionFilter()));
The class looks like this:
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;
}
}
I would expect that when validating it would invoke the OnActionExecuting
method. So I added this code:
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
And I put a breakpoint at the start of the method, but when I run my application and try to post an invalid model, I get this response:
{
"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."
}
How can I force FluentValidation to use my filter?
The best solution I found was:
.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))));
};
})