CarTrackr contains various scenarios where form validation is performed. Let's have a look at one of these scenarios—creating a new Car
. The action method New
is defined in the CarController:
[AcceptVerbs("POST")] [ValidateAntiForgeryToken] public ActionResult New(FormCollection form) { Car car = new Car(); try { this.UpdateModel(car, new[] { "Make", "Model", "PurchasePrice", "LicensePlate", "FuelType", "Description" }); CarRepository.Add(car); return RedirectToAction("Details", new { licensePlate = car.LicensePlate }); } catch (RuleViolationException) { this.UpdateModelStateWithViolations(car, ViewData.ModelState); return View("New", car); } }
When creating a new Car
, the New
action method of the CarController
class creates a new Car
instance and tries to update this object with the data received from the posted form, by using the UpdateModel
method. Immediately after that, the CarRepository
is instructed to add the car instance and save it to the database. Note that this method will call the EnsureValid
method that is defined on the Car class. The EnsureValid
method checks whether there are any violations in the car instance, and throws a RuleViolationException
if any errors are present.
public void EnsureValid() { List<RuleViolation> issues = GetRuleViolations(); if (issues.Count != 0) throw new RuleViolationException("Business Rule Violations", issues); }
The GetRuleViolations
method performs various checks on the car instance. Whenever a check fails, a new RuleViolation
is added to a list of violations. The RuleViolation
object holds the property name, the provided value and an error message.
public List<RuleViolation> GetRuleViolations() { List<RuleViolation> validationIssues = new List<RuleViolation>(); if (string.IsNullOrEmpty(Make)) validationIssues.Add(new RuleViolation("Make", Make, "Make should be specified!")); if (string.IsNullOrEmpty(Model)) validationIssues.Add(new RuleViolation("Model", Model, "Model should be specified!")); if (PurchasePrice <= 0) validationIssues.Add(new RuleViolation("PurchasePrice", PurchasePrice, "Purchase price should be specified!")); if (string.IsNullOrEmpty(LicensePlate)) validationIssues.Add(new RuleViolation("LicensePlate", LicensePlate, "License plate should be specified!")); return validationIssues; }
When the New
action method of CarController
catches a RuleViolationException
, it calls the UpdateModelStateWithViolations
method (and provides the car being added) and the ViewData ModelState
dictionary. The UpdateModelStateWithViolations
method copies all of the rule violations from the RuleViolationException
into the ViewData ModelState
dictionary. Afterwards, the CarController
renders the view again, which will now display any validation issues:
Error messages in the view are displayed using ASP.NET MVC's HtmlHelper.ValidationMessage
form helper, which we explained in Chapter 4, Components in the ASP.NET MVC Framework.