Blazor 6 min read

Blazor Forms and Validation: A Practical Guide

Forms are a core part of many Blazor applications. This guide explains EditForm, validation models, data annotations, validation messages and practical form patterns.

Admin
Admin
.NET & IoT Developer
Blazor Forms and Validation: A Practical Guide

Blazor Forms and Validation: A Practical Guide

Forms are one of the most common parts of web applications. Login pages, contact forms, checkout flows, admin panels, search filters and data entry screens all depend on forms.

Blazor provides a clean way to build forms using EditForm, model binding and validation components. The basic setup is simple, but real-world forms require careful structure.

A good form should be easy to use, easy to validate and easy to maintain.

The basic EditForm

The main component for forms in Blazor is EditForm.

Example:

<EditForm Model="@model" OnValidSubmit="HandleSubmit">
    <DataAnnotationsValidator />
&lt;InputText @bind-Value="model.Title" /&gt;
&lt;ValidationMessage For="@(() =&gt; model.Title)" /&gt;

&lt;button type="submit"&gt;Save&lt;/button&gt;

</EditForm>

The EditForm is connected to a model. The input components bind to properties on that model. Validation messages are displayed when the model is invalid.

This pattern is clean and strongly typed.

Creating a form model

A form model should represent the data the user is allowed to enter.

Example:

public class CreateBlogPostForm
{
    [Required]
    [StringLength(120)]
    public string Title { get; set; } = string.Empty;
[Required]
[StringLength(200)]
public string Excerpt { get; set; } = string.Empty;

[Required]
public string Content { get; set; } = string.Empty;

}

This model is not necessarily the same as your database entity.

That is important.

A database entity may contain fields such as Id, CreatedAt, UpdatedAt, AuthorId and PublishedAt. The user should not always be able to edit those fields directly.

Use a dedicated form model when the form has its own purpose.

Data annotations validation

Blazor works well with data annotations.

Common attributes include:

  • Required
  • StringLength
  • Range
  • EmailAddress
  • Compare
  • RegularExpression

Example:

public class ContactForm
{
    [Required]
    public string Name { get; set; } = string.Empty;
[Required]
[EmailAddress]
public string Email { get; set; } = string.Empty;

[Required]
[StringLength(1000)]
public string Message { get; set; } = string.Empty;

}

Then enable validation:

<DataAnnotationsValidator />

And show validation errors:

<ValidationSummary />

or per field:

<ValidationMessage For="@(() => model.Email)" />

For most simple forms, this is enough.

Field-level validation messages

A good form should show errors close to the field that caused them.

Example:

<label>Title</label>
<InputText class="form-control" @bind-Value="model.Title" />
<ValidationMessage For="@(() => model.Title)" />

This creates a better user experience than showing all errors only at the top.

For larger forms, a combination works well:

  • field-level messages near each input
  • a validation summary at the top for general overview

Handling valid submit

OnValidSubmit is called only when the form passes validation.

<EditForm Model="@model" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />
&lt;InputText @bind-Value="model.Title" /&gt;
&lt;ValidationMessage For="@(() =&gt; model.Title)" /&gt;

&lt;button type="submit"&gt;Save&lt;/button&gt;

</EditForm>

Handler:

private async Task HandleValidSubmit()
{
    await BlogPostService.CreateAsync(model);
}

This keeps the submit logic simple because validation has already passed.

Handling invalid submit

Sometimes you want to react when the form is invalid.

<EditForm Model="@model"
          OnValidSubmit="HandleValidSubmit"
          OnInvalidSubmit="HandleInvalidSubmit">
    <DataAnnotationsValidator />
</EditForm>

Example:

private void HandleInvalidSubmit()
{
    errorMessage = "Please fix the validation errors before submitting.";
}

This is useful when you want to display a general message, log validation attempts or guide the user.

Input components

Blazor provides several built-in input components.

Common ones include:

  • InputText
  • InputTextArea
  • InputNumber
  • InputDate
  • InputCheckbox
  • InputSelect

Example:

<InputText @bind-Value="model.Title" />
<InputTextArea @bind-Value="model.Content" />
<InputDate @bind-Value="model.PublishedAt" />
<InputCheckbox @bind-Value="model.IsPublished" />

These components integrate with Blazor validation.

Using plain HTML inputs is possible, but Blazor input components usually give you better validation integration.

Custom validation

Data annotations are useful, but sometimes you need custom validation.

Example:

  • checking if a slug is unique
  • validating a date range
  • checking business rules
  • validating against database state

For business validation, avoid putting everything directly in the component.

A better pattern is to call an application service:

var result = await BlogPostService.ValidateAsync(model);

Then display errors based on the result.

Simple UI validation can stay in the form model. Business validation usually belongs in the application layer.

EditContext

For more advanced scenarios, you can use EditContext.

private EditContext editContext = default!;

protected override void OnInitialized() { editContext = new EditContext(model); }

Then use it in the form:

<EditForm EditContext="@editContext" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />
</EditForm>

EditContext gives you more control over validation state, modified fields and form behavior.

For simple forms, Model is enough. For advanced forms, EditContext is useful.

Good form UX

Validation is not only about correctness. It is also about user experience.

A good form should:

  • clearly show required fields
  • show errors near the relevant input
  • avoid vague messages
  • disable submit while saving
  • show loading state
  • prevent duplicate submissions
  • preserve user input when possible
  • show success feedback after saving

Example:

<button type="submit" disabled="@isSaving">
    @(isSaving ? "Saving..." : "Save")
</button>

This small detail prevents double submission and gives the user feedback.

Separating form models from entities

A common mistake is binding forms directly to database entities.

For small demos, this works. For real applications, it can become risky.

Problems include:

  • exposing fields the user should not edit
  • accidentally modifying tracked EF Core entities
  • mixing UI validation with domain rules
  • making forms harder to maintain

Prefer dedicated form models or request DTOs.

Example:

public class CreateProductRequest
{
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
}

Then map the request to a domain entity in the application layer.

Common mistakes

Too much logic in the component

A form component should not contain all business rules, database checks and persistence logic.

Move those into services.

No loading state

When the user submits a form, show that something is happening.

No duplicate submit protection

Disable the submit button while saving.

Poor validation messages

Messages like "Invalid value" are not helpful. Be specific.

Binding directly to entities

Use form models or DTOs for better control.

Final thoughts

Blazor makes forms straightforward with EditForm, model binding and validation components.

The key is to keep forms structured. Use dedicated form models, apply data annotations where they make sense, show validation messages clearly and move business rules into services.

A good form is not just technically valid. It should also guide the user, prevent mistakes and keep your codebase clean.

When forms are designed well, your Blazor application becomes easier to use and easier to maintain.

Share:

Become a member

Get the latest news right in your inbox. It's free and you can unsubscribe at any time. We hate spam as much as we do, so we never spam!

Read next

Clean Architecture in Blazor Projects

Clean Architecture helps Blazor applications stay maintainable as they grow. This article explains how to separate UI, application logic, domain rules and infrastructure in a practical .NET project.

Admin 21-May-2026