I’m trying to create an ActionLink to export data from a grid. The grid is filtered by values from the query string. Here’s an example of the url:
http://www.mysite.com/GridPage?Column=Name&Direction=Ascending&searchName=text
Here’s the code to add my ActionLink to the page:
@Html.ActionLink("Export to Excel", // link text
"Export", // action name
"GridPage", // controller name
Request.QueryString.ToRouteDic(), // route values
new { @class = "export"}) // html attributes
When the link is displayed, the url is this:
http://www.mysite.com/GridPage/Export?Count=3&Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object%5D&Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D
What am I doing wrong?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Try this:
I’m not sure this is the cleanest or most correct way but it does work
I didn’t use your extension method. You’ll have to reintegrate that:
@{
RouteValueDictionary tRVD = new RouteValueDictionary(ViewContext.RouteData.Values);
foreach (string key in Request.QueryString.Keys )
{
tRVD[key]=Request.QueryString[key].ToString();
}
}
then
@Html.ActionLink("Export to Excel", // link text
"Export", // action name
"GridPage", // controller name
tRVD,
new Dictionary<string, object> { { "class", "export" } }) // html attributes
Results in

with class export
Method 2
If you look here:
http://msdn.microsoft.com/en-us/library/system.web.mvc.html.linkextensions.actionlink.aspx
//You are currently using: ActionLink(HtmlHelper, String, String, String, Object, Object) //You want to be using: ActionLink(HtmlHelper, String, String, String, RouteValueDictionary, IDictionary<String, Object>)
Method 3
Cross-posting from How do I get the QueryString values into a the RouteValueDictionary using Html.BeginForm()?
Here’s a helper extension so you can dump the querystring in any method accepting a RouteValueDictionary.
/// <summary>
/// Turn the current request's querystring into the appropriate param for <code>Html.BeginForm</code> or <code>Html.ActionLink</code>
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
/// <remarks>
/// See discussions:
/// * https://stackoverflow.com/questions/4675616/how-do-i-get-the-querystring-values-into-a-the-routevaluedictionary-using-html-b
/// * https://stackoverflow.com/questions/6165700/add-query-string-as-route-value-dictionary-to-actionlink
/// </remarks>
public static RouteValueDictionary QueryStringAsRouteValueDictionary(this HtmlHelper html)
{
// shorthand
var qs = html.ViewContext.RequestContext.HttpContext.Request.QueryString;
// because LINQ is the (old) new black
return qs.AllKeys.Aggregate(new RouteValueDictionary(html.ViewContext.RouteData.Values),
(rvd, k) => {
// can't separately add multiple values `?foo=1&foo=2` to dictionary, they'll be combined as `foo=1,2`
//qs.GetValues(k).ForEach(v => rvd.Add(k, v));
rvd.Add(k, qs[k]);
return rvd;
});
}
Method 4
You can also try CopyTo from System.Collections.Specialized like this:
var queryParams = new Dictionary<string, object>(); Request.QueryString.CopyTo(queryParams); var routeValueDictionary = new RouteValueDictionary(queryParams);
Method 5
Here is a fixed version that also handles the case where the same key appears several times:
public static RouteValueDictionary QueryStringToRouteValueDictionary(this HtmlHelper html)
{
var qs = html.ViewContext.RequestContext.HttpContext.Request.QueryString;
return qs.AllKeys.Aggregate(new RouteValueDictionary(html.ViewContext.RouteData.Values),
(rvd, k) =>
{
// get values
var values = qs.GetValues(k);
// if only one value simply add it
if (values.Length == 1)
{
rvd.Add(k, values[0]);
}
else
{
// an array has to be add using the syntax <k>[<i>] for the key values, where k is the key itself and i is the counter
for (var i = 0; i < values.Length; ++i)
{
rvd.Add($"{k}[{i}]", values[i]);
}
}
return rvd;
});
}
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0