ASP.NET Core 2.0 MVC Model Validation

Problem

How to validate input models in ASP.NET Core MVC.

Solution

We discussed model binding in a previous post, using that sample as a template, add Save() method in HomeController:

Add a model annotated with various validation attributes:

Discussion

Data coming from web (forms, HTTP request etc.) must be validated. No exceptions! Model Validation is the mechanism ASP.NET Core MVC provides for this purpose. Validation triggers after the Model Binding but before the action executes.

Validations can be added by using Validation Attributes. Framework provides a lot of useful validation attributes and we can even create our own too.

Model State

ControllerBase provides a property ModelState to work with model validation. MVC will populate this dictionary with validation errors after model binding. You could then verify its IsValid property in the action method to act accordingly.

ModelState has a method to add errors to the model at server side (e.g. in Controller). This is use for validations that require database access and report errors back to the client. Modified Save() method demonstrates this:

ModelState:

model state

Validation Attributes

Framework provided validation attributes exist in System.ComponentModel.DataAnnotations. In the sample application I’ve demonstrated the use of commonly used attributes.

An interesting aspect of model validation is that even without any attributes, MVC will do some basic validations based on data types. Below is result of a request when model has no validation and no data was supplied, note that empty values fail for Integer, DateTime and Boolean properties:

error

Custom Validation

Custom validation attributes are useful to create reusable and application specific validation logic. There are two ways to implement this (both can be used on the same model):

Inherit ValidationAttribute and override its IsValid method

IsValid takes in a parameter of type ValidationContext, which has few useful properties:

  • ObjectInstance: returns the model on which the attribute is applied. Casting this to a specific model class gives you access to its properties.
  • DisplayName: returns either the name of model’s property or string specific in [Display(Name = “…”)] attribute applied to the property.

ValidationAttribute class also provide few useful properties and methods:

  • ErrorMessage: returns the error message set on the attribute when declaring it in the model.
  • FormatErrorMessage: returns the generic message i.e. The field {0} is invalid, where {0} is replaced with DisplayName.

IsValid method returns ValidationResult class, either through its static field Success or by initialising a new instance (in case of an error).

Below is a custom validation attribute applied on the BirthDate property of our model:

Implement IValidatableObject in your model

To implement more complex validations that need access to more than one property in your model, IValidatableObject works best, by implementing its Validate() method. A key thing to remember is that these validations will run after attribute based validations are successful.

Validate() method returns IEnumerable, because this method can validate more than one property of the model providing a validation error for each.

Here is a sample for our example model:

Source Code

GitHub: https://github.com/TahirNaushad/Fiver.Mvc.ModelValidation

Leave a Reply