简体   繁体   中英

ASP.NET MVC Generic Controller for a Base Entity

I'm trying to create a generic controller that can deal with entities that will all inherit from a base class.

At the moment, I have a "Department" controller:

public class DepartmentsController : BaseController
{
    Departments model;

    public virtual ActionResult Index()
    {                        
        model = new Departments("");
        return View("Index", model.SearchAsList());
    }

    [HttpPost]
    public virtual ActionResult Insert(Departments obj)
    {
        obj.Create();
        return RedirectToAction("Index");
    }

    [HttpPost]
    public virtual ActionResult Update(Departments obj)
    {
        obj.Update();
        return RedirectToAction("Index");
    }

    public virtual ActionResult Edit(int id)
    {
        model = new Departments("");
        model.ID = id;
        return View("Edit", model.SearchAsList()[0]);
    }

    public virtual ActionResult Details(int id)
    {
        model = new Departments("");
        model.ID = id;
        return View("Details", model.SearchAsList()[0]);
    }

    public virtual ActionResult Delete(int id)
    {
        model = new Departments("");
        model.ID = id;
        model.Delete();
        return RedirectToAction("Index");
    }

}

a base controller:

public class BaseController : Controller
{
    public virtual ActionResult Create()
    {
        return View("Create");
    }

}

as well as an entity and base entity:

public class BaseEntity
{
    public int Create { get; set; }
}

public class Department : BaseEntity
{
    public int MySpecificMethod { get; set; }
}

But I want to make this more generic so that the Department controller (and all my other entity controllers do not have to have any actions unless they are different to those in the base controller. The "Create" action is the only one that doesn't reference "Department" so I have added that to the Base Controller but I'm unsure on how I modify it so that it will accept any object type that is based on my base entity.

I have seen examples where you can pass through a class eg

 public class DepartmentsController<T> : BaseController
        where T: class

However, "T" in my instance would be a class that I know inherits from "BaseEntity" and I therefore want to be able to access it's public functions.

I changed that example to be:

public class DepartmentsController<T> : BaseController
        where T: BaseEntity

And now "T" does have access to the base entity functions (eg Create), but that gives me the problem of how to access the specific functions from the actual Department class (eg MySpecificMethod).

Hopefully that makes sense and someone can explain how I can modify my controller and base controller.

Thanks!

To do this, you need to be able to choose one of your derived classes during the binding step (ie by the parameters you are sending to the server).

Next, you need a custom ModelBinder, overriding method

protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)

and then, you will be able to create an instance of the derived class you want...

In my case, I have:

public class AbstractC1 { . . . }
public class DerivedC1 : AbstractC1   { . . . }
public class DerivedC2 : AbstractC2   { . . . }

Then, in my controller:

public ActionResult MyAction([ModelBinder(typeof(CustomModelBinder))] AbstractC1 myData) { . . . }

And, in my ModelBinder:

public class CustomModelBinder : DefaultModelBinder {
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) {
    AbstractC1 data = MyFactory.createDerivedClass(...);
    return data;
}

Where MyFactory creates either DerivedC1 or DerivedC2, depending on some parameters of the request.

BUT... this allows you to use one common method for all derived types, altough you have to use them as base classes, or find a method to cast them to their derived classes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM