Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I inherit an ASP.NET MVC controller and change only the view?

Tags:

asp.net-mvc

I have a controller that's inheriting from a base controller, and I'm wondering how I can utilize all of the logic from the base controller, but return a different view than the base controller uses.

The base controller populates a model object and passes that model object to its view, but I'm not sure how I can access that model object in the child controller so that I can pass it to the child controller's view.

like image 263
Bret Walker Avatar asked Oct 14 '09 15:10

Bret Walker


2 Answers

A couple points. You can type your return value as ViewResult if you know that's all you're going to return. Then you can interrogate that value from the overridden implementation. More importantly, according to the MVC v1 source, calling View(object) simply sets the ViewData.Model on the controller, then constructs a ViewResult.

Controller.cs:440

protected internal ViewResult View(object model) {
    return View(null /* viewName */, null /* masterName */, model);
}

Controller.cs:456

protected internal virtual ViewResult View(string viewName, string masterName, object model) {
    if (model != null) {
        ViewData.Model = model;
    }

    return new ViewResult {
        ViewName = viewName,
        MasterName = masterName,
        ViewData = ViewData,
        TempData = TempData
    };
}

So all you need to do is call the base method and call View(string).

namespace BaseControllers
{
    public class CoolController
    {
        public virtual ViewResult Get() 
        {
            var awesomeModel = new object();
            return View(awesomeModel);
        }
    }
}

public class CoolController : BaseControllers.CoolController
{
    public override ViewResult Get() 
    {
        var ignoredResult = base.Get();
        // ViewData.Model now refers to awesomeModel
        return View("NotGet");
    }
}

Of course you waste CPU cycles constructing the ViewResult that you ignore. So instead you can do this:

public class CoolController : BaseControllers.CoolController
{
    public override ViewResult Get() 
    {
        var baseResult = base.Get();
        baseResult.ViewName = "NotGet";
        return baseResult;
    }
}

If your base controller returns ActionResult, you'll have to cast it to ViewResult before changing the ViewName.

like image 91
G-Wiz Avatar answered Nov 08 '22 23:11

G-Wiz


Sample from my app:

Base class:

public abstract class BaseTableController<T,TU> : BaseController where TU : IGenericService<T>,IModelWrapperService
{
    protected readonly TU _service;

    public BaseTableController(TU service)
    {
        _service = service;
        _service.ModelWrapper = new ControllerModelStateWrapper(ModelState);
    }


    public ActionResult Index()
    {
        return View(_service.List());
    }

Inherited:

public class SeverityController : BaseTableController<Severity, ISeverityService>
{
    public SeverityController(ISeverityService service)
        : base(service)
    {
    }

   //NO CODE INSIDE
}

SeverityController.Index() leads to Views/Severity/Index.aspx. Just had to prepare view. Severity is one of dictionared in my bug tracking application. Every dictionary has similar logic, so I could share some code.

like image 5
LukLed Avatar answered Nov 08 '22 22:11

LukLed