Skip to main content
A newer version of this page is available. .

Validate Input

  • 12 minutes to read

You can add any standalone data editor or the Form Layout component to Blazor’s standard EditForm. This form validates user input based on data annotation attributes defined in a model and indicates errors.

Important

You should not rely on form validation alone to secure your Blazor-powered app. Form validation is designed to improve usability. A threat actor can bypass validation and send malicious data to the server. To minimize security related threats/risks, you must validate user input using multiple strategies. Refer to the following topic for more information: Validate User Input.

The following table lists data editors and their properties that you can validate in the EditForm.

Data Editor

Property

DxCalendar

SelectedDate

SelectedDates

DxCheckBox

Checked

DxComboBox

Value

DxDateEdit

Date

DxListBox

Values

DxMemo

Text

DxSpinEdit

Value

DxTagBox

Tags

Values

DxTextBox

Text

Common Steps

Do the following to enable input validation:

  1. Create a model and apply data annotation attributes to model fields.

    using System.ComponentModel.DataAnnotations;
    
    public class MyModel
    {
        [Required]
        [StringLength(10, ErrorMessage = "Name is too long.")]
        public string Name { get; set; }
        // ...
    }
    
  2. Declare the EditForm component and assign a model object to the EditForm’s Model property. The edit context is constructed based on this model. To supply the edit context explicitly, assign it to the EditContext property and do not specify the Model property.

    <EditForm Model="@model" ...>
    </EditForm>
    
    @code {
        private MyModel model = new MyModel();
        // ...
    }
    
  3. Create the DataAnnotationsValidator component to enable validation based on annotation attributes.

    <EditForm Model="@model" ...>
        <DataAnnotationsValidator />
        @*...*@
    </EditForm>
    
  4. Add standalone data editors or the Form Layout with data editors to the EditForm. Use the @bind attribute to implement two-way binding between editor properties and model fields that have data annotations. The edit context is updated once input values are changed.

    <EditForm Model="@model" ...>
        <DataAnnotationsValidator />
        <DxFormLayout >
            <DxFormLayoutItem Caption="Name:" ColSpanMd="6" >
                <Template >
                    <DxTextBox @bind-Text="@model.Name" />
                </Template >
            </DxFormLayoutItem >
        </DxFormLayout>
        @*...*@
    </EditForm>
    

    If you handle an editor’s <PropertyName>Changed event and cannot use two-way binding, specify the <PropertyName>Expression.

    <DxTextBox Text="@model.Name"
               TextExpression="@(() => model.Name)"
               TextChanged="@TextChanged">
    </DxTextBox>
    
    @code {
        void TextChanged(string textValue) {
            // ...
        }
    }
    

    An exception occurs if you do not use two-way binding or the <PropertyName>Expression.

  5. If you place the Form Layout component in the EditForm, specify an unique value for the EditForm‘s Context property to avoid a name conflict. Otherwise, Blazor adds implicit Context parameters with the same name to the EditForm and each layout item.

    <EditForm Model="@model" Context="EditFormContext" ...>
        @*...*@
    </EditForm>
    
  6. Use the ValidationMessage component to display messages for individual data editors or the ValidationSummary component to summarize validation messages.

    <DxFormLayout >
        @*...*@
        <DxFormLayoutItem ColSpanMd="12">
            <Template>
                <ValidationSummary />
            </Template>
        </DxFormLayoutItem>
    </DxFormLayout>
    
  7. If you want to respond to form submission, specify the EditForm‘s OnValidSubmit and OnInvalidSubmit callbacks. They are triggered when the form passed and failed validation, respectively. For instance, you can post valid values to an underlying data source. Alternatively, you can specify the OnSubmit callback to check field values and trigger validation manually.

    <EditForm Model="@model" ... OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
        @*...*@
    </EditForm>
    
  8. Add the DxButton component and set its SubmitFormOnClick property to true. The form submits when a user clicks this button.

    <DxFormLayout >
        @*...*@
        <DxFormLayoutItem ColSpanMd="12">
            <Template>
                <DxButton SubmitFormOnClick="true" Text="Submit" RenderStyle="@ButtonRenderStyle.Secondary" />
            </Template>
        </DxFormLayoutItem>
    </DxFormLayout>
    

The EditForm validates input values based on the edit context once a user attempts to submit this form. Editors become marked with colored outlines: green indicates valid values, red - invalid values.

Valid Value

Invalid Value

Valid Input

Invalid Input

For more information, refer to the official Microsoft documentation: Forms and validation.

Custom Validation Attributes

You can also implement a custom validation attribute.

  1. Create a ValidationAttribute class descendant.
  2. Override the IsValid method to implement custom validation logic. This method has two overloads: one overload accepts only the object that should be validated; the other also accepts a ValidationContext object that stores additional information about the validation operation.
  3. Apply the AttributeUsage class to the custom attribute to specify how the attribute can be used.
  4. Apply the custom attribute to a model field.

For more information, refer to the official Microsoft documentation: Custom attributes.

using System.ComponentModel.DataAnnotations;

public class Starship
{
    // ...

    [DateInPastAttribute(ErrorMessage = "The Production Date value cannot be later than today.")]
    public DateTime ProductionDate { get; set; }
}

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, 
                AllowMultiple = false)]
public class DateInPastAttribute: ValidationAttribute
{
    public override bool IsValid(object value)
    {
        return (DateTime)value <= DateTime.Today;
    }
}

Form Layout

The following example validates user input in the Form Layout component with four layout items. These items contain the following data editors: Text Box, ComboBox, Spin Edit, and Date Edit.

One layout item contains the ValidationSummary component that displays all the error messages. The last layout item contains the Button that submits the form.

Validate Input in Form Layout

<EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit" 
          Context="EditFormContext">
    <DataAnnotationsValidator />
    <DxFormLayout >
        <DxFormLayoutItem Caption="Identifier:" ColSpanMd="6" >
            <Template >
                <DxTextBox @bind-Text="@starship.Identifier" />
            </Template >
        </DxFormLayoutItem >
        <DxFormLayoutItem Caption="Primary Classification:" ColSpanMd="6" >
            <Template >
                <DxComboBox
                            NullText="Select classification ..."
                            ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto"
                            @bind-Value="@starship.Classification"
                            Data="@(new List<string>() { "Defense", "Exploration", "Diplomacy" })"
                />
            </Template >
        </DxFormLayoutItem >
        <DxFormLayoutItem Caption="Maximum Accommodation:" ColSpanMd="6" >
            <Template >
                <DxSpinEdit Id="accommodation" @bind-Value="@starship.MaximumAccommodation" />
            </Template >
        </DxFormLayoutItem >
        <DxFormLayoutItem Caption="Production Date:" ColSpanMd="6" >
            <Template >
                <DxDateEdit @bind-Date="@starship.ProductionDate" />
            </Template>
        </DxFormLayoutItem>
        <DxFormLayoutItem ColSpanMd="12">
            <Template>
                <ValidationSummary />
            </Template>
        </DxFormLayoutItem>
        <DxFormLayoutItem ColSpanMd="12">
            <Template>
                <DxButton SubmitFormOnClick="true" Text="Submit" RenderStyle="@ButtonRenderStyle.Secondary" />
            </Template>
        </DxFormLayoutItem>
    </DxFormLayout>
</EditForm>

@code {
    private Starship starship=new Starship();

    private void HandleValidSubmit() {
        Console.WriteLine("OnValidSubmit");
    }
    private void HandleInvalidSubmit() {
        Console.WriteLine("OnInvalidSubmit");
    }
}

Run Demo: Form Validation - Form Layout

Standalone Data Editors

The following example validates user input in standalone Text Box, ComboBox, Spin Edit, and Date Edit. The ValidationMessage component is used to display error messages for each editor.

Validate Input in Data Editors

<EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
    <DataAnnotationsValidator />
    <div class="row">
        <div class="col-md-6" style="padding-bottom: 12px">
            <label for="identifier">Identifier: </label>
            <DxTextBox Id="identifier" @bind-Text="@starship.Identifier" />
            <ValidationMessage For="@(() => starship.Identifier)" />
        </div>
        <div class="col-md-6" style="padding-bottom: 12px">
            <label for="classification">Primary Classification: </label>
            <DxComboBox Id="classification" NullText="Select classification ..."
                        ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto"
                        Data="@(new List<Classification>() { new Classification(1, "Defense"),
                                                             new Classification(2, "Exploration"),
                                                             new Classification(3, "Diplomacy") })"
                        TextFieldName="Value"
                        ValueFieldName="Id"
                        @bind-Value="@starship.Classification" />
            <ValidationMessage For="@(() => starship.Classification)" />
        </div>
        <div class="col-md-6" style="padding-bottom: 12px">
            <label for="accommodation">Maximum Accommodation: </label>
            <DxSpinEdit Id="accommodation" @bind-Value="@starship.MaximumAccommodation" />
            <ValidationMessage For="@(() => starship.MaximumAccommodation)" />
        </div>
        <div class="col-md-6" style="padding-bottom: 12px">
            <label for="productionDate">Production Date: </label>
            <DxDateEdit @bind-Date="@starship.ProductionDate" />
            <ValidationMessage For="@(() => starship.ProductionDate)" />
        </div>
        <div class="col-md-12">
            <DxButton SubmitFormOnClick="true" Text="Submit" RenderStyle="@ButtonRenderStyle.Secondary" />
        </div>
    </div>
</EditForm>

@code {
    private Starship starship = new Starship();

    private void HandleValidSubmit() {
        Console.WriteLine("OnValidSubmit");
    }
    private void HandleInvalidSubmit() {
        Console.WriteLine("OnInvalidSubmit");
    }
}

Run Demo: Form Validation - Custom Form

Data Editors Inside Another Component

