String URL to RouteValueDictionary
Asked Answered
C

4

20

Is there as easy way to convert string URL to RouteValueDictionary collection? Some method like UrlToRouteValueDictionary(string url).

I need such method because I want to 'parse' URL according to my routes settings, modify some route values and using urlHelper.RouteUrl() generate string URL according to modified RouteValueDictionary collection.

Thanks.

Cream answered 26/9, 2009 at 16:20 Comment(0)
O
39

Here is a solution that doesn't require mocking:

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"

Hope this helps.

Oviform answered 2/12, 2009 at 9:48 Comment(3)
@david.s I had problems with the solution you posted. It couldn't sepearate a route value from querystring. Piotr's solution works fine.Zackzackariah
+10! Is there a way to get this into the request.RequestContext.RouteData? I have an extension method that acts on RequestContext.RouteData, but it doesn't match routeData above.Adoree
@Piotr - thanks. This code works and allows me to do some routing based on the Referring URL - mission accomplished! However, I can only get the code to run in the context of the application, but, never in the context of my Visual Studio unit test. I'm populating the RouteTable from the RouteConfig, but, still, I get a NullReferenceException when the GetRouteData method is called.Gaberones
O
3

You would need to create a mocked HttpContext as routes constrains requires it.

Here is an example that I use to unit test my routes (it was copied from Pro ASP.Net MVC framework):

        RouteCollection routeConfig = new RouteCollection();
        MvcApplication.RegisterRoutes(routeConfig);
        var mockHttpContext = new MockedHttpContext(url);
        RouteData routeData = routeConfig.GetRouteData(mockHttpContext.Object);
        // routeData.Values is an instance of RouteValueDictionary
        //...
Oviform answered 3/11, 2009 at 15:29 Comment(2)
Thanks, this solution looks interesting. But its a pity there is no 'lightweight' method that does not require mocking, because I use Mocks in my unit tests but not in general code. Looks like I should.Cream
I've had similar concerns and finally decided to pass serialized RouteCollection between requests.Oviform
M
1

I wouldn't rely on RouteTable.Routes.GetRouteData from previous examples because in that case you risk missing some values (for example if your query string parameters don't fully fit any of registered mapping routes). Also, my version doesn't require mocking a bunch of request/response/context objects.

public static RouteValueDictionary UrlToRouteValueDictionary(string url)
{
    int queryPos = url.IndexOf('?');

    if (queryPos != -1)
    {
        string queryString = url.Substring(queryPos + 1);
        var valuesCollection = HttpUtility.ParseQueryString(queryString);
        return new RouteValueDictionary(valuesCollection.AllKeys.ToDictionary(k => k, k => (object)valuesCollection[k]));
    }

    return new RouteValueDictionary();
}
Mendelssohn answered 8/12, 2017 at 9:26 Comment(1)
doesn't this only return the query string when the OP actually asked for the routed path?Threegaited
P
0

Here is a solution that doesn't require instantiating a bunch of new classes.

var httpContext = context.Get<System.Web.HttpContextWrapper>("System.Web.HttpContextBase");
var routeData = System.Web.Routing.RouteTable.Routes.GetRouteData(httpContext);
var values = routeData.Values;
var controller = values["controller"];
var action = values["action"];

The owin context contains an environment that includes the HttpContext.

Pedrick answered 3/8, 2015 at 23:28 Comment(2)
can you explain your owin context a little more? Are you saying your snippet works if we reference the Microsoft.Owin libraries?Gaberones
I'm running the code above in an MVC project that uses OWIN. MVC 5 uses OWIN but earlier versions didn't. If you are using MVC 5 or later then you shouldn't need to add any references.Pedrick

© 2022 - 2024 — McMap. All rights reserved.