Exercise 6: Form with Validation Using EditForm and Data Annotations

Blazor Exercise 6: Form with Validation Using EditForm and Data Annotations

Blazor Exercise 6: Form with Validation Using EditForm and Data Annotations

Awesome! You've built a solid foundation with Blazor components, communication, and data binding. Now, let’s dive into **form validation** in Blazor — a must-have feature for any robust business application. This exercise will guide you through creating a user registration form with built-in validation using Blazor's powerful EditForm and Data Annotations.

✅ Goal:

Build a user registration form with built-in validation using:

  • EditForm: The central component for Blazor forms.
  • DataAnnotationsValidator: To enable attribute-based validation.
  • ValidationSummary & ValidationMessage: To display validation errors.
  • Blazor's built-in input components: InputText, InputNumber, InputCheckbox.

๐Ÿงฉ Concepts Covered:

  • **Model-based validation** using C# Data Annotations attributes (e.g., [Required], [StringLength], [EmailAddress], [Range]).
  • Understanding the **EditForm lifecycle** and its OnValidSubmit and OnInvalidSubmit events.
  • How to use DataAnnotationsValidator to hook up your model's validation attributes.
  • Displaying a **summary of all validation errors** using ValidationSummary.
  • Displaying **per-field validation errors** using ValidationMessage.
  • Using Blazor's built-in Input* components for seamless form integration.

๐Ÿ”ง Steps:

Step 1: Create a model class UserRegistration.cs

Create a new C# class file named UserRegistration.cs. It's good practice to place model classes in a dedicated Models folder in your project. This class will define the structure of the data for our registration form and include Data Annotation attributes for validation rules.


<!-- Models/UserRegistration.cs -->
using System.ComponentModel.DataAnnotations;

public class UserRegistration
{
    [Required(ErrorMessage = "Name is required")]
    [StringLength(50, ErrorMessage = "Name can't exceed 50 characters")]
    public string Name { get; set; } = ""; // Initialize to prevent null reference warnings

    [Required(ErrorMessage = "Email is required")]
    [EmailAddress(ErrorMessage = "Invalid email format")]
    public string Email { get; set; } = ""; // Initialize to prevent null reference warnings

    [Range(18, 100, ErrorMessage = "Age must be between 18 and 100")]
    public int Age { get; set; } // int defaults to 0, which is outside range for age < 18

    [Required(ErrorMessage = "You must accept the terms")] // Required for boolean
    public bool AcceptTerms { get; set; } = false; // Initialize to false
}
        

Explanation of Data Annotations:

  • [Required]: Ensures the field cannot be empty.
  • [StringLength(50)]: Sets a maximum length for string fields.
  • [EmailAddress]: Validates that the input is a valid email format.
  • [Range(18, 100)]: Ensures a numerical value falls within a specified range.
  • ErrorMessage: Customizes the validation message displayed to the user.

Step 2: Create a Razor page named Register.razor

Create a new Razor page file named Register.razor in your Pages folder. This page will contain the EditForm and all the input and validation components.


<!-- Pages/Register.razor -->
@page "/register"
@using System.ComponentModel.DataAnnotations <!-- Required for Data Annotations -->
@using YourAppName.Models <!-- Replace YourAppName with your actual project name if UserRegistration is in a separate Models folder -->

<h3 class="heading3">Register</h3>

<EditForm Model="@user" OnValidSubmit="HandleValidSubmit" OnInvalidSubmit="HandleInvalidSubmit">
    <DataAnnotationsValidator /> <!-- Enables validation based on Data Annotations on the 'user' model -->
    <ValidationSummary class="validation-summary" /> <!-- Displays all validation errors in a list -->

    <div class="form-group">
        <label for="nameInput">Name:</label>
        <InputText id="nameInput" @bind-Value="user.Name" class="form-control" />
        <ValidationMessage For="@(() => user.Name)" class="validation-message" /> <!-- Shows error for Name field -->
    </div>

    <div class="form-group">
        <label for="emailInput">Email:</label>
        <InputText id="emailInput" @bind-Value="user.Email" class="form-control" />
        <ValidationMessage For="@(() => user.Email)" class="validation-message" /> <!-- Shows error for Email field -->
    </div>

    <div class="form-group">
        <label for="ageInput">Age:</label>
        <InputNumber id="ageInput" @bind-Value="user.Age" class="form-control" />
        <ValidationMessage For="@(() => user.Age)" class="validation-message" /> <!-- Shows error for Age field -->
    </div>

    <div class="form-group">
        <label>
            <InputCheckbox @bind-Value="user.AcceptTerms" />
            I accept the terms
        </label>
        <ValidationMessage For="@(() => user.AcceptTerms)" class="validation-message" /> <!-- Shows error for AcceptTerms -->
    </div>

    <button type="submit" class="blazor-button">Submit</button>
