diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMap.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMap.cs index ff23e1d8..4d8821be 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMap.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMap.cs @@ -51,4 +51,12 @@ public interface ISiteMap [Obsolete("ResolveActionMethodParameters is deprecated and will be removed in version 5.")] IEnumerable ResolveActionMethodParameters(string areaName, string controllerName, string actionMethodName); } + + public static class SiteMapExtensions + { + public static string GetUrlContextKey(this ISiteMap siteMap) + { + return "__MVCSITEMAP_" + siteMap.CacheKey + "_UrlContext_" + siteMap.IsReadOnly.ToString() + "_"; + } + } } diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMap.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMap.cs index 2c719d6d..4dfc36ab 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMap.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMap.cs @@ -86,8 +86,17 @@ public override bool IsAccessibleToUser(ISiteMapNode node) var result = this.requestCache.GetValue(key); if (result == null) { + // Fix for #272 - Change the context of the URL cache to ensure + // that the AclModule doesn't prevent manually setting route values + // from having any effect on the URL. This setting takes effect in + // the RequestCacheableSiteMapNode.Url property. + var urlContextKey = this.GetUrlContextKey(); + this.requestCache.SetValue(urlContextKey, "AclModule"); result = base.IsAccessibleToUser(node); this.requestCache.SetValue(key, (bool)result); + + // Restore the URL context. + this.requestCache.SetValue(urlContextKey, string.Empty); } return (bool)result; } diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMapNode.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMapNode.cs index 8a60a975..550cdd5f 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMapNode.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/RequestCacheableSiteMapNode.cs @@ -124,7 +124,16 @@ public override bool IsVisible(IDictionary sourceMetadata) public override string Url { - get { return this.GetCachedOrMemberValue(() => base.Url, "Url", true); } + get + { + // Fix for #272 - Change the context of the URL cache to ensure + // that the AclModule doesn't prevent manually setting route values + // from having any effect on the URL. + var urlContext = this.requestCache.GetValue(this.SiteMap.GetUrlContextKey()); + var memberName = "Url" + (string.IsNullOrEmpty(urlContext) ? string.Empty : "_" + urlContext); + + return this.GetCachedOrMemberValue(() => base.Url, memberName, true); + } set { base.Url = value; } }