How to get RouteData by URL?

Serge S. picture Serge S. · Aug 23, 2010 · Viewed 19k times · Source

I need to get RoutData by given URL string in ASP.NET MVC application.

I've found the way that I need to mock HttpContextBase based on my URL string and then pass it to RouteTable.Routes.GetRouteData() method in Route Parsing (Uri to Route) thread.

How to mock HttpContextBase to retrieve RouteData by URL string using RouteTable.Routes.GetRouteData()? Or is there another way to retrieve RouteData by URL?

Answer

Serge S. picture Serge S. · Aug 24, 2010

I used Moq to determine what members of HttpContextBase are used in GetRouteData(). They are:

  • Request
    • AppRelativeCurrentExecutionFilePath
    • PathInfo

Request.AppRelativeCurrentExecutionFilePath should return path with ~, what I exactly need, so utility class may be like this one:

public static class RouteUtils
{
    public static RouteData GetRouteDataByUrl(string url)
    {
        return RouteTable.Routes.GetRouteData(new RewritedHttpContextBase(url));
    }

    private class RewritedHttpContextBase : HttpContextBase
    {
        private readonly HttpRequestBase mockHttpRequestBase;

        public RewritedHttpContextBase(string appRelativeUrl)
        {
            this.mockHttpRequestBase = new MockHttpRequestBase(appRelativeUrl);
        }


        public override HttpRequestBase Request
        {
            get
            {
                return mockHttpRequestBase;
            }
        }

        private class MockHttpRequestBase : HttpRequestBase
        {
            private readonly string appRelativeUrl;

            public MockHttpRequestBase(string appRelativeUrl)
            {
                this.appRelativeUrl = appRelativeUrl;
            }

            public override string AppRelativeCurrentExecutionFilePath
            {
                get { return appRelativeUrl; }
            }

            public override string PathInfo
            {
                get { return ""; }
            }
        }
    }
}

Then, you can use it like this (for example on ~/Error/NotFound):

var rd = RouteUtils.GetRouteDataByUrl("~/Error/NotFound")

Which should return an object that looks like this:

RouteData.Values
{
    controller = "Error",
    action = "NotFound"
}