</EditForm>

@if (isSubmitted)
{
    <p style="color:green; margin-top: 1rem;">✅ Registration Successful for @user.Name!</p>
}

@code {
    // Create an instance of our UserRegistration model
    UserRegistration user = new();
    // Flag to indicate successful submission
    bool isSubmitted = false;

    // This method is called when the form is submitted AND all validation rules pass
    void HandleValidSubmit()
    {
        isSubmitted = true; // Set flag to show success message
        Console.WriteLine($"User Registered: Name: {user.Name}, Email: {user.Email}, Age: {user.Age}, Accepted Terms: {user.AcceptTerms}");
        // Here you would typically send the 'user' data to a backend API or save it.
    }

    // This method is called when the form is submitted AND there are validation errors
    void HandleInvalidSubmit()
    {
        isSubmitted = false; // Ensure success message is not shown
        Console.WriteLine("Form submission failed due to validation errors.");
        // You could add logging or more complex error handling here.
    }
}
        

Key points in Register.razor:

  • <EditForm Model="@user" ...>: Binds the form to our UserRegistration model. OnValidSubmit and OnInvalidSubmit are crucial event handlers.
  • <DataAnnotationsValidator />: This component is mandatory to make the Data Annotations on UserRegistration effective.
  • <ValidationSummary />: Displays a list of all validation errors that are currently active in the form.
  • <InputText />, <InputNumber />, <InputCheckbox />: Blazor's built-in input components that automatically integrate with EditForm and validation.
  • <ValidationMessage For="@(() => user.Name)" />: Shows the error message for a specific field. The lambda expression @(() => user.Name) provides a strong-typed way to link the validation message to the property.
  • HandleValidSubmit(): Executed only if the form data is valid according to the Data Annotations.
  • HandleInvalidSubmit(): Executed if the form data is invalid.

๐Ÿงช Try this:

  • Run your Blazor application.
  • Navigate to /register.
  • Try submitting the form with **empty values**. Observe the [Required] validation messages.
  • Enter an **invalid email format** (e.g., "test"). Observe the [EmailAddress] validation message.
  • Enter an **age less than 18** or greater than 100. Observe the [Range] validation message.
  • Try submitting without checking "I accept the terms". Observe the [Required] validation message for the boolean.
  • Finally, **fill all fields correctly** and click "Submit". Observe the success message and check your browser's console for the logged user details.

๐ŸŽฏ Expected Output:

You will see real-time validation feedback as you interact with the form.

  • **Empty submission:** A summary list of all errors will appear at the top, and individual error messages will appear below each invalid field.
  • **Invalid data:** Specific error messages (e.g., "Invalid email format", "Age must be between 18 and 100") will appear.
  • **Successful submission:** The validation messages will disappear, and a green success message "✅ Registration Successful for [Your Name]!" will appear below the form.

๐Ÿง  Bonus Challenges:

  • **Disable the Submit button:** Modify the "Submit" button to be disabled until the AcceptTerms checkbox is checked. (Hint: Use the disabled HTML attribute and bind it to user.AcceptTerms).
  • **Add Password & ConfirmPassword fields:**
    • Add Password and ConfirmPassword properties to your UserRegistration model.
    • Use [Required] and [StringLength] on the password.
    • Implement **custom validation** to ensure Password and ConfirmPassword match. (Hint: This might involve implementing IValidatableObject on your UserRegistration model or creating a custom validation attribute).
  • **Explore @bind alternatives:** For the InputText fields, try replacing @bind-Value="user.Name" with Value="@user.Name" ValueExpression="@(() => user.Name)" OnChange="@((args) => user.Name = args.Value.ToString())". This gives you finer control over when the value is updated and how.

✅ You’ve now implemented a full Blazor validation flow! This is a critical skill for building robust and user-friendly Blazor applications.

Raushan Ranjan

Microsoft Certified Trainer

.NET | Azure | Power Platform | WPF | Qt/QML Developer

Power BI Developer | Data Analyst

๐Ÿ“ž +91 82858 62455
๐ŸŒ raushanranjan.azurewebsites.net
๐Ÿ”— linkedin.com/in/raushanranjan

Comments

Popular posts from this blog

Blazor: Building Web Apps with C# - Introduction

Blazor WebAssembly Hosted App Tutorial: Envelope Tracker System

Securing MVC-based Applications Using Blazor