I have a old MVC program web api with [ValidateModel] attribute:
[Route("login")]
[ValidateModel]
public User Login(LoginModel model)
{
}
Validate the model by code below and return with custom response:
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateResponse(
HttpStatusCode.BadRequest,
new CustomErrorResult
{
Succeeded = false,
Errors = actionContext.ModelState.Values.SelectMany(
o => o.Errors.Select(
e => e.ErrorMessage))
});
}
base.OnActionExecuting(actionContext);
}
}
Custom error result class
public class CustomErrorResult
{
public bool Succeeded { get; set; }
public IEnumerable<string> Errors { get; set; }
}
I am revamping the code to .NET Core now, how do I modify this part to Core version?
I am researched quite some time but still unable solve this, .NET Core seem have a feature can suppress custom response in startup/program file?
CodePudding user response:
When using a controller with the [ApiController]
attribute applied, ASP.NET Core automatically handles model validation errors by returning a 400 Bad Request with ModelState
as the response body.
Reference: Automatic HTTP 400 responses
One way is that you could suppress this feature by:
services.AddControllers().ConfigureApiBehaviorOptions(options => {
options.SuppressModelStateInvalidFilter = true;
});
And change your custom ValidateModel:
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(new CustomErrorResult
{
Succeeded = false,
Errors = context.ModelState.Values.SelectMany(
o => o.Errors.Select(
e => e.ErrorMessage))
});
}
base.OnActionExecuting(context);
}
}
Another way without customizing ValidateModel is to use a custom response factory in Startup.cs like below:
services.Configure<ApiBehaviorOptions>(o =>
{
o.InvalidModelStateResponseFactory = actionContext =>
new BadRequestObjectResult(new BadRequestObjectResult(new CustomErrorResult
{
Succeeded = false,
Errors = actionContext.ModelState.Values.SelectMany(
o => o.Errors.Select(
e => e.ErrorMessage))
}));
});