Siamak Ferdos
Siamak Ferdos

Reputation: 3299

Can not create instance of an inherited class from an abstract class

I have a class inherited from an abstarct class. On razor, when I create instance of child class, I got this error as is shown in image:

Cannot create an abstract class

But StuffRegisterSearchParameterVM is not an abstract class. Why this happen?

Controller

public ActionResult SearchRegistration(SearchParameterVM model)

Model

abstract public class SearchParameterVM
{
    public string FromDate { get; set; }
    public string ToDate { get; set; }
    public int? MainTestRegisterId { get; set; }
    public int TestTypeId { get; set; }
    public bool IsForAnsweringPage { get; set; }

}


public class StuffRegisterSearchParameterVM : SearchParameterVM
{
    public int? StuffId { get; set; }
    public string Code { get; set; }
}

image of error

Upvotes: 0

Views: 1183

Answers (2)

Jason Goemaat
Jason Goemaat

Reputation: 29234

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
  }
}

Upvotes: 1

Backs
Backs

Reputation: 24923

You can not use abstract class as a parameter of action, because asp.net mvc does not know anything abount posted object type, it trys to create an argument type, and this type is abstract. So, replace it this concrete class or create special binder.

Upvotes: 3

Related Questions