Repro:
- Create an Action method as follows that displays a WebGrid with paging enabled:
public class MyController : Controller
{
...
public ActionResult MyAction(IList<int> productId)
{
.... return a View that contains a WebGrid with paging or sorting enabled
}
}
- Navigate to the action with the following URL:
http://servername/MyController/MyAction?productId=1&productId=3&productId=5
- Examine the paging or sorting urls in the rendered WebGrid
Expected result:
- Generated urls should contain the same repeated keys as the original url, e.g.:
http://servername/MyController/MyAction?productId=1&productId=3&productId=5&page=2
Actual result:
- Generated urls replace repeated querystring keys by a single key with a comma-separated value, e.g.:
http://servername/MyController/MyAction?productId=1%2c3%2c5&page=2
- As a consequence, the productId parameter of the Action method received a single value "1,3,5" instead of a list of values.
Analysis:
This is a bug in the method WebGrid.GetPath, which does not take account of repeated values in the QueryString NameValueCollection. To fix it, replace the following code:
for (int i = 0; i < queryString.Count; i++)
{
if (i > 0)
{
sb.Append("&");
}
sb.Append(HttpUtility.UrlEncode(queryString.Keys[i]));
sb.Append("=");
sb.Append(HttpUtility.UrlEncode(queryString[i]));
}
with something like:
for (int i = 0; i < queryString.Count; i++)
{
string encodedKey = HttpUtility.UrlEncode(queryString.Keys[i]);
foreach(string value in queryString.GetValues(i))
{
if (i > 0)
{
sb.Append("&");
}
sb.Append(key);
sb.Append("=");
sb.Append(HttpUtility.UrlEncode(value));
}
}
- Create an Action method as follows that displays a WebGrid with paging enabled:
public class MyController : Controller
{
...
public ActionResult MyAction(IList<int> productId)
{
.... return a View that contains a WebGrid with paging or sorting enabled
}
}
- Navigate to the action with the following URL:
http://servername/MyController/MyAction?productId=1&productId=3&productId=5
- Examine the paging or sorting urls in the rendered WebGrid
Expected result:
- Generated urls should contain the same repeated keys as the original url, e.g.:
http://servername/MyController/MyAction?productId=1&productId=3&productId=5&page=2
Actual result:
- Generated urls replace repeated querystring keys by a single key with a comma-separated value, e.g.:
http://servername/MyController/MyAction?productId=1%2c3%2c5&page=2
- As a consequence, the productId parameter of the Action method received a single value "1,3,5" instead of a list of values.
Analysis:
This is a bug in the method WebGrid.GetPath, which does not take account of repeated values in the QueryString NameValueCollection. To fix it, replace the following code:
for (int i = 0; i < queryString.Count; i++)
{
if (i > 0)
{
sb.Append("&");
}
sb.Append(HttpUtility.UrlEncode(queryString.Keys[i]));
sb.Append("=");
sb.Append(HttpUtility.UrlEncode(queryString[i]));
}
with something like:
for (int i = 0; i < queryString.Count; i++)
{
string encodedKey = HttpUtility.UrlEncode(queryString.Keys[i]);
foreach(string value in queryString.GetValues(i))
{
if (i > 0)
{
sb.Append("&");
}
sb.Append(key);
sb.Append("=");
sb.Append(HttpUtility.UrlEncode(value));
}
}