Linefeed
Linefeed

Reputation: 979

How to pass Request.QueryString to Url.Action?

I'm building an url using the method:

Url.Action("action", "controller");

I like to pass the querystring for the current request into that url as well. Something like the following (but it doesn't work):

Url.Action("action", "controller", Request.QueryString);

Converting the QueryString to routevalues is possible with the following extension:

    public static RouteValueDictionary ToRouteValues(this NameValueCollection queryString)
    {
        if (queryString.IsNull() || queryString.HasKeys() == false) return new RouteValueDictionary();

        var routeValues = new RouteValueDictionary();
        foreach (string key in queryString.AllKeys)
            routeValues.Add(key, queryString[key]);

        return routeValues;
    }

With the extension method the following does work:

Url.Action("action", "controller", Request.QueryString.ToRouteValues());

Is there an other better way ? Thx

Upvotes: 40

Views: 25879

Answers (3)

pwhe23
pwhe23

Reputation: 1334

If you want to easily be able to add additional route value parameters to your Url.Action, try this extension method (based on Linefeed's) which takes an anonymous object and returns a RouteValueCollection:

public static RouteValueDictionary ToRouteValues(this NameValueCollection col, Object obj)
{
    var values = new RouteValueDictionary(obj);
    if (col != null)
    {
        foreach (string key in col)
        {
            //values passed in object override those already in collection
            if (key != null && !values.ContainsKey(key)) values[key] = col[key];
        }
    }
    return values;
}

Then you can use it like so:

Url.Action("action", "controller", Request.QueryString.ToRouteValues(new{ id=0 }));

Upvotes: 35

Tomino
Tomino

Reputation: 6249

Here's my solution based on pwhe23's answer. I wanted to keep query string parameters through POST requests (due to a Mvc.Grid) and use just a single action for HTTP GET. CRUD actions are handled by a single page and modal dialogs inside (for insert/update/delete).

So here's my Extension:

public static class MvcExtensions
{
    public static RouteValueDictionary ToRouteValues(this NameValueCollection col, Object obj = null)
    {
        var values = obj != null ? new RouteValueDictionary(obj) : new RouteValueDictionary();

        if (col == null) return values;

        foreach (string key in col)
        {
            //values passed in object are already in collection
            if (!values.ContainsKey(key)) values[key] = col[key];
        }
        return values;
    }
}

Usage in Controller (e.g. Edit action):

    [HttpPost]
    public ActionResult Edit(MyModel model)
    {
        // Some stuff
        return RedirectToAction("Index", Request.QueryString.ToRouteValues());
    }

Form for edit generated in View (modal dialog is used):

 @using (Html.BeginForm("Edit", "SomeControllerName", Request.QueryString.ToRouteValues(), FormMethod.Post))
    {
        // Some stuff... e.g. dialog content
    }

Upvotes: 2

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

The extension method seems correct and is the way to go.

Upvotes: 14

Related Questions