Section 4 of 5

Forms and Validation

🎯 What You'll Learn

  • Creating forms
  • Model binding
  • Data annotations
  • Validation
  • Anti-forgery tokens

Creating Forms

Basic Form HTML
@page
@model CreateModel

<form method="post">
    <input asp-for="Product.Name" />
    <button type="submit">Create</button>
</form>

Data Annotations

Product Model with Validation C#
public class Product
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Name is required")]
    [StringLength(100)]
    public string Name { get; set; } = string.Empty;

    [Required]
    [Range(0.01, 10000)]
    public decimal Price { get; set; }

    [Range(0, 1000)]
    public int Quantity { get; set; }
}

Validation in PageModel

Check ModelState C#
public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page(); // Re-render with errors
    }

    _context.Products.Add(Product);
    await _context.SaveChangesAsync();

    return RedirectToPage("Index");
}

Display Validation Errors

Validation Tag Helpers HTML
<form method="post">
    <!-- Validation summary -->
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    <div>
        <label asp-for="Product.Name"></label>
        <input asp-for="Product.Name" />
        <span asp-validation-for="Product.Name" class="text-danger"></span>
    </div>

    <button type="submit">Submit</button>
</form>

@section Scripts {
    @await Html.PartialAsync("_ValidationScriptsPartial")
}

Complete InvenTrack Example

Pages/Products/Create.cshtml.cs C#
public class CreateModel : PageModel
{
    private readonly InvenTrackDbContext _context;

    public CreateModel(InvenTrackDbContext context) => _context = context;

    [BindProperty]
    public Product Product { get; set; } = new();

    public IActionResult OnGet() => Page();

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
            return Page();

        _context.Products.Add(Product);
        await _context.SaveChangesAsync();

        TempData["Success"] = "Product created!";
        return RedirectToPage("Index");
    }
}
Pages/Products/Create.cshtml HTML
@page
@model CreateModel

<h1>Create Product</h1>

<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    <div class="mb-3">
        <label asp-for="Product.Name" class="form-label"></label>
        <input asp-for="Product.Name" class="form-control" />
        <span asp-validation-for="Product.Name" class="text-danger"></span>
    </div>

    <div class="mb-3">
        <label asp-for="Product.Price" class="form-label"></label>
        <input asp-for="Product.Price" class="form-control" />
        <span asp-validation-for="Product.Price" class="text-danger"></span>
    </div>

    <div class="mb-3">
        <label asp-for="Product.Quantity" class="form-label"></label>
        <input asp-for="Product.Quantity" class="form-control" />
        <span asp-validation-for="Product.Quantity" class="text-danger"></span>
    </div>

    <button type="submit" class="btn btn-primary">Create</button>
    <a asp-page="Index" class="btn btn-secondary">Cancel</a>
</form>

@section Scripts {
    @await Html.PartialAsync("_ValidationScriptsPartial")
}

Key Takeaways

  • Data annotations: [Required], [Range], [StringLength]
  • ModelState.IsValid: Check validation
  • asp-validation-for: Display field errors
  • asp-validation-summary: Display all errors
  • Anti-forgery: Automatic with <form>
  • Client validation: _ValidationScriptsPartial