2

I'm using MVC and i have a controller action which handles several different view models, each view model has validation and i'd like the controller to check the validation.

This is my controller action:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult WizardCaseResult(FormCollection fc)
{
    ViewA vm = new ViewA();
    TryUpdateModel<ViewA>(vm);
}

How do i change this code so that the type of view model can be set dynamically something like this:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult WizardCaseResult(FormCollection fc, string ViewType)
{
    ViewType vm = new ViewType();
    TryUpdateModel<ViewType>(vm);
}

I will probably have many different view models so a different action for each type is really out of the question.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Jammy
  • 779
  • 2
  • 13
  • 26

1 Answers1

4

You will need to write a custom model binder for this to work:

public class MyModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var typeValue = bindingContext.ValueProvider.GetValue("viewType");
        var type = Type.GetType(
            (string)typeValue.ConvertTo(typeof(string)), 
            true
        );
        var model = Activator.CreateInstance(type);
        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
        return model;
    }
}

and then:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult WizardCaseResult([ModelBinder(typeof(MyModelBinder))]object model)
{
    ...
}

Now all you have to do is to ensure that the form sends the ViewType parameter which will point to the view model that you want to instantiate.

Oh, and you can forget about strong typing such as the following when dealing types that are only known at runtime:

ViewType vm = new ViewType();
TryUpdateModel<ViewType>(vm);

You might also find the following answer helpful.

Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928