Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Example IModelBinderProvider implementation for ModelBinder constructor injection in MVC 3

I need to wire my custom ModelBinder up to my DI container in MVC 3, but I can't get it working.

So. This is what I have: A ModelBinder with a constructor injected service.

public class ProductModelBinder : IModelBinder{
  public ProductModelBinder(IProductService productService){/*sets field*/}
  // the rest don't matter. It works.
}

My binder works fine if I add it like this:

ModelBinders.Binders.Add(typeof(Product),
     new ProductModelBinder(IoC.Resolve<IProductService>()));

But that is the old way of doing it, and I don't want that.

What I need is help on how to hook that modelbinder up to the IDependencyResolver I've registered.

According to Brad Wilson the secret is using a IModelBinderProvider implementation, but its very unclear as to how to wire that up. (in this post)

Does anyone have an example?

like image 966
Christian Dalager Avatar asked Dec 08 '10 20:12

Christian Dalager


2 Answers

I faced the same situation when coding my MVC 3 app. I ended up with something like this:

public class ModelBinderProvider : IModelBinderProvider
{
    private static Type IfSubClassOrSame(Type subClass, Type baseClass, Type binder)
    {
        if (subClass == baseClass || subClass.IsSubclassOf(baseClass))
            return binder;
        else
            return null;
    }

    public IModelBinder GetBinder(Type modelType)
    {
        var binderType = 
            IfSubClassOrSame(modelType, typeof(xCommand), typeof(xCommandBinder)) ??
            IfSubClassOrSame(modelType, typeof(yCommand), typeof(yCommandBinder)) ?? null;

        return binderType != null ? (IModelBinder) IoC.Resolve(binderType) : null;
    }
}

Then I registered this in my IoC container (Unity in my case):

_container.RegisterType<IModelBinderProvider, ModelBinderProvider>("ModelBinderProvider", singleton());

This works for me.

like image 109
kidoman Avatar answered Nov 18 '22 01:11

kidoman


You need to write your own IModelBinderProvider and register it with the ModelBinderProviders.BinderProviders collection:

public class YourModelBinderProvider : IModelBinderProvider {
    public IModelBinder GetBinder(Type modelType) {
         if(modelType == typeof(Product)) {
             return new ProductModelBinder(...);
         }
         return null;
    }
}

In Global.asax:

ModelBinderProviders.BinderProviders.Add(new YourModelBinderProvider());
like image 36
marcind Avatar answered Nov 18 '22 03:11

marcind