Validation checks whether request data meets an application’s requirements before that data is used or stored. A missing value, an unusable price, or an invalid relationship can cause immediate errors or quietly leave bad data in a database. Rejecting the data is only half the job: the user also needs enough feedback to correct it. section 29.0 section 29.2
For an ASP.NET Core controller that accepts a form:
- Put rules on model properties using attributes from System.ComponentModel.DataAnnotations. [Required] demands a value; [EmailAddress] checks an email address; [Range] sets numeric limits. Rules on a model can be reused by forms that bind to it. section 3.2.9 section 19.5.4
- Let model binding populate the object and check ModelState.IsValid in the receiving action. Process valid data; return the form when validation fails. ModelState retains error details for the response. section 3.2.9 section 29.3
- Show the errors. A form can use asp-validation-summary="All"; validation tag helpers can also mark invalid inputs with input-validation-error for CSS styling. Returning the same view preserves the validation context. section 3.2.9 section 29.3
An unanswered RSVP is not a “no”
An attendance choice uses bool? rather than bool. If the visitor makes no selection, model binding leaves it null and [Required] reports an error. A non-nullable bool could only be true or false, obscuring whether a choice was made. The POST action adds a valid response and shows a thank-you view; otherwise, it redisplays the form. section 3.2.9
Listing 3.17 Applying validation in the GuestResponse.cs file in the Models folder
using System.ComponentModel.DataAnnotations;
namespace PartyInvites.Models {
public class GuestResponse {
[Required(ErrorMessage = "Please enter your name")]
public string? Name { get; set; }
[Required(ErrorMessage = "Please enter your email address")]
[EmailAddress]
public string? Email { get; set; }
[Required(ErrorMessage = "Please enter your phone number")]
public string? Phone { get; set; }
[Required(ErrorMessage = "Please specify whether you'll attend")]
public bool? WillAttend { get; set; }
}
}
See the model properties, their validation attributes, and the nullable attendance choice together. section 3.2.9
Listing 3.18 Checking for errors in the HomeController.cs file in the Controllers folder
using Microsoft.AspNetCore.Mvc;
using PartyInvites.Models;
namespace PartyInvites.Controllers {
public class HomeController : Controller {
public IActionResult Index() {
return View();
}
[HttpGet]
public ViewResult RsvpForm() {
return View();
}
[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse) {
if (ModelState.IsValid) {
Repository.AddResponse(guestResponse);
return View("Thanks", guestResponse);
} else {
return View();
}
}
public ViewResult ListResponses() {
return View(Repository.Responses
.Where(r => r.WillAttend == true));
}
}
}
Follow the POST action’s ModelState.IsValid branch from accepted response to error redisplay. section 3.2.9
A REST endpoint needs a different error response. A product POST checks ModelState before saving: valid data produces Ok; invalid data produces BadRequest(ModelState) and HTTP 400. [Range] is useful for numeric properties that would otherwise default to zero when the request omits them. Do not assume every client can interpret the error body; there is no standard error description format here. section 19.5.4
Validation also belongs in database-backed create forms: bind the submitted object, check it, and save only acceptable data. If the editor view expects a different view-model type, rebuild that view model with the submitted data before redisplaying it. Basic checks during model binding can be supplemented with explicit custom validation; client-side and remote validation offer feedback before or alongside a server submission. section 31.2.3 section 29.8





























