6 Tips for ASP.NET MVC Model Binding

Monday, April 27, 2009 by K. Scott Allen
19 comments

Model binding in the ASP.NET MVC framework is simple. Your action methods need data, and the incoming HTTP request carries the data you need. The catch is that the data is embedded into POST-ed form values, and possibly the URL itself. Enter the DefaultModelBinder, which can magically convert form values and route data into objects. Model binders allow your controller code to remain cleanly separated from the dirtiness of interrogating the request and its associated environment.

 magic default model binder 

Here are some tips on how to take advantage of model binding in your MVC projects.

Tip #1: Prefer Binding Over Request.Form

If you are writing your actions like this ..

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create()
{
    Recipe recipe = new Recipe();
    recipe.Name = Request.Form["Name"];
    
    // ...
    
    return View();
}

.. then you are doing it all wrong. The model binder can save you from using the Request and HttpContext properties – those properties make the action harder to read and harder to test. One step up would be to use a FormCollection parameter instead:

public ActionResult Create(FormCollection values)
{
    Recipe recipe = new Recipe();
    recipe.Name = values["Name"];      
            
    // ...
            
    return View();
}

With the FormCollection you don’t have to dig into the Request object, and sometimes you need this low level of control. But, if all of your data is in Request.Form, route data, or the URL query string, then you can let model binding work its magic:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Recipe newRecipe)
{            
    // ...
    
    return View();
}

In this example, the model binder will create your newRecipe object and populate it with data it finds in the request (by matching up data with the recipe’s property names). It’s pure auto-magic. There are many ways to customize the binding process with “white lists”, “black lists”, prefixes, and marker interfaces. For more control over when the binding takes place you can use the  UpdateModel and TryUpdateModel methods. Just beware of unintentional binding – see Justin Etheredge’s Think Before You Bind.

Tip #2: Custom model binders

Model binding is also one of the extensibility points in the MVC framework. If you can’t use the default binding behavior you can provide your own model binders, and mix and match binders. To implement a custom model binder you need to implement the IModelBinder interface. There is only method involved - how hard can it be?

public interface IModelBinder
{
    object BindModel(ControllerContext controllerContext, 
ModelBindingContext bindingContext); }

Once you get neck deep into model binding, however, you’ll discover that the simple IModelBinder interface doesn’t fully describe all the implicit contracts and side-effects inside the framework.  If you take a step back and look at the bigger picture you’ll see that model binding is but one move in a carefully orchestrated dance between the model binder, the ModelState, and the HtmlHelpers. You can pick up on some of these implicit behaviors by reading the unit tests for the default model binder.

Scott Hanselman demonstrates a non-trivial model binder in his post “Splitting DateTime – Unit Testing ASP.NET MVC Custom Model Binders”. One detail I want to call out about Scott’s DateTime splitter is how you still don’t need to use Request.Form when building the model. Inside the GetA<T> method you’ll see how Scott uses the binding context’s ValueProvider property to fetch data. The ValueProvider represents an amalgamation of all data from the request’s posted form values, routing data, and query string. Scott’s example is great, but it is missing one detail – the propagation of binding errors.

If the default model binder has problems putting data into your object, it will place the error messages and the erroneous data value into ModelState. You can check ModelState.IsValid to see if binding problems are present, and use ModelState.AddModelError to inject your own error messages. See this very simple tutorial for more information on how ModelState and HtmlHelpers can work together to present validation errors to the user. 

If you scroll down the comments to Scott’s post you’ll see Sebastien Crocquesel’s patch for Scott’s code. If a conversion fails, Sebastien’s code will use ModelState.AddModelError to propagate the error. Both the controller action and the view can look in ModelState to see if there was a binding problem. The controller would need to check ModelState for errors before saving stuff into the database, while the view can check ModelState for errors to give the user validation feedback. One important note is that the HtmlHelpers you use in a view will require ModelState to hold both a value (via ModelState.SetModelValue) and the error (via AddModelError) or you’ll have runtime errors (null reference exceptions). The following code can demonstrate the problem:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection Form)
{
    // this is the wrong approach ...
    if (Form["Name"].Trim().Length == 0)
        ModelState.AddModelError("Name", "Name is required");

    return View();
}

