ASP.NET MVC 2 - How do I use an Interface as the Type for a Strongly Typed View
I'd like to keep my concrete classes separate from my views. Without using strongly typed views, I'm fine. I just use a big parameter list in the controller method signatures and then use my service layer factory methods to create my concrete objects.
This is actually just fine with me, but it got me thinking and after a little playing, I realized it was literally impossible for a controller method to accept an interface as a method parameter - because it has no way of instantiating it. Can't create a strongly-typed view using an interface through the IDE either (which makes sense actually).
So my question. Is there some way to tell the controller how to instantiate the interface parameter using my service layer factory me开发者_开发百科thods?
I'd like to convert from:
[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
[UrlRoute(Path = "Application/Edit/{id}")]
public ActionResult Edit(String id, String TypeCode, String TimeCode, String[] SelectedSchoolSystems,
String PositionChoice1, String PositionChoice2, String PositionChoice3, String Reason, String LocationPreference,
String AvailableDate, String RecipientsNotSelected, String RecipientsSelected) {
//New blank app
IApplication _application = ApplicationService.GetById(id);
to something like
[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
[UrlRoute(Path = "Application/Edit/{id}")]
public ActionResult Edit(String id, IApplication app) {
//Don't need to do this anymore
//IApplication _application = ApplicationService.GetById(id);
You need view model layer.
It might make sense to abstract away business layer entities using interfaces, but it won't make much sense to abstract web app specific entities (in most cases i guess). That would allow You to code against implementations.
And trying to bind back entities from Form without accessing database will make a lot of trouble too.
Custom model binding. Just have the model binder build a instance of a derived class and return it as it's interface.
On the other hand, why? Typically, you'd use view-specific models both for the view and the controller parameters. Each view/action has specific model needs. I can understand why you might like to derive them from a common interface or abstract class -- so, for instance, your master page has a set of common information that it can use, but why would a specific action ever need to receive the data as an abstraction? Wouldn't it know exactly the kind of data that it needs and simply use the correct derived class as the parameter type?
You could write a custom model binder which will instantiate the correct type:
public class MyModelBinder: DefaultModelBinder
{
protected override object CreateModel(
ControllerContext controllerContext,
ModelBindingContext bindingContext,
Type modelType
)
{
return // ... instantiate your model here
}
}
And then:
public ActionResult Edit(
string id,
[ModelBinder(typeof(MyModelBinder))] IApplication app
)
{
...
}
精彩评论