Noah Blumenthal's Blog

July 10, 2009

ASP.NET Custom Model Binder Template

Filed under: Uncategorized — noahblu @ 2:09 am

I have found that I build a lot of the same logic into my Model Binders.  I typically use Reflection to either instantiate a new object or call a method on a Factory that will do that for me.  So I’ve put together a ModelBinder using the Template pattern to help accomplish this more easily.

First, the Template:

   1: public abstract class ReflectionModelBinder : DefaultModelBinder

   2:     {

   3:         private IModelBinderValidator _validator = null;

   4:         public ReflectionModelBinder() { }

   5:         public ReflectionModelBinder(IModelBinderValidator validator)

   6:         {

   7:             _validator = validator;

   8:         }

   9:         protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)

  10:         {

  11:             ParameterInfo[] parameters = GetParameters();

  12:             List<object> paramValues = new List<object>();

  13:             IModelBinder binder;

  14:             string oldModelName = bindingContext.ModelName;

  15:             foreach (ParameterInfo param in parameters)

  16:             {

  17:                 string name = CreateSubPropertyName(oldModelName, param.Name);

  18:                 bindingContext.ModelType = param.ParameterType;

  19:                 bindingContext.ModelName = name;

  20:                 if (!System.Web.Mvc.ModelBinders.Binders.TryGetValue(param.ParameterType, out binder))

  21:                     binder = System.Web.Mvc.ModelBinders.Binders.DefaultBinder;

  22:                 object model = binder.BindModel(controllerContext, bindingContext);

  23:                 paramValues.Add(model);

  24:             }

  25:             bindingContext.ModelType = modelType;

  26:             bindingContext.ModelName = oldModelName;

  27:             object obj = CreateModel(paramValues.ToArray());

  28:  

  29:             if (_validator != null)

  30:                 _validator.Validate(bindingContext, obj);

  31:  

  32:             return obj;

  33:         }

  34:         protected abstract ParameterInfo[] GetParameters();

  35:         protected abstract object CreateModel(object[] parameters);

  36:     }

(don’t mind the IModelBinderValidator, that’ll have to be another post, but you can probably figure it out)

So now I have this template.  Here’s an example of how I can bind a model by using a Factory (I have a Lease object with a LeaseFactory  that creates the lease and all the associated charges like back rent etc.):

   1: public class LeaseReflectionModelBinder : ReflectionModelBinder

   2: {

   3:     public LeaseReflectionModelBinder(IModelBinderValidator validator) : base(validator)

   4:     {

   5:         _createLeaseMethod = typeof(LeaseFactory).GetMethod("CreateLease", BindingFlags.Static | BindingFlags.Public);

   6:     }

   7:     private MethodInfo _createLeaseMethod;

   8:  

   9:     protected override ParameterInfo[] GetParameters()

  10:     {

  11:         return _createLeaseMethod.GetParameters();

  12:     }

  13:  

  14:     protected override object CreateModel(object[] parameters)

  15:     {

  16:         return _createLeaseMethod.Invoke(null, parameters);

  17:     }

  18: }

Easy, huh?

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

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

Blog at WordPress.com.

%d bloggers like this: