liveBook · Manning

ModelState

As explained in ASP.NET Core in Action, 3e

ModelState is the ASP.NET Core request-state dictionary that stores bound values and validation errors associated with properties or the model.

ModelState is the request-state dictionary used by ASP.NET Core MVC and Razor Pages. It holds the results of model binding and validation, including errors associated with a model or its properties. The framework validates bound data before an action or page handler runs, but a Razor Page handler still runs when validation fails. Check ModelState.IsValid before using the data for business logic. section 16.3.2 section 15.3

Listing 16.7 Checking model state to view the validation result
public class CheckoutModel : PageModel                              #1
{
    [BindProperty]                                                  #2
    public UserBindingModel Input { get; set; }                     #2
 
    public IActionResult OnPost()                                   #3
    {
        if (!ModelState.IsValid)                                    #4
        {
            return Page();                                          #5
        }
 
        /* Save to the database, update user, return success */     #6
 
        return RedirectToPage("Success");
    }
}

In the checkout handler, an invalid ModelState leads to Page(), which redisplays the form with the submitted values and validation messages. Only a valid submission proceeds toward saving and a redirect to the success page. section 16.3.2

Validation is automatic; choosing the response is not. Returning Page() is useful when a Razor Page should let the user correct a form. For an API, a validation failure commonly produces a 400 Bad Request response containing errors. The [ApiController] attribute ordinarily supplies that API behavior, including a Problem Details response. A custom action filter is an alternative when you cannot or do not want to use the attribute. section 16.3.2 section 22.1.3

Listing 22.5 The action filter for validating ModelState
public class ValidateModelAttribute : ActionFilterAttribute      #1
{
    public override void OnActionExecuting(                      #2
        ActionExecutingContext context)                          #2
    {
        if (!context.ModelState.IsValid)                         #3
        {
            context.Result =                                     #4
                new BadRequestObjectResult(context.ModelState);  #4
        }
    }
}

The custom action filter checks context.ModelState.IsValid before the action executes. If it is false, setting context.Result to a BadRequestObjectResult containing ModelState short-circuits the action. section 22.1.3

Testing the invalid path

A controller unit test does not run MVC model binding, so passing an invalid model alone will not populate ModelState. Add an error with controller.ModelState.AddModelError before calling the action, then check its result. Keep the test model consistent with that error so the test represents a situation that could occur in the running application. section 36.2

ModelState is also a reason to choose an MVC or Razor Pages filter rather than middleware for shared response logic: filters can access MVC constructs such as ModelState, while general middleware cannot. section 21.3

How ASP.NET Core in Action, 3e covers it

How deep it goes
Defines ModelState as a ModelStateDictionary of validation results and works through response handling, filters, and unit tests without exploring its internals.
Examples
Shows a checkout form redisplayed after validation failure, an API action filter returning Bad Request, and a controller test adding an error.
What it assumes
Assumes familiarity with C# handlers or actions while explaining when framework validation runs and who must handle failure.
What you can do after
Apply it via ModelState.IsValid to handle invalid submissions, and diagnose/debug with it by adding errors in controller unit tests.
How it connects
Connects ModelState to model binding, validation, Razor Page handlers, API controllers, action filters, and middleware.

Also explained in

Compare how 3 books explain ModelState →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of ASP.NET Core in Action, 3e. The section links point to the parts of the book it draws on.