Model State Validation in ASP.NET Core

ASP.Net Model binder could help you to link the data it generates to an error. The errors that Model Binder encounters when trying to bind the values of the request with the properties of the ViewModel are saved in the ModelState and can be consulted from the controller itself and also from the view. In fact, as we saw in the previous article, the helpers consult the ModelState to use a specific CSS class in case there is an error associated with the field.

Trying to convert an alphanumeric string into an int is therefore an error, but there are many more cases in which we may be interested in telling the user that the data entered is incorrect: mandatory fields, strings with a certain format (eg an email) or two fields that must have the same value (eg password and check password). These are the cases when we refer to validations and that is what we are going to discuss in our article. But even though we differentiate between errors and validations, ASP.NET MVC does not: both are treated the same, that is, they are both stored in the ModelState. But before delving further, let’s see exactly what the ModelState is.

ModelState or model status

The ModelState is an object, managed by the ASP.NET MVC framework that indicates the state of the model. In this context, by model, we understand the object that a controller receives (what we generally call view model) and by state, we understand if it is correct or not. Correct means that the data in the request was valid and that the Model Binder was able to create an object and fill it. Incorrect means that there was some invalid request data, either due to an error (an alphanumeric string was tried to be assigned to an int) or due to some unsuccessful validation (a string declared as email did not have the correct format).
The ModelState is basically a dictionary where:

  1. The keys are the names of the properties of our model (they are really the names used by the Model Binder to link the properties but we can assume that they coincide).
  2. For each key, there is the value that Model Binder has assigned to that key and what matters most to us: a collection of the errors linked to that key if any. And when I say errors here I mean both errors and failed validations.

The ModelState contains a property called IsValid that tells us if the model is correct, that is, if there are no errors. That property is usually used in the following way:

[HttpPost]
public ActionResult Index(DemoModel data)
{

   if (!ModelState.IsValid)
   {
     return View(data);
  }
   else
   {
     // Codigo normal
   return View("ok");
  }

}

If the ModelState is not valid it means that some input of the user is not correct, therefore we return again the view that contains the form with the data. As we saw in the previous article if we use the helpers to create the form, those will show the errors (in red with CSS by default). If the ModelState is valid that means that the user entries are correct so we proceed to perform the action we want.

Add our validations
Well, we have seen the mechanism used by the MVC framework to indicate that there is an error, the ModelState. Now let’s see how we can add our validations. Although ASP.NET MVC is very flexible at this point, let’s see the most common way of doing it: using DataAnnotations. In later articles, we will see other forms.
To add validations using DataAnnotations we simply have to decorate the property we want with some of the attributes (some of them are in the namespace System.ComponentModel.DataAnnotations and others in System.Web.Mvc). E.g. if we have the following ViewModel:

public class DemoModel
{
  public string Nombre { get; set; }
   public int Edad { get; set; }
}

If we want the Name to be obligatory we can decorate it with [Required]:

public class DemoModel
{
  [Required]
   public string Nombre { get; set; }
  public int Edad { get; set; }
}

And ready! Just by adding the Required attribute, the framework knows that the Name is required and if the user does not enter it, an error will be displayed.

Here is the sample code to generate that view:

@using (Html.BeginForm()) {
      @Html.ValidationSummary(true)
     <fieldset>
            <legend>DemoModel</legend>

            <div class="editor-label">
                  @Html.LabelFor(model => model.Nombre)
            </div>
           <div class="editor-field">
                 @Html.EditorFor(model => model.Nombre)
           @Html.ValidationMessageFor(model => model.Nombre)
           </div>

            <div class="editor-label">
                  @Html.LabelFor(model => model.Edad)
            </div>
           <div class="editor-field">
                 @Html.EditorFor(model => model.Edad)
                  @Html.ValidationMessageFor(model => model.Edad)
            </div>

            <p>
                 <input type="submit" value="Create" />
           </p>
      </fieldset>
}

Other attributes to validate

There are several attributes for different validations and all are used the same: decorating the properties. If your application requires that its users are between 18 and 65 years old, you can use Range:

public class DemoModel
{
   [Required]
   public string Nombre { get; set; }
   [Range(18, 65)]
   public int Edad { get; set; }
}

More attributes that exist:

  • StringLength: To limit the number of characters in a text field (eg the password must be between 6 and 15 characters).
  • Compare: So that two fields have the same value (eg password and repeat password)
  • RegularExpression: To validate against a regular expression

Of course, there is the possibility of creating your own attributes for own validations … but that is something we leave for a later article!

Happy Coding!

You may also like...

Leave a Reply

Your email address will not be published.