154

On the NerdDinner example of Professional ASP.NET MVC 1.0 there's a method to create a new dinner as copied bellow (page 89 of the free NerdDinner version).

There it checks ModelState.IsValid for true. It seems to check if the model is valid for the database (that is, it catches data type conversions, like dates with invalid format, but not business rules). Is that true?

When submitting the form, if you have an error in the date, ModelState.IsValid will be false and you'll get back an error, but only for the date because AddRuleViolations was never executed. If you remove the check for ModelState.IsValid completely, then you'll get all the errors (due to the exception), including a marking in the date when it is invalid. Then, why is the check for ModelState.IsValid there at all? Am I missing something?

// 
// POST: /Dinners/Create 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create(Dinner dinner) {
    if (ModelState.IsValid) {
        try {
            dinner.HostedBy = "SomeUser"; 

            dinnerRepository.Add(dinner);
            dinnerRepository.Save();

            return RedirectToAction("Details", new {id = dinner.DinnerID }); 
        } catch {
            ModelState.AddRuleViolations(dinner.GetRuleViolations());
        } 
    } 
    return View(dinner); 
} 
Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622

4 Answers4

154

ModelState.IsValid tells you if any model errors have been added to ModelState.

The default model binder will add some errors for basic type conversion issues (for example, passing a non-number for something which is an "int"). You can populate ModelState more fully based on whatever validation system you're using.

The sample DataAnnotations model binder will fill model state with validation errors taken from the DataAnnotations attributes on your model.

Liam
  • 27,717
  • 28
  • 128
  • 190
Brad Wilson
  • 67,914
  • 9
  • 74
  • 83
  • Brad is there any way to find out if a Model that is decorated with DataAnnotations "IsValid" without ModelState. (Say for example the Object is loaded from a file or used in a Console App etc.) – runxc1 Bret Ferrier May 10 '11 at 03:53
  • 1
    No, ModelState.IsValid is the only way to know whether there were any validation (or data conversion) errors during model binding. – Brad Wilson May 16 '11 at 04:51
  • @Brad, when you say "You can populate ModelState more fully based on whatever validation system you're using", how is that accomplished? Is there a way to crack-open my ModelState validation code for my ViewModel? I'm using EF4, so most of my validation is automatic out-of-the-box. – WEFX Aug 16 '11 at 20:46
  • 15
    Use: `var errors = ModelState.Values.SelectMany(v => v.Errors);` with a break point to view any validation issues. – full_prog_full Dec 10 '15 at 13:07
  • Sometimes its an error in the related table if property names have been changed, migrations have not been performed and as a result the SaveChanges(); fails and cannot occur due to the change. – Oracular Man Feb 25 '18 at 18:46
26

From the Errata: ModelState.AddRuleViolations(dinner.GetRuleViolations());

Should be:

ModelState.AddModelErrors(dinner.GetRuleViolations());

Reference: http://www.wrox.com/WileyCDA/WroxTitle/Professional-ASP-NET-MVC-1-0.productCd-0470384611,descCd-ERRATA.html

Jared
  • 5,840
  • 5
  • 49
  • 83
Kelly Orr
  • 751
  • 8
  • 17
1

All the model fields which have definite types, those should be validated when returned to Controller. If any of the model fields are not matching with their defined type, then ModelState.IsValid will return false. Because, These errors will be added in ModelState.

B.Khan
  • 11
  • 2
0

Yes , Jared and Kelly Orr are right. I use the following code like in edit exception.

foreach (var issue in dinner.GetRuleViolations())
{
    ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}

in stead of

ModelState.AddRuleViolations(dinner.GetRuleViolations());
ndmeiri
  • 4,979
  • 12
  • 37
  • 45