How to pass Request.QueryString to Url.Action?

2019-01-21 18:55发布

问题:

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

回答1:

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



回答2:

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


回答3:

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
    }