MVC ActionLink add all (optional) parameters from current url

Viewed 15267

The very famous ActionLink:

 <%: Html.ActionLink("Back to List", "Index")%>

Now, this link is in my Details view. The Index view is a search page. The URL of that looks like this:

http://localhost:50152/2011-2012/Instelling/Details/76?gemeente=Dendermonde&postcode=92**&gebruikerscode=VVKSO114421&dossiernr=114421%20&organisatie=CLB

As you can see, quite the amount of parameters. Obviously I want to keep all these parameters when I return to the Index page, so I need to add them in the ActionLink.

Now, I'm tired of doing that manually, it's ok for 1, but not for 6. This should go a lot easier.

Question: How do I return All parameters of the current URL into the ActionLink as optional RouteValues.

I've been looking to Request.QueryString. It has to be something with that. I was thinking of writing some static method in Global.asax doing the job but no luck yet. Maybe there is an easy way to do this which I don't know about?

Edit: This is what I came up with (which works)

In global.asax:

    public static RouteValueDictionary optionalParamters(NameValueCollection c) {
        RouteValueDictionary r = new RouteValueDictionary();
        foreach (string s in c.AllKeys) {
            r.Add(s, c[s]);
        }
        return r;
    }

Details.aspx:

    <%: Html.ActionLink("Back to List", "Index", MVC2_NASTEST.MvcApplication.optionalParamters(Request.QueryString))%>

Where do I best put this code? not in Global.asax I guess...

Edit 2:

using System;
using System.Web.Mvc;

namespace MVC2_NASTEST.Helpers {
    public static class ActionLinkwParamsExtensions {
        public static MvcHtmlString CustomLink(this HtmlHelper helper, string linktext) {
            //here u can use helper to get View context and then routvalue dictionary
            var routevals = helper.ViewContext.RouteData.Values;
            //here u can do whatever u want with route values
            return null;
        }

    }
}


<%@ Import Namespace="MVC2_NASTEST.Helpers" %>
...
<%: Html.ActionLinkwParams("Index") %>
5 Answers

Here is an extension method for ViewContext that creates a RouteValueDictionary based on the request route values and querystring.

using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

namespace MyMvcApplication.Utilities
{
    public static class ViewContextExtensions
    {
        /// <summary>
        /// Builds a RouteValueDictionary that combines the request route values, the querystring parameters,
        /// and the passed newRouteValues. Values from newRouteValues override request route values and querystring
        /// parameters having the same key.
        /// </summary>
        public static RouteValueDictionary GetCombinedRouteValues(this ViewContext viewContext, object newRouteValues)
        {
            RouteValueDictionary combinedRouteValues = new RouteValueDictionary(viewContext.RouteData.Values);

            NameValueCollection queryString = viewContext.RequestContext.HttpContext.Request.QueryString;
            foreach (string key in queryString.AllKeys.Where(key => key != null))
                combinedRouteValues[key] = queryString[key];

            if (newRouteValues != null)
            {
                foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(newRouteValues))
                    combinedRouteValues[descriptor.Name] = descriptor.GetValue(newRouteValues);
            }


            return combinedRouteValues;
        }
    }
}

You can pass the created RouteValueDictionary to Html.ActionLink or Url.Action

@Html.ActionLink("5", "Index", "Product",
    ViewContext.GetCombinedRouteValues(new { Page = 5 }),
    new Dictionary<string, object> { { "class", "page-link" } })

If the Page parameter does not exist in the request URL, it will be added in the generated URL. If it does exist, its value will be changed to 5.

This article has a more detailed explanation of my solution.

Related