6

I need to extract the route data (Controller, Action etc) from an arbitrary request path (not related to the current request) such as / or /account/manage. In previous versions of Asp.Net Mvc this could be accomplished like this:

var request = new HttpRequest(null, "http://localhost:3333/Home/About", "testvalue=1");
var response = new HttpResponse(new StringWriter());
var httpContext = new HttpContext(request, response);
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
var values = routeData.Values;

// The following should be true for initial version of mvc app.
values["controller"] == "Home"
values["action"] == "Index"

Source

This solution is not optimal since it requires a fully qualified Url instead of just a request path.

Community
  • 1
  • 1
Oliver Weichhold
  • 10,259
  • 5
  • 45
  • 87
  • Do you already have a HttpContext at the place where you want to read the route data from? Then you could use `var routeData = httpContext.GetRouteData()` to get the routing data from HttpContext's `Features` list (middlewares can store data there to be accessed by services and controllers at a later point) – Tseng Oct 19 '16 at 08:34
  • @Tseng Yes I have a context but that won't help much because I need to get the route data for a request path that's totally unrelated to the current request (I've updated the question to make this clearer). – Oliver Weichhold Oct 19 '16 at 08:52

1 Answers1

4

You can use TemplateMatcher to extract route values:

public class RouteMatcher
{
    public static RouteValueDictionary Match(string routeTemplate, string requestPath)
    {
        var template = TemplateParser.Parse(routeTemplate);
        var matcher = new TemplateMatcher(template, GetDefaults(template));
        var values = new RouteValueDictionary();
        var moduleMatch = matcher.TryMatch(requestPath, values);
        return values;
    }

    // This method extracts the default argument values from the template.
    private static RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate)
    {
        var result = new RouteValueDictionary();

        foreach (var parameter in parsedTemplate.Parameters)
        {
            if (parameter.DefaultValue != null)
            {
                result.Add(parameter.Name, parameter.DefaultValue);
            }
        }

        return result;
    }
}

And example usage:

var template = "{controller=Home}/{action=Index}/{id?}";
var routeValues = RouteMatcher.Match(template, "<your path>");

See this article: https://blog.markvincze.com/matching-route-templates-manually-in-asp-net-core/

adem caglin
  • 22,700
  • 10
  • 58
  • 78
  • 1
    Sorry I'm not sold on this approach. This would not work with attribute based routing and would require to somehow get a hold of all currently active routing template deep in your codebase. – Oliver Weichhold Oct 19 '16 at 09:56