Blazor University Learn the .NET SPA framework from Microsoft
Ctrl X

Validation

The DataAnnotationsValidator is the standard validator type in Blazor. Adding this component within an EditForm component will enable form validation based on .NET attributes descended from System.ComponentModel.DataAnnotations.ValidationAttribute.

First we'll create a short example, then we'll go through what happens behind the scenes. First, create a model we can edit, and decorate its properties with some data annotations for validation.

public class Person
{
  [Required]
  public string Name { get; set; }
  [Range(18, 80, ErrorMessage = "Age must be between 18 and 80.")]
  public int Age { get; set; }
}
  • Line 3 specifies the Name property cannot be null or empty.
  • Line 5 specifies a valid range of values for the Age property (from 18 to 80) and also provides a suitable error message to display to the user.

Adding validation

Edit the Index.razor page in a default Blazor app and provide some mark-up to edit an instance of Person.

<EditForm Model=@Person>
  <div class="form-group">
    <label for="Name">Name</label>
    <InputText @bind-Value=Person.Name class="form-control" id="Name" />
  </div>
  <div class="form-group">
    <label for="Age">Age</label>
    <InputNumber @bind-Value=Person.Age class="form-control" id="Age" />
  </div>
  <input type="submit" class="btn btn-primary" value="Save"/>
</EditForm>

@code {
  Person Person = new Person();
}

Running the app now will result in the user being presented with a form that does not validate their input. To ensure the form is validated we must specify a validation mechanism. Add a DataAnnotationsValidator component inside the EditForm component.

<EditForm Model=@Person>
  <DataAnnotationsValidator/>
  <div class="form-group">
    <label for="Name">Name</label>
    <InputText @bind-Value=Person.Name class="form-control" id="Name" />
  </div>
  <div class="form-group">
    <label for="Age">Age</label>
    <InputNumber @bind-Value=Person.Age class="form-control" id="Age" />
  </div>
  <input type="submit" class="btn btn-primary" value="Save"/>
</EditForm>

Running the app and clicking the Save button will update the user interface to provide a visual indication that there are errors in the user's input.

Displaying validation error messages

Validation error messages can be displayed to the user in two ways. We can add a ValidationSummary to show a comprehensive list of all errors in the form. We can also use the ValidationMessage component to display error messages for a specific input on the form. These components are not mutually exclusive, so it is possible to use both at the same time.

The ValidationSummary component can simply be dropped into an EditForm in our mark-up; no additional parameters are required at all.

As the ValidationMessage component displays error messages for a single field, it requires us to specify the identity of the field. To ensure our parameter's value stays correct after refactoring (for example, when we refactor property names on our Person class) Blazor requires us to specify an Expression when identifying the field. The parameter, named For, is defined on the ValidationMessage as follows:

[Parameter]
public Expression<Func<T>> For { get; set; }

This means to specify the identity of the field we should use a lambda expression, which can be presented either "quoted", or wrapped in @(...)

  • Quoted form
    <ValidationMessage For="() => Person.Name"/>
  • Razor expression form
    <ValidationMessage For=@( () => Person.Name )/>

Both forms are equivalent. The quoted form is easier to read, whereas the razor expression makes it more obvious to other developers that we are defining an expression rather than a string.

@page "/"
@using Models

<EditForm Model=@Person>
  <DataAnnotationsValidator/>
  <ValidationSummary/>
  <div class="form-group">
    <label for="Name">Name</label>
    <InputText @bind-Value=Person.Name class="form-control" id="Name" />
    <ValidationMessage For="() => Person.Name"/>
  </div>
  <div class="form-group">
    <label for="Age">Age</label>
    <InputNumber @bind-Value=Person.Age class="form-control" id="Age" />
    <ValidationMessage For=@(() => Person.Age) />
  </div>
  <input type="submit" class="btn btn-primary" value="Save"/>
</EditForm>

@code {
  Person Person = new Person();
}