The above code creates a model error without ever setting a model value. It has other problems, too, but it will create exceptions if you render the following view.

<%= Html.TextBox("Name", Model.Name) %>
Even though you’ve specified Model.Name as the value for the textbox, the textbox helper will see the model error and attempt to display the “attempted value” that the user tried to put in the model. If you didn’t set the model value in model state you’ll see a null reference exception.

Tip #3: Custom Model Binding via Inheritance

If you’ve decided to implement a custom model binder, you might be able to cut down on the amount of work required by inheriting from DefaultModelBinder and adding some custom logic. In fact, this should be your default plan until you are certain you can’t subclass the default binder to achieve the functionality you need. For example, suppose you just want to have some control over the creation of your model object. The DefaultModelBinder will create object’s using Activator.CreateInstance and the model’s default constructor. If you don’t have a default constructor for your model, you can subclass the DefaultModelBinder and override the CreateModel method.

Jimmy Bogard has an example of sub classing the DefaultModelBinder in his post titled “A Better Model Binder”.

Tip #4: Using Data Annotations for Validation

Brad Wilson explains everything beautifully in this post: DataAnnotations and ASP.NET MVC.

I encourage you to go read Brad’s post, but if you are in a hurry, here is a summary:

.NET 3.5 SP1 shipped a System.ComponentModel.DataAnnotations assembly that looks to play a central role as we move forward with the .NET framework. By using data annotations and the DataAnnotationsModelBinder, you can take care of most of your server-side validation by simply decorating your model with attributes.

public class Recipe
{
    [Required(ErrorMessage="We need a name for this dish.")]
    [RegularExpression("^Bacon")] 
    public string Name { get; set; }

    // ...
}

The DataAnnotationsModelBinder is also a great sample to read and understand how to effectively subclass the default model binder.

Tip #5 : Recognize Binding and Validation As Two Phases

Binding is about taking data from the environment and shoving it into the model, while validation is checking the model to make sure it meets our expectations. These are different different operations, but model binding tends to blur the distinction. If you want to perform validation and binding together in a model binder, you can – it’s exactly what the DataAnnotationsModelBinder will do. You can also find samples like Automatic Model Validation with ASP.NET MVC, xVal, Castle, and a Custom Binder (John McDowall), and Enterprise Library Validation Application Block with MVC Binders (Steve Michelotti).  However, one thing that is often overlooked is how the DefaultModelBinder itself separates the binding and validation phases. If all you need is simple property validation, then all you need to do is override the OnPropertyValidating method of the DefaultModelBinder.

 

Tip #6: Binders Are About The Environment

Earlier I said that “model binders allow your controller code to remain cleanly separated from the dirtiness of interrogating the request and its associated environment”. Generally, when we think of binder we think of moving data from the routing data and posted form values into the model. However, there is no restriction of where you find data for your model. The context of a web request is rich with information about the client. A good example is another Scott Hanselman post on automatically binding the user’s identity into a model see: IPrincipal (User) ModelBinder in ASP.NET MVC for easier testing.

In Conclusion

Model binding is beautiful magic, so take advantage of the built-in magic when you can. I think the topic of model binding could use it’s own dedicated web site. It would be a very boring web site with lots of boring code, but model binding has many subtleties. For instance, we never even got to the topic of culture in this post.

Do you have any model binding tips?

Life and Times of an ASP.NET MVC Controller

Thursday, April 23, 2009 by scott
1 comment

The May issue of MSDN Magazine is now on-line with my article “The Life and Times of an ASP.NET MVC Controller”.

In this article, I will dissect the ASP.NET MVC framework and look at how controllers work. I'll explain how the framework interacts with your controllers and how you can influence those interactions. I'll look at controller factories, controller actions, action filters, and action results as well.

