Check ModelState.IsValid globally for all controllers

In my main ASP.NET controllers, I always check if the ModelState is really:

[HttpPost("[action]")] public async Task<IActionResult> DoStuff([FromBody]DoStuffRequest request) { if (!ModelState.IsValid) { return BadRequest("invalid parameters"); } else { return Ok("some data")); } } 

Is there a way to verify that ModelState is being used globally using a filter, so I no longer need to do this in every API element on every controller? It would be nice if the action could rely on the fact that the model state really does not need to be checked:

 [HttpPost("[action]")] public async Task<IActionResult> DoStuff([FromBody]DoStuffRequest request) { return Ok("some data")); } 
+6
source share
4 answers

You can use ActionFilter . It is not global, but it moves the problem from your method body to the attribute. I understand that it does not completely solve your problem, but may be better than nothing.

 public class ModelStateValidationActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { var modelState = actionContext.ModelState; if (!modelState.IsValid) actionContext.Response = actionContext.Request .CreateErrorResponse(HttpStatusCode.BadRequest, modelState); } } 

And in your controller:

 [HttpPost] [ModelStateValidationActionFilter] public IHttpActionResult Post(object model) { } 

I believe that you can install it on your controller as well. I actually have not tried this, but could work accordingly .

 [ModelStateValidationActionFilter] public class MyApiController : ApiController { } 

EDIT:

As @Camilo Terevinto mentioned, Core is a little different. Just use this ActionFilter if you want to use Core.

 public class ModelStateValidationActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { var modelState = context.ModelState; if (!modelState.IsValid) context.Result = new ContentResult() { Content = "Modelstate not valid", StatusCode = 400 }; base.OnActionExecuting(context); } } 
+7
source

The existing answers so far are for the ASP.NET Web API , and not for the ASP.NET Core . The actual way to do this in the ASP.NET kernel is:

 public class SampleActionFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { // do something before the action executes } public void OnActionExecuted(ActionExecutedContext context) { // do something after the action executes } } 

And you can register this filter globally in Startup.cs so that it will be executed in every single call, and you do not need to repeat it in each Action / Controller:

 options.Filters.Add(typeof(SampleActionFilter)); 

More details in the official documentation .

+5
source

Use HandleInvalidModelState

PM> Install-Package HandleInvalidModelState

Example

 [HttpPost] [TypeFilter(typeof(HandleInvalidModelWithViewActionFilterAttribute))] public IHttpActionResult Post(object model) {} 

In addition to the base scenario of the script (return with an invalid model), the package supports Json return and Request redirection .

disclaimer: package author

0
source

For ASP.NET Core 2.0, not to apply attributes to all Controllers or Actions individually;

Define a filter:

 namespace Test { public sealed class ModelStateCheckFilter : IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { } public void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { context.Result = new BadRequestObjectResult(context.ModelState); } } } } 

Then in Startup.cs add it as a filter:

  public void ConfigureServices(IServiceCollection services) { services.AddMvc(config => { config.Filters.Add(new ModelStateCheckFilter()); }); } 
0
source

Source: https://habr.com/ru/post/1014452/


All Articles