Roman
Roman

Reputation: 4611

String URL to RouteValueDictionary

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.

Upvotes: 20

Views: 17734

Answers (4)

Serg
Serg

Reputation: 7475

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();
}

Upvotes: 1

Steve Hiner
Steve Hiner

Reputation: 2573

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.

Upvotes: 0

Piotr Czapla
Piotr Czapla

Reputation: 26522

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.

Upvotes: 39

Piotr Czapla
Piotr Czapla

Reputation: 26522

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
        //...

Upvotes: 3

Related Questions