I don’t like programming by coincidence, and I hope this article gives you everything you need to work confidently with MVC controllers. In addition to the technical details, I also believe you have to properly apply a technology to make great software – thus the next installment of Extreme ASP.NET in July will cover some guiding principles to keep in mind when developing applications with the ASP.NET MVC framework.

Looking even further down the road (September seems so far away), I’m not sure what I’ll dig into next. Will it be web forms? More ASP.NET MVC? If there is something you want to hear about that is related to the ASP.NET server-side runtime - drop me a line or leave a comment.

ASP.NET MVC Controls and Good versus Evil

Thursday, April 9, 2009 by scott
23 comments

Good Unicorn versus Evil UnicornLuis and David recently posted about the controls that appear in the ASP.NET MVC Futures 1.0 release.

I’ve seen some discussions where people positively erupt at any mention of the word “control” in an MVC setting. These are the people who consider ASP.NET Web Forms as the ultimate source of evil in the universe – a cross between a Sith lord and a velociraptor. The idea of introducing controls, with un-testable event handling code and giant gobs of view state, is a travesty that will corrupt the minds of all developers before devouring their children. They must be stopped.  

The Case For Controls

Let’s take the simple scenario of rendering a text input in the browser. If you are using the ASP.NET MVC framework release with no additional libraries, you’ll be looking to use one of the 4 Html helper TextBox methods (excerpted for space below):

string TextBox(... string name);
string TextBox(... string name, object value);
string TextBox(... string name, object value, IDictionary<string, object> htmlAttributes);
string TextBox(... string name, object value, object htmlAttributes);

A text input is a pretty trivial control, but even these 4 options don’t give you a clean path to the entire universe of things you might want to do when displaying a value in a text input, like specifying a formatting string to use when converting the model value to a string. One solution is to write additional helper methods, or include an additional library with the methods already written, but you are only adding to the number of method overloads a developer has to parse when they just want to display a simple text input. In the end, you’ll still be looking at code similar to the following…

<%= Html.TextBox("ReleaseDate",
                 String.Format("{0:d}", Model.ReleaseDate),
                 new { @class = "special" })%>

…versus the declarative syntax of the MVC futures TextBox control…

<mvc:TextBox Name="ReleaseDate" Format="{0:d}"
             class="special" runat="server" />

Note that the MVC control does not inject view state into the rendered output, but that’s not to say that the MVC controls don’t have some issues. One issue is that they still inherit properties, behaviors, and events from System.Web.UI.Control, and some of those inherited features don’t make sense in an MVC view.

I think I'm still happier using Html helpers.

Here are some advantages I see to using controls:

  • The declarative model is easier to scan because the named properties are explicit, whereas with HtmlHelpers the order of the unnamed parameters is important.
  • It’s easier to add extensibility via additional properties instead of adding yet another extension method overload.
  • The logic for a custom control is encapsulated in a class, with all of the benefits of using a class, whereas the entry point for an HtmlHelper is just a method.
  • Controls would probably be the preferred way to work for designers (of the human variety).
  • Controls would probably open up more opportunities for vendors to ship functionality.

And the disadvantages:

  • They remove the benefit of strongly typing the model, which is a huge loss.
  • Someone under the influence of the dark side can wire up event handlers.
  • It’s possible to build controls that are too smart for their own good (or for the view’s good).
  • Nobody knows what HTML might appear when the control renders (which, to be fair, is also true of 3rd party Html helpers).

 

It’s also worth pointing out that there are other solutions, besides controls, to the often clumsy Html helpers. By sticking to view-specific models, conventions, and effective CSS with JavaScript, you can remove many of the concerns that the HtmlHelpers burden themselves with. Using a view engine other than the web forms view engine can also solve some of these issues.

What do you think?

Will MVC controls be the spawn of Satan, or the blessing of a saint?

MVC Course is Coming Online!

Tuesday, April 7, 2009 by scott
0 comments

