Getting ASP.NET MVC to do the dirty work

Hey, whaddaya know! I have some actual feedback to give on something in the form of "boy, I wish the product could do X". Who knew I had evaluation skillz?

The product is ASP.NET MVC and I’m implementing some pretty standard functionality: Get the data from the user and save it in the database. For this post, we’ll call the object being saved a Critter.

One of the properties on a Critter is Species and its value is selected from a dropdown list. This is not such a far cry from Scott Guthrie’s equally descriptive Product/Category example which is an okay example if you’re looking only for education and not entertainment.

Like Scott’s version, I’m passing what amounts to a DTO as the ViewData. The DTO includes a list of Species to select from as well as the actual Critter object. You fill in the name of the critter, select your species, and click Save and watch the magic happen in the form of saving the Critter to the database.

Now, according to the tutorial, there are two ways to create your Critter object in the Create action. The first way is to specify a method parameter for each property. For example:

[ControllerAction]
public void Create( string CritterName, int SpeciesID )
{
    Critter critter = new Critter( );
    critter.Name = CritterName;
    critter.SpeciesID = SpeciesID;
    // Do "stuff" with the critter
}

The second way is shorter and possibly cleaner:

[ControllerAction]
public void Create( )
{
    Critter critter = new Critter( );
    critter.UpdateFrom( Request.Form );
    // Do "stuff" with the critter
}

This one is kinda cool if a little too magic. Updating from a NameValueCollection sounds like it might be fragile but they seem to have a good collective head on their shoulders so that might not be a concern.

Here’s where my wish list comes in. Neither of these methods are how I would code the thing if I were doing it in, say, a Windows app. Ideally, I’d like to be able to do this:

[ControllerAction]
public void Create( ICritter critter )
{
    // Do "stuff" with the critter
}

That is, I’d like the framework to create my critter for me. It can do this for primitive types but not so much with objects. Admittedly, this is probably a tall order without getting back into a ViewState state of being but a hillbilly can dream, can’t he?

Kyle the Utopian

This entry was posted in Featured. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://coloradobeach.yolasite.com/ FritzHester

     I just stumbled upon your site and wanted to say that I have really
    enjoyed reading your blog posts. Any way I’ll be subscribing to your
    feed and I hope you post again soon.

  • http://codeprairie.net/blogs/chrisortman Chris Ortman

    @Ben: If you are using ActiveRecord + MonoRail you can do an update using the ARDataBind attribute. It will look for the PrimaryKey, fetch the object from the database and then do the update.

  • http://www.flux88.com Ben Scheirman

    After looking at Monorails documentation on this, I don’t see this being used in an “Update” action, only create. Do you think that the convention I proposed is worthwhile?

  • Kyle Baley

    @Ben: It very much is based on heavy use of convention. Reviewing the Castle documentation on how they handle this, you need to make sure your HTML elements are named appropriately. And that includes handling complex object graphs. Changing property names will wreak much havoc, especially since things like ReSharper’s rename (and probably even Visual Studio’s built-in one) won’t change these in your HTML files.

    But I’m good with that. I’m not big on arguments that amount to which tradeoff you’re willing to live with. In this case, I’m having to change the design I want to use. If the other option was available, I’d use it and take the chance that maaaaybe I’d rename the Age property to Ripeness at a later date and have some work to do.

  • http://www.flux88.com Ben Scheirman

    Isn’t that part of MVCToolkit Justice?

    @Kyle: that’s a killer feature and it’s definitely attainable. One thing you might need to consider is that often times we are updating a record, so the critter that comes in must have already been fetched from the repository and the properties set on top of that.

    This might work if your IController implementation could look in the IoC container for a IRepository (where ICritter is the type of the parameter) and then fetch it using the id from the request collection.

    While that seems very cool and magic, I’m worried that it is way too much convention. The minute you deviate from the norm it becomes cloudy.

  • http://graysmatter.codivation.com Justice~!

    I didn’t realize you had access to UpdateFrom(Request.Form). Honestly, I’ve looked for it but cant seem to call it! What am I missing?

  • http://www.kenegozi.com/blog Ken Egozi

    Im actually quite surprised that the ASP.NET MVC / MvcContrib didn’t come up yet with the equivalent to MonoRail’s SmartDispatcherController stuff. I wish I had some free time to do so.

  • http://www.bluespire.com/blogs Rob

    I have to chime in and say that the way Monorail supports this is sweet. It just makes web development a pleasure. It would be a major thumbs down if they didn’t support something similar in ASP.NET MVC. Perhaps we’ll see more stuff like this in the next release.

  • http://codebetter.com/blogs/kyle.baley Kyle Baley

    @shawn

    Oh good, I was told that Monorail supported this and was hoping would chime in with the info so I didn’t need to find it myself. And after looking through it, it does look familiar from the brief period when I looked at Monorail.

    It’s kinda funky doing it by specifying an attribute on the method parameter. Still not as clean as having it done for you. But it’s closer to what I want than the ASP.NET MVC mechanism. At least the code will look nicer in the tests.

  • shawn

    I don’t know if you’ve seen this, but what do you think about how MonoRail solves the problem?

    http://www.castleproject.org/monorail/documentation/v1rc2/usersguide/smartcontroller.html

  • http://blogs.veloc-it.com/pat Pat Gannon

    That does seem like a desirable feature. It seems like that would be possible if you could configure the MVC framework to know how to hook into your DI container… It seems like Windsor/StructureMap/Unity should be able to instantiate “complex” arguments if the MVC Framework knew how to talk to it before calling a controller method.