Lessons in this course (10)

6. Model binding and validation

Intermediate★ Must knowLesson 6 of 10

The DefaultModelBinder fills action parameters and complex objects from value providers: form fields, route data, query string, posted files — matching by name (including nested Address.City, indexed Lines[0].Qty).

csharp
public class ProductEditModel
{
    [Required, StringLength(200)]
    public string Name { get; set; }

    [Range(0.01, 1000000), DataType(DataType.Currency)]
    public decimal Price { get; set; }

    [Display(Name = "Category")]
    public int CategoryId { get; set; }

    [Remote("IsNameUnique", "Products", ErrorMessage = "Name already exists")]   // AJAX validation
    public string Code { get; set; }

    public IEnumerable<SelectListItem> Categories { get; set; }
}

// Custom validation attribute
public class FutureDateAttribute : ValidationAttribute
{
    public override bool IsValid(object value) => value is DateTime d && d > DateTime.Today;
}
  • ModelState.IsValid after binding; add your own errors with ModelState.AddModelError("Name", "...").
  • Unobtrusive client validation (jquery.validate + jquery.validate.unobtrusive) uses data-val-* attributes generated from the annotations — client validation is a convenience; server checks are mandatory.
  • IValidatableObject for cross-field rules; FluentValidation as an alternative library.
  • Over-posting/mass assignment: bind to view models (or [Bind(Include = "Name,Price")]) — never bind directly to EF entities with sensitive fields like IsAdmin.