TryUpdateModel and IDataErrorInfo – Avoiding Exception-Based Validation

In the comments on my previous post, Eric doesn’t like the idea of using exception-based validation.


My focus in the previous post on IDataErrorInfo and MVC wasn’t so much on the raising of exceptions to signal a validation violation or broken rule, but mainly on the perceived poor experience I get with IDataErrorInfo and validation frameworks.


Certainly you can avoid the exceptions by using TryUpdateModel instead of UpdateModel. Of course this doesn’t return the validation errors / broken rules so depending on your needs you may need to do validation once again just as you did so many times in the IDataErrorInfo members when using a validation framework [Note: you may not need to retrieve those validation errors / broken rules again if IDataErrorInfo meets all your validation needs because it adds the errors to the form via AddModelError as mentioned before.]. I am not going to repeat all the previous code ( check the previous post ), but here is just the idea of using TryUpdateModel which avoids the exception…


 



var customer = new Customer();


 


if (TryUpdateModel<ICreateCustomerForm>(customer))


{


    // Validation Passed…


}


else


{


    // Validation Did Not Pass…


}


 


Hope that helps,


David Hayden


 

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

5 Responses to TryUpdateModel and IDataErrorInfo – Avoiding Exception-Based Validation

  1. Eric Hexter says:

    Thanks for the alternative method. I can concede that the TryUpdateModel is more to my liking , than the exception version thrown in the UpdateModel.

    As I consider the DefaultBinder using this implementation, I start to wonder if having that binder do the validation automatically leaves a little too much up to the framework? Someone new to the framework would have no idea that is happening.. although maybe that convention is good and the less code I have to write the better….

    I learned from the exchange… thank you.

  2. scottgu says:

    One other thing to note is that the IDataErrorInfo support is implemented using standard validation extensibility APIs added with the RC. So if you don’t like IDataErrorInfo and prefer a different validation extensibility point you can integrate that in as well.

    Thanks,

    Scott

  3. David Hayden says:

    Absolutely, Scott.

    It is the DefaultModelBinder that looks to see if the complex type being bound to implements IDataErrorInfo and therefore acts accordingly. So whether you use UpdateModel, TryUpdateModel, or use a complex type in the action parameters, DefaultModelBinder and therefore IDataErrorInfo will be engaged if implemented by the complex type.

  4. So, just curious – why not have a ref parameter to the Try…. method that can contain error messages and all that? Something similar to the TryParse(…) methods.

    I’ve always been a believer that you should not use Exceptions to control your business flow.

    Just a thought. :)

  5. scottgu says:

    One thing to note is that IDataErrorInfo can be used with both UpdateModel/TryUpdateModel and with passing parameters explicitly to an action method.  For example, if your Customer or CustomerForm ViewModel object implemented IDataErrorInfo and you passed it to the action method like this:

    public ActionResult Save(Customer customer) {

      if (ModelState.IsValid) {

          // there were no errors with IDataErrorInfo

      }

      // redisplay form since there was a binding error

      return View(customer);

    }

    The default model binder in ASP.NET MVC would have used IDataErrorInfo on customer for each property it set on the object it passed in, and populated the ModelState collection with errors if there were any.  This also allows you to avoid any exceptions being thrown.

    Hope this helps,

    Scott

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>