From b4929b9aa419c3302819e3284c3bd20fec3afb38 Mon Sep 17 00:00:00 2001 From: Shad Storhaug Date: Sat, 31 Jan 2015 02:11:46 +0700 Subject: [PATCH] Performance enhancements for #380 fix. --- .../NameValueCollectionExtensions.cs | 1 + .../RequestCacheableSiteMapNode.cs | 24 +++++++++++++++++++ .../MvcSiteMapProvider/SiteMapNode.cs | 12 ++++++---- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Collections/Specialized/NameValueCollectionExtensions.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Collections/Specialized/NameValueCollectionExtensions.cs index 29606e1d..9aa23071 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Collections/Specialized/NameValueCollectionExtensions.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Collections/Specialized/NameValueCollectionExtensions.cs @@ -17,6 +17,7 @@ public static void AddWithCaseCorrection(this NameValueCollection nameValueColle { // Add item with corrected case key nameValueCollection.Add(item, value); + break; } } } diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMapNode.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMapNode.cs index 04b63240..150b9d5f 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMapNode.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMapNode.cs @@ -1,6 +1,9 @@ using System; using System.Text; using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Web; using MvcSiteMapProvider.Caching; using MvcSiteMapProvider.Globalization; using MvcSiteMapProvider.Web.Mvc; @@ -167,6 +170,27 @@ public override string Route set { this.SetCachedOrMemberValue(x => base.Route = x, "Route", value); } } + protected override NameValueCollection GetCaseCorrectedQueryString(HttpContextBase httpContext) + { + // This method is called twice per node only in the case where there are + // preserved route parameters, so the memory trade-off is only worth it if + // we have some configured. + if (this.PreservedRouteParameters.Any()) + { + var key = this.GetCacheKey("GetCaseCorrectedQueryString_" + httpContext.Request.Url.Query); + var result = this.requestCache.GetValue(key); + if (result == null) + { + result = base.GetCaseCorrectedQueryString(httpContext); + this.requestCache.SetValue(key, result); + } + + return result; + } + + return base.GetCaseCorrectedQueryString(httpContext); + } + protected override bool AreRouteParametersPreserved { get diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs index b26d7a06..a5030cdc 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; @@ -645,7 +646,7 @@ 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 + /// key value pairs for the passed in HTTP context. The casing of the keys corrected to be the same case as the values that are /// configured either in the dictionary or the collection. /// /// The HTTP context. @@ -656,9 +657,10 @@ protected virtual NameValueCollection GetCaseCorrectedQueryString(HttpContextBas 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 routeKeys = this.routeValues.Keys.ToArray(); + var caseInsensitiveRouteKeys = new HashSet(routeKeys, StringComparer.InvariantCultureIgnoreCase); var caseInsensitivePreservedRouteParameters = new HashSet(this.PreservedRouteParameters, StringComparer.InvariantCultureIgnoreCase); - var result = new NameValueCollection(); + var result = new NameValueCollection(queryStringValues.Count); foreach (var key in queryStringValues.AllKeys) { @@ -667,11 +669,11 @@ protected virtual NameValueCollection GetCaseCorrectedQueryString(HttpContextBas { if (caseInsensitivePreservedRouteParameters.Contains(key)) { - result.AddWithCaseCorrection(key, queryStringValues[key], caseInsensitivePreservedRouteParameters); + result.AddWithCaseCorrection(key, queryStringValues[key], this.PreservedRouteParameters); } else if (caseInsensitiveRouteKeys.Contains(key)) { - result.AddWithCaseCorrection(key, queryStringValues[key], caseInsensitiveRouteKeys); + result.AddWithCaseCorrection(key, queryStringValues[key], routeKeys); } else {