ModelState.IsValid is the decision point after ASP.NET Core MVC binds request data and checks validation constraints. ModelState, available on Controller and ControllerBase, holds the results. When IsValid is false, the action can avoid saving invalid data and return errors instead. section 3.2.9 section 19.5.4
Choose the response that fits the action:
- For a form POST, save the bound object and show a confirmation only when IsValid is true. Otherwise, return the form view; Razor validation tag helpers can display the errors held in ModelState. section 3.2.9
- For an API POST, store the object and return Ok only when IsValid is true. Otherwise, return BadRequest(ModelState), giving the client a 400 response and validation-error details. section 19.5.4
A checkout rule beyond data annotations
An order can have valid shipping details and still be impossible to process because the cart is empty. Add that error with ModelState.AddModelError before checking IsValid. The same gate then prevents checkout for either kind of problem. In a controller unit test, add a model error explicitly to exercise the invalid branch, then verify that the order was not saved and the form view was returned. section 9.3.5
Explicit property checks can join that gate too. Check a property's validation state before testing its value: a request value that could not be converted should not be treated as a usable number. AddModelError records failures such as a nonpositive price or an ID absent from the database; IsValid then reflects both existing and explicitly added errors. section 29.3.3
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));
}
}
}
The POST RsvpForm action shows the core pattern: store and thank the guest on success, or redisplay the form on failure. section 3.2.9
