My team needs to develop a framework for our company and products using this framework. One of the requisites is that a product could be customized for a specific client, yet it should be easily updated with another version of the same product (not automatically).
We're using ASP.NET MVC 4 + Web API (for now, a desktop product will be created next year, based on our framework), NHibernate, heavily IoC using Autofac as DI container and N-Layers.
So, in some points of the WebApp, we're using ViewModels as Interfaces with one default implementation and using Autofac to link them, and that's is easy to change in futures customizations.
In ASP.NET MVC, we achieve this implementing IModelBinderProvider and creating a custom class inherating DefaultModelBinder:
Something like this:
public class MyCustomMVCModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(Type modelType)
{
if (modelType.IsInterface)
return new MyCustomMVCModelBinder();
return new DefaultModelBinder();
}
}
public class MyCustomMVCModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var context = new ModelBindingContext(bindingContext);
var item = DependencyResolver.Current.GetService(bindingContext.ModelType);
Func<object> modelAccessor = () => item;
context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),
bindingContext.ModelMetadata.ContainerType, modelAccessor, item.GetType(), bindingContext.ModelName);
return base.BindModel(controllerContext, context);
}
}
And in my controller I just use the interface as parameter. So, it works fine because the values are populated correctly.
But, how do I do the same in Web API with the values binded correctly? I tried implemeting IModelBinder and inheriting ModelBinderProvider. I can get the instance of interface's implementantion, but the values aren't populated.
Here's an attempt implementation in WebAPI:
public class MyCustomWebAPIModelBinderProvider : ModelBinderProvider
{
public override IModelBinder GetBinder(System.Web.Http.HttpConfiguration configuration, Type modelType)
{
return new MyCustomWebAPIModelBinder();
}
}
public class MyCustomWebAPIModelBinder : IModelBinder
{
public bool BindModel(System.Web.Http.Controllers.HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType.IsInterface)
{
var item = GlobalConfiguration.Configuration.DependencyResolver.GetService(bindingContext.ModelType);
if (item != null)
{
Func<object> modelAccessor = () => item;
var a = bindingContext.ModelMetadata.ContainerType;
var b = modelAccessor;
var c = item.GetType();
var d = bindingContext.ModelName;
bindingContext.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(), a, b, c, d);
bindingContext.Model = item;
return true;
}
}
return false;
}
}
What am I missing? Is it possible to do what we want?