When you define the action:
public ActionResult SearchRegistration(SearchParameterVM model)
That defines a method that MVC will call based on your routes when an http request is made to the server. That http request probably contains only parameters like you would have if you had a web form. MVC model binding simply creates an instance of the class specified in the parameter to the action in C# and tries to set the property values based on the http parameters passed in the http call. This call could be from a view action like you have, from a static html page, from a program, or anywhere else you can make an http call. When it is an abstract class, it cannot create an instance of it.If you had 3 child classes based on your abstract class, MVC would have no way to tell which type to create.
You can check out this question for some more information.
So how would you determine what concrete class should exist in memory when a call to that action is made, given only parameter names with different values? You could create different routes and actions that had different types in their parameters. You could also check those parameters and create different concrete classes based on the passed parameters. For instance if you wanted to use a certain class based on if the 'code' value is passed, , you'll either have to create your own IModelBinder
which could determine which concrete class based on the passed query parameters:
public class MyModelBinder : IModelBinder {
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
// create different concrete instance based on parameters
ValueProviderResult code = bindingContext.ValueProvider.GetValue("Code");
if (code.AttemptedValue != null) {
// code is passed as a parameter, might be our class
// create instance of StuffRegisterSearchParameterVM and return it
}
// no Code parameter passed, check for others
}
}
Then you have to tell in your startup that you have a special model binder
for your abstract class:
ModelBinders.Binders.Add(typeof(SearchParameterVM), new MyModelBinder());
Or you could do something in your action to determine what type to create and use TryUpdateModel
to set the values:
public ActionResult SearchRegistration() {
SearchParameterVM model = null;
if (Request.Parameters["code"] != null) {
model = new StuffRegisterSearchParameterVM();
TryUpdateModel(model); // check return value
}
}