Just a quick note to let you know that the first three modules of my ASP.NET MVC course are ready for consumption at Pluralsight! On-Demand. Pluralsight is building a fantastic library of online content you can view as a subscriber, or see in person via instructor led training at a classroom or on-site at your place.

There is also a heap of free screencasts and previews to wet your appetite.

A single subscription can get you access to training for WPF, C#, .NET, ASP.NET, AJAX, WF, WCF, Silverlight, BizTalk, with more on the way.

P.S. I’ve heard the LINQ class is awesome, too…

Putting the M in MVC – Part III

Monday, April 6, 2009 by scott
6 comments

In the last post we talked about using entities as the models in an MVC application. This approach works well until an application reaches a certain level of complexity, at which point entities as the M in MVC can become painful.

I believe entities exist to serve the business layer. They also have a role in the data access layer, but only because the data access layer has to be acutely aware of entities. The reverse is not true – entities don’t need to know details about the data access layer nor how they are saved in persistent storage. Entities aren’t owned by the UI, or the data access layer. Entities are business objects and are owned by the business layer.

An application that supports a complex business needs a fine-tuned layer of business logic. You know an application is growing in complexity when you uncover scenarios like these:

  • Validation rules go beyond mere database constraints - maximum discount is 10% unless an administrator is overriding the discount percentage
  • Multiple sets of validation policies are in effect - contracts signed in the state of Maryland after Jan 1, 2009 require additional checks to meet regional law #443570.
  • Entities are involved in long running business processes - the request for proposal requires approval from three directors before moving to a published state.
  • The application integrates with external applications and services - changes to any customer information must be published to the CRM system within 10 minutes.

These types of requirements have a significant impact on the design and behavior of the business layer and its entities. You want all this complicated business stuff in a layer where it is testable, maintainable, and free from the influence of all the infrastructure that surrounds it – databases, data grids, message queues, communication protocols, and the technology du jour. It’s a business layer built with business objects that encapsulate business state and business behavior. It’s the secret sauce that makes money for your company. It’s a rich model of your domain.

So - why wouldn’t we want to use this rich domain model inside of our views? Isn’t it every young view’s dream to grow up and marry an extraordinarily rich, fat model?

Models, Models Everywhere

Views can grow complex just as quickly as business logic can grow complex. Complex views might exhibit some of the following conditions.

  • Displays aggregate information from across the application (reporting views).
  • Displays information from disparate sources (composite views).
  • Lives on a different tier (the view is built using JavaScript, JSON, and client-side data binding).

Perhaps you don’t consider these views as super-complex because you build them all the time, but the types of views we are talking about in the above three bullet points do place requirements and constraints on the model. For example, the UI may require a model that can serialize into a JSON or RSS format.

If you share your entities or domain model with the UI layer, you’ll find your business objects have to serve two masters. The requirements from these two masters will pull your business objects in different directions, and they won’t be optimized to fit in either role.

Also, ask yourself these questions about the model for your views:

  1. Who determines what properties the model should have?
  2. Who invokes business logic on the the model?
  3. Who owns the model?

Answers:

  1. The view.
  2. Not the view.
  3. The view.

Complex applications often require multiple models. There is the domain model that encapsulates your company’s secret money-making business sauce, and then there are multiple view models that the UI layer consumes. Somewhere in between is logic that maps data between the various models. This isn’t a new idea, and it was at one time known as the Model Model View Controller pattern.

You might create a model class for each type of view, like a – MovieReviewViewModel, and perhaps all the UI models derive from a base class. The model classes will hold just the state that their respective views require. These classes don’t need behavior – they are essentially just data transfer objects. In a sense, the model classes also become contracts that explicitly describe what the controller needs to put together for the UI, and the view author sees a model with just the information they need.

Of course, building these additional models comes with a price.

  • You have to map data from the domain model into view model classes, and vice versa.
  • You have to figure out how to provide validation logic for view models.
  • You’ll write more code, and manage more classes.

