Of Code and Me

Somewhere to write down all the stuff I'm going to forget and then need

Enumeration model binder for asp.net mvc August 8, 2009

Filed under: C#,MVC,Uncategorized — Rupert Bates @ 9:06 pm

We were recently working on an asp.net MVC app and I noticed that in a lot of places actions were taking strings as parameters and then converting them to enum values with the action. The reason for doing this rather than just typing the parameter as the enum type was because they were optional and so when the value didn’t exist an error was thrown:

screenshot of error page

screenshot of error page

Because enums are not nullable types they can’t be used as optional parameters.

What was needed then was a way to provide a default parameter for when the parameter didn’t exist in the url. To do this I wrote a custom model binder and it solved the problem pretty well.

Here is the code for the binder

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace EnumTest.Helpers
{
public class EnumBinder<T> : IModelBinder
{
private T DefaultValue { get; set; }
public EnumBinder(T defaultValue)
{
DefaultValue = defaultValue;
}

#region IModelBinder Members
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
return bindingContext.ValueProvider[bindingContext.ModelName] == null
? DefaultValue
: GetEnumValue(DefaultValue, bindingContext.ValueProvider[bindingContext.ModelName].AttemptedValue);
}

#endregion

public static T GetEnumValue<T>(T defaultValue, string value)
{
T enumType = defaultValue;

if ((!String.IsNullOrEmpty(value)) && (Contains(typeof(T), value)))
enumType = (T)Enum.Parse(typeof(T), value, true);

return enumType;
}
public static bool Contains(Type enumType, string value)
{
return Enum.GetNames(enumType).Contains(value, StringComparer.OrdinalIgnoreCase);
}
}
}

And to use it in your project you just register it in your Global.asax, specifying the type of your enum and the default value you want when there is no value available in the input.

protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
            ModelBinders.Binders.Add(typeof(TestEnum), new EnumBinder<TestEnum>(TestEnum.rupert));
        }
About these ads
 

7 Responses to “Enumeration model binder for asp.net mvc”

  1. [...] to VoteEnumeration model binder for asp.net mvc (8/8/2009)Saturday, August 08, 2009 from Rupert BatesWe were recently working on an asp.net MVC app and I [...]

  2. Joshua Ewer Says:

    Hey, a possible alternate approach:

    Could you make the Enum nullable in your controller action (e.g. “public ActionResult Edit(EnumWhatever? value){}”)

    If the querystring value is null (or an invalid value for the mapped enum), the value mapped to your controller will be null and, in the controller action, you could perform your default behavior.

    This approach means you don’t have to register an enum in the model binders each time you have a new one.

    • Rupert Bates Says:

      Hi, yes this would also work. The thing I like about the approach I described here though is that it encapsulates the code for dealing with a null case in one place rather than having it duplicated in every action which takes that enum as a parameter

  3. [...] binding enumerations Rupert Bates has this custom binder, which looks as follows when having it implement the IFilteredModelBinder [...]

  4. [...] looking into this, I came across just the code I thought I needed from Rupert Bates. It is case-insensitive model binder that is designed to allow you to declare a site-wide default [...]

  5. Andrew Says:

    Can you do this in a generic fashion? ie. have a model binder that is responsible for binding any enum regardless of the type. I have hundreds of enums and don’t want to register a separate binder for each one.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.