Reputation: 1065
In my MVC 4 project, I have a Model like:
public class MyModel
{
private readonly IService MyService;
public MyModel([Dependency]IService service)
{
this.MyService = service;
}
// ...
}
My Controller has an action which is an HttpPost like:
[HttpPost]
public ActionResult Show(MyModel myModel)
{
// do stuff
My Controller does not (and should not) have an instance of my IoC container. When the HttpPost happens and the action is called, MVC tries to create an instance of my Model when it does the model binding. It needs a parameterless constructor to do so. If it creates a Model using the default constructor, MyService won't be set, and the Model will not have all of it's dependencies present. I don't want to have to call myModel.Init(someIServiceInstance). I want to plug into the framework so that the dependency is resolved (the correct constructor is called) at the creation of the model.
I'm currently using Unity as my dependency resolver and have a few factories for things like Controllers, Service clients, etc. For the controller, I was able to register the ControllerFactory and pass dependencies into the controllers, but I don't see a ModelFactory that I can register. I'm not so concerned with the binding process itself; once the model is instantiated, I'm happy with how the binding is done. I only want to implement how the model is created/constructed. I'm also okay if the ModelFactory uses a reference to the container in order to resolve the dependency (I can inject the container to the factory as a parameter to it's constructor, I just don't want the Controllers to have a reference directly to the container).
Does anyone have a sample of a ModelFactory (or ModelBinder, and/or ModelBinderResolver, etc.) that will handle creation of the Model, and then rely on the frameworks implementation to do the rest of the Binding process?
Upvotes: 2
Views: 1745
Reputation: 1065
I think I figured it out:
public class MyModelBinder : DefaultModelBinder
{
private readonly UnityContainer container;
public MyModelBinder(UnityContainer container)
{
this.container = container;
}
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
if (modelType == null)
{
return base.CreateModel(controllerContext, bindingContext, null);
}
return this.container.Resolve(modelType);
}
}
And in Global.asax, within Application_Start(), or in your IoC configuration:
ModelBinders.Binders.Add(typeof(object), new MyModelBinder(container));
Upvotes: 2
Reputation: 1038780
You could write a custom model binder:
public class MyModelModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
// TODO: create the model instance here using your DI framework or the
// DependencyResolver which is more correct
}
}
and then register this model binder in your Global.asax
:
ModelBinders.Binders.Add(typeof(MyModel), new MyModelModelBinder());
But usually this is bad practice. I would recommend you using view models and have your controller actions take view models as parameters and pass view models to the views. Those view models will have parameterless constructor. And then you could have your domain model or repository injected into the controller constructor.
Upvotes: 4