tags:

views:

123

answers:

3

Is it possible in ASP.NET MVC via some extension/override points to allow a "delegate field" to be used as an "action"?

Something like:

using System;
using System.Web.Mvc;

namespace Company.Web.Controllers
{
    public class SwitchboardController : BaseController
    {
        public Func<ActionResult> Index, Admin, Data, Reports;

        public SwitchboardController()
        {
            // Generic views
            Index = Admin = Data = Reports =
                () => View();
        }
    }
}

I know I'm a little hell-bent for this one but if this is possible it'd open up many new ways of making actions. You could, for example, have Django-style generic views in MVC with only a single line of code to define the action or have different ways to factor duplicate logic across multiple controllers.

I'm not quiet sure where would be the place to slap this logic into or how much work would be required to alter something so fundamental in the framework.

+1  A: 

No, it isn't. The base controller is looking for methods and not for fields to dispatch an action.

EDIT:
Sorry, I was a bit fast and fixed to the standard classes provided.
You can do that but you have to overwrite the Execute Method in your controller or implement and provide your own IActionInvoker to dispatch the action to fields. Look into the post action processing in detail. It explains the dispatching in detail.

Christian13467
Maybe not possible with the default controller, but there are some good extension points in ASP.NET MVC to plug in your own controllers and change the way things work.
Lance Fisher
Your right. I edited my answer.
Christian13467
+2  A: 

You will probably have to build your own Controller factory. This class builds controllers, and implements IControllerFactory. You can inherit from DefaultControllerFactory. Override CreateController() to return your own IController.

Register your controller factory in Application_Start() of MvcApplication using this line:

ControllerBuilder.Current.SetControllerFactory(typeof(MyControllerFactory));

In your implementation of IController, override the Execute method. You can use the RequestContext to decide which delegate to invoke. It would probably be easiest to inherit from ControllerBase, and override Execute in there if you don't want to fully implement IController.

The RequestContext passed into Execute carries a RouteData object. This is a dictionary populated by the routing engine that tells you what action should be invoked, and any parameters. You can get the action name like this:

//context is a RequestContext object passed to IController.Execute()
string actionName = requestContext.RouteData.Values["action"];

You could even define your action as a dictionary, and just pull them out once you get the action name.

One last thing, normal action methods return an ActionResult, which the framework uses to decide which view to render. Once you execute your delegates, I think you'll have to set some stuff manually in your special base controller. I'm not exactly sure what to set or how to get your View executed from here without cracking open the MVC source.

Good luck! This looks like an interesting idea.

Lance Fisher
A: 

As you seem to be implementing a BaseController in your code sample, if you override the Execute (from the IController) you'll be able to interpret the request => action however you like.

Kieron