Friday, April 22, 2011

Model binder? I hardly even know her!

The biggest stumbling block I've encountered, so far, was regarding incoming model validation.  Like a good boy, I was (and still am) using Entity Framework 4 for my ORM needs.  Following the examples in the various tutorials I found, my HttpPost method was binding its data straight onto an EF4 entity.  The entity was simple, so simple that I didn't use a view model.  It had a total of four properties, two of which didn't need to be handled by the form (its ID and its LastModified DateTime, which I was originally going to supply in the controller).  I was attempting to test MVC's form validation with Data Annotations when the problem came up - I was getting a ConstraintException from the bowels of EF4.

The exception itself was easy to decipher.  My backing db columns were all set to 'NOT NULL', which was done purposely (I want all articles to have titles, and an article cannot exist without an ID or text.  LastModified is for my own book keeping).  What was odd to me, at the time, was that EF4's entity validation was firing before I even attempted to call SaveChanges().  This validation was triggered right when MVC attempted to bind the incoming form data to an entity.  Since some of the values were purposely empty, they were received as null values, and that, in turn, violated the contract between entity and db.

For a look at the particulars, go here: http://stackoverflow.com/questions/4703085/entity-framework-4-w-mvc-2-fighting-against-ef4s-inability-to-allow-empty-str

This drove me nuts.  Nothing was mentioned about EF4 validation being triggered by MVC model binding.  I scoured over the MVC Music Store demo, and, at the time, there was no mention of it.  I asked Julie Lerman through Twitter, where she was more than gracious with her time and effort, but we couldn't figure out the problem.  I found a workaround on Stack Overflow - there's a Data Annotation attribute which does the trick: [DisplayFormat(ConvertEmptyStringToNull = false].  It worked, but it felt sloppy.  It also didn't address why this was happening.

I eventually found something of an answer here: http://mvcmusicstore.codeplex.com/workitem/6604  The problem for me was that I couldn't step through the error as Jon Galloway claimed.  I'd get the ConstraintException, then a YSOD.  In fact, the YSOD was what alerted me to the error.

I'm still wondering why validation would/should care whether or not an entity in memory has null properties, especially when that entity is not attached to an ObjectContext.  Shouldn't that kind of exception only be raised when one attempts to store the entity back in the db after it's been (re)attached to the ObjectContext?  Seems a bit restrictive to me.

So, the workaround works, but I'm going to change over to custom edit models for incoming data, then transfer that data to an entity.  It will allow me to apply Data Annotations for simple UI layer validation without forcing me to add it to my domain layer entities.  I also don't like relying on the [DisplayFormat] attribute in general.  It has a bad code smell to me.

No comments:

Post a Comment