To validate user input in a data editor that is placed in another Blazor component, do the following:

  1. Create a custom Blazor component and add a data editor. Define parameters that is passed to the editor’s <PropertyName> and <PropertyName>Expression properties and handle the <PropertyName>Changed event as shown below. The following snippet creates the MyComponent with a Text Box:

    <DxTextBox Text="@MyValue" TextChanged="@((v) => MyValue = v)" TextExpression="@MyValueExpression" />
    
    @code {
        private string _value;
    
        [Parameter]
        public string MyValue
        {
            get => _value;
            set
            {
                if (_value == value) return;
                _value = value;
                MyValueChanged.InvokeAsync(value);
            }
        }
    
        [Parameter]
        public EventCallback<string> MyValueChanged { get; set; }
    
        [Parameter]
        public Expression<Func<string>> MyValueExpression { get; set; }
    }
    
  2. Register the System.Linq.Expressions namespace in the _Imports.razor file to use the Expression class.

    @using System.Linq.Expressions
    
  3. Apply data annotation attributes to model fields and add the MyComponent to the EditForm.

    <EditForm Model="@customer" OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit" 
            Context="EditFormContext">
        <DataAnnotationsValidator />
        <div class="container">
            <div class="col">
                <div class="row"><h5>@nameof(customer.FirstName)</h5></div>
                <div class="row">
                    <div class="form-group">
                        <MyComponent @bind-MyValue="@customer.FirstName" />
                        <ValidationMessage For="@(() => customer.FirstName)" />
                    </div>
                </div>
            </div>
    
            <div class="col">
                <div class="row"><h5>@nameof(customer.LastName)</h5></div>
                <div class="row">
                    <div class="form-group">
                        <MyComponent @bind-MyValue="@customer.LastName" />
                        <ValidationMessage For="@(() => customer.LastName)" />
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <div class="form-group ">
                        <DxButton SubmitFormOnClick="true" Text="Submit" 
                                  RenderStyle="@ButtonRenderStyle.Primary" />
                    </div>
                </div>
            </div>
        </div>
    </EditForm>
    

Validate Editors in Another Component

Data Grid Edit Form

To validate user input in the Data Grid’s edit form, use the EditFormTemplate property. Place the Blazor EditForm component to the template and add data editors or the Form Layout.

Refer to the EditFormTemplate property description for step-by-step instructions.

Grid EditFormTemplate

<DxDataGrid @ref="@grid"
            Data="@Vacancies"
            ShowPager="false"
            RowRemoving="@((dataItem) => OnRowRemoving(dataItem))"
            RowEditStart="@(dataItem => OnRowEditStarting(dataItem))"
            RowInsertStart="@(() => OnRowEditStarting(null))">
    <Columns>
        <DxDataGridCommandColumn Width="150px"></DxDataGridCommandColumn>
        <DxDataGridComboBoxColumn Field="@nameof(Vacancy.Region)" Data="@VacancyRepository.Regions"></DxDataGridComboBoxColumn>
        <DxDataGridColumn Field="@nameof(Vacancy.City)"></DxDataGridColumn>
        <DxDataGridColumn Field="@nameof(Vacancy.Description)" Caption="Vacancy"></DxDataGridColumn>
    </Columns>
    <EditFormTemplate>
        <EditForm Model="@EditContext" Context="EditFormContext" OnValidSubmit="@HandleValidSubmit">
            <DataAnnotationsValidator />
            <DxFormLayout>
                <DxFormLayoutItem Caption="Vacancy Description:" ColSpanMd="12" Context="FormLayoutContext">
                    <Template>
                        <DxTextBox @bind-Text="@EditContext.Description" />
                    </Template>
                </DxFormLayoutItem>
                <DxFormLayoutItem Caption="Region:" ColSpanMd="6" Context="FormLayoutContext">
                    <Template>
                        <DxComboBox Data="@VacancyRepository.Regions"
                                    NullText="Select Region..."
                                    @bind-Value="@EditContext.Region">
                        </DxComboBox>
                    </Template>
                </DxFormLayoutItem>
                <DxFormLayoutItem Caption="City:" ColSpanMd="6" Context="FormLayoutContext">
                    <Template>
                        <DxComboBox Data="@EditContext.OfficeLocations"
                                    NullText="Select City..."
                                    @bind-Value="@EditContext.City">
                        </DxComboBox>
                    </Template>
                </DxFormLayoutItem>
                <DxFormLayoutItem ColSpanMd="12" Context="FormLayoutContext">
                    <Template>
                        <ValidationSummary />
                    </Template>
                </DxFormLayoutItem>
                <DxFormLayoutItem ColSpanMd="12" Context="FormLayoutContext">
                    <Template>
                        <div class="text-right">
                            <DxButton RenderStyle="@ButtonRenderStyle.Link" SubmitFormOnClick="true" Text="Update" />
                            <DxButton RenderStyle="@ButtonRenderStyle.Link" @onclick="@OnCancelButtonClick" Text="Cancel" />
                        </div>
                    </Template>
                </DxFormLayoutItem>
            </DxFormLayout>
        </EditForm>
    </EditFormTemplate>
</DxDataGrid>

Run Demo: Data Grid - Edit Form Template with Validation