It’s up to you to decide if the benefits are worth the price:

  • Your entities and business objects are optimized for business logic
  • Your view models are optimized for the UI
  • You achieve separation and isolation of the business and UI concerns 

What Was The Original Question?

It was:

“I have created domain entities like Customer, Order, etc. They come out of  repository classes backed by NHibernate. I’m wondering if I send them directly to the view or if I create a ViewModel class to hold data. I’m confused by all the terminology”.

I haven’t given a definitive answer, but I hope I’ve given you enough of my opinion to see that the answer depends on the complexity of your application and its long term goals. For forms-over-data applications, passing your entities can be a simple and effective solution. For more complex applications you may need models built specifically for your views to maintain the integrity and maintainability of your business objects.

Putting the M in MVC – Part II

Thursday, April 2, 2009 by scott
0 comments

Rob just put the M into MVC using Subsonic and a Subsonic MVC Template. The template allows you to go from 0 to functioning application in less time than it takes to listen to a Rob Zombie song. Fantastic work by Rob C, and it leads nicely into the actual question behind this series of posts:

“I have created domain entities like Customer, Order, etc. They come out of  repository classes backed by NHibernate. I’m wondering if I send them directly to the view or if I create a ViewModel class to hold data. I’m confused by all the terminology”.

This is a difficult question to answer without looking at the specifics of an application, but what follows is my opinion on the matter.

Entities, Models, Ownership

To me, an entity is a business object that is full of data and behavior. The data probably comes from a database. The behavior comes from code you write to implement “business logic”. Perhaps the business logic is simple validation code, or perhaps the business logic is code that talks to other entities and objects in your business layer to coordinate more complex business goals – like placing an order and running a long business process.

An entity exists to serve the business layer. If the customer asks you to change how the order total displays, you’ll make the change in the UI and not touch any entities. But, if the customer asks you to change how the order total is calculated, you’ll make the change in the business logic and possibly modify the Order entity itself. Since the entity exists to serve the business layer you should assume the business layer owns all entities.

Sharing

It is reasonable to share these business layer owned entities with the UI layer in many applications. This is what happens if you use Rob’s templates. Here is an excerpt from a template generated controller:

// GET: /Movie/Edit/5
public ActionResult Edit(int id)
{
    var item = _repository.GetByKey(id);
    return View(item);
}

//
// POST: /Movie/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Movie item)
{
    if (ModelState.IsValid)
    {
        string resultMessage = "";
        try
        {
            _repository.Update(item);
            resultMessage = item.DescriptorValue() + " updated!";
        }
        // ...
    }
}

Entities come out of repositories and go directly into a view. During a save operation, the entities materialize from the view and go to a repository. The approach is simple to understand, and works well if you can picture your software like the following:

 entities, views, logic

The entities are round pegs, while the business logic and views are round holes. There is no friction because the entities fit the needs of both layers perfectly. What you are building in these scenarios is a “forms-over-data” application. These types of applications usually have the following characteristics:

  • Every input on a view maps directly to an entity property.
  • Every entity property maps directly to a column in a database table.
  • The majority of the business logic is validation logic.
  • The validation logic mostly exists to satisfy database constraints (like field lengths and null-ability)

I’m not trying to make “forms-over-data” applications sound trivial or stupid. If all you need is a data entry application then you don't want to add unnecessary complexity to your software. Share entities with the UI views and keep things simple. Simple works well.

In the next post we’ll talk about when to avoid sharing entities with your UI layer. As you might guess, it will involve a diagram like this:

 mismatch

Euphemized Exceptions for .NET 4.0

Wednesday, April 1, 2009 by scott
11 comments

Microsoft has discovered, after several well-funded studies, that the names they use for exceptions in the .NET framework create pathological levels of anxiety and stress in programmers. Thus, for .NET 4.0 they decided to create a “kinder and gentler” version of .NET by renaming exceptions in the framework class library.

The changes I know about so far:

Unfortunately,  we will need to update and recompile our code for .NET 4.0, but imagine the healthier lifestyle that will result from friendly error messages.

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!