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