Tim Rogers
Tim Rogers

Reputation: 21713

Can route values be bound to values other than components of the URL?

Is there a way in ASP.NET MVC 4 to bind route values from sources other than a placeholder in a route URL: a header or post data for example? Or are they intrinsically coupled to the URL?

Specifically, I was interested in overriding the action route value with a value from a posted form field. That way, you could easily have different submit buttons on a page that invoked different actions on the controller by giving each a name of action and a value of the action name.

I've tried setting the RouteData.Values in an HttpModule but that appears to be too early in the pipeline to override the action.

Upvotes: 1

Views: 82

Answers (1)

haim770
haim770

Reputation: 49095

HttpModule is indeed too early for this, and is actually not needed. You can rely on the regular MVC route-handling mechanism and simply provide it with your own RouteValues extracted from the HTTP request.

For example:

public class MyHeadersBasedRoute : RouteBase
{
    public const string HEADER_CONTROLLER_KEY = "X-REQUESTED-CONTROLLER";
    public const string HEADER_ACTION_KEY = "X-REQUESTED-ACTION";

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var requestedController = httpContext.Request.Headers[HEADER_CONTROLLER_KEY];
        var requestedAction = httpContext.Request.Headers[HEADER_ACTION_KEY];

        if (String.IsNullOrEmpty(requestedController) || String.IsNullOrEmpty(requestedAction))
            return null;

        var ret = new RouteData(this, new MvcRouteHandler());

        ret.Values.Add("controller", requestedController);
        ret.Values.Add("action", requestedAction);

        // add any extra parameter from request, for example:
        ret.Values.Add("id", httpContext.Request.Form["id"]);

        return ret;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        return null;
    }
}

Then just register it in your global.asax:

 RouteTable.Routes.Add(new MyHeadersBasedRoute());

Upvotes: 1

Related Questions