diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Collections/Specialized/NameValueCollectionExtensions.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Collections/Specialized/NameValueCollectionExtensions.cs
new file mode 100644
index 00000000..29606e1d
--- /dev/null
+++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Collections/Specialized/NameValueCollectionExtensions.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using System.Collections.Specialized;
+
+namespace MvcSiteMapProvider.Collections.Specialized
+{
+ ///
+ /// Provides extension methods for the .
+ ///
+ public static class NameValueCollectionExtensions
+ {
+ public static void AddWithCaseCorrection(this NameValueCollection nameValueCollection, string key, string value, IEnumerable correctCaseKeyset)
+ {
+ var loweredKey = key.ToLowerInvariant();
+ foreach (var item in correctCaseKeyset)
+ {
+ if (item.ToLowerInvariant().Equals(loweredKey))
+ {
+ // Add item with corrected case key
+ nameValueCollection.Add(item, value);
+ }
+ }
+ }
+ }
+}
diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj b/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj
index 557d4d07..4b3949a0 100644
--- a/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj
+++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj
@@ -185,6 +185,7 @@
+
diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs
index 872874a0..b26d7a06 100644
--- a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs
+++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.Specialized;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
@@ -620,7 +621,7 @@ protected virtual void PreserveRouteParameters()
{
var requestContext = this.mvcContextFactory.CreateRequestContext();
var routeDataValues = requestContext.RouteData.Values;
- var queryStringValues = requestContext.HttpContext.Request.QueryString;
+ var queryStringValues = this.GetCaseCorrectedQueryString(requestContext.HttpContext);
foreach (var item in this.PreservedRouteParameters)
{
@@ -642,6 +643,47 @@ protected virtual void PreserveRouteParameters()
}
}
+ ///
+ /// Gets a containing the query string
+ /// key value pairs for the passed in HTTP context. The casing of the keys corrected to be the same as the values that are
+ /// configured either in the dictionary or the collection.
+ ///
+ /// The HTTP context.
+ /// A containing the case-corrected
+ /// key value pairs of the query string.
+ protected virtual NameValueCollection GetCaseCorrectedQueryString(HttpContextBase httpContext)
+ {
+ var queryStringValues = httpContext.Request.QueryString;
+ // Note: we must use the configured route values, rather than the RouteValue property to avoid an
+ // infinite loop.
+ var caseInsensitiveRouteKeys = new HashSet(this.routeValues.Keys, StringComparer.InvariantCultureIgnoreCase);
+ var caseInsensitivePreservedRouteParameters = new HashSet(this.PreservedRouteParameters, StringComparer.InvariantCultureIgnoreCase);
+ var result = new NameValueCollection();
+
+ foreach (var key in queryStringValues.AllKeys)
+ {
+ // A malformed URL could have a null key
+ if (key != null)
+ {
+ if (caseInsensitivePreservedRouteParameters.Contains(key))
+ {
+ result.AddWithCaseCorrection(key, queryStringValues[key], caseInsensitivePreservedRouteParameters);
+ }
+ else if (caseInsensitiveRouteKeys.Contains(key))
+ {
+ result.AddWithCaseCorrection(key, queryStringValues[key], caseInsensitiveRouteKeys);
+ }
+ else
+ {
+ // If the value is not configured, add it to the dictionary with the original case.
+ result.Add(key, queryStringValues[key]);
+ }
+ }
+ }
+
+ return result;
+ }
+
///
/// Flag to ensure the route values are only preserved from the current request a single time.
///
@@ -718,7 +760,7 @@ protected virtual IDictionary MergeRouteValuesAndNamedQueryStrin
var result = new Dictionary(routeValues);
// Add any query string values from the current context
- var queryStringValues = httpContext.Request.QueryString;
+ var queryStringValues = this.GetCaseCorrectedQueryString(httpContext);
// QueryString collection might contain nullable keys
foreach (var key in queryStringValues.AllKeys)