diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/AspNetSiteMapBuilder.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/AspNetSiteMapBuilder.cs index 528e0ada..da3940f8 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/AspNetSiteMapBuilder.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/AspNetSiteMapBuilder.cs @@ -129,6 +129,7 @@ protected virtual ISiteMapNode GetSiteMapNodeFromProviderNode(ISiteMap siteMap, siteMapNode.HttpMethod = node.GetAttributeValueOrFallback("httpMethod", "*").ToUpperInvariant(); siteMapNode.Url = node.Url; siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true")); + siteMapNode.IncludeAmbientRequestValues = bool.Parse(node.GetAttributeValueOrFallback("includeAmbientRequestValues", "false")); siteMapNode.CanonicalUrl = node.GetAttributeValue("canonicalUrl"); siteMapNode.CanonicalKey = node.GetAttributeValue("canonicalKey"); siteMapNode.MetaRobotsValues.AddRange(node.GetAttributeValue("metaRobotsValues"), new[] { ' ' }); @@ -151,7 +152,7 @@ protected virtual ISiteMapNode GetSiteMapNodeFromProviderNode(ISiteMap siteMap, } siteMapNode.PreservedRouteParameters.AddRange(node.GetAttributeValue("preservedRouteParameters"), new[] { ',', ';' }); siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver"); - + // Add inherited route values to sitemap node foreach (var inheritedRouteParameter in node.GetAttributeValue("inheritedRouteParameters").Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)) { diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/AspNetSiteMapNodeProvider.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/AspNetSiteMapNodeProvider.cs index 5ece1af5..4b32fa70 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/AspNetSiteMapNodeProvider.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/AspNetSiteMapNodeProvider.cs @@ -126,6 +126,7 @@ protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromProviderNode(Sy siteMapNode.HttpMethod = node.GetAttributeValueOrFallback("httpMethod", "*").ToUpperInvariant(); siteMapNode.Url = node.Url; siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true")); + siteMapNode.IncludeAmbientRequestValues = bool.Parse(node.GetAttributeValueOrFallback("includeAmbientRequestValues", "false")); siteMapNode.CanonicalUrl = node.GetAttributeValue("canonicalUrl"); siteMapNode.CanonicalKey = node.GetAttributeValue("canonicalKey"); siteMapNode.MetaRobotsValues.AddRange(node.GetAttributeValue("metaRobotsValues"), new[] { ' ' }); diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReflectionSiteMapBuilder.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReflectionSiteMapBuilder.cs index b13a8152..cb9b2ab5 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReflectionSiteMapBuilder.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReflectionSiteMapBuilder.cs @@ -451,6 +451,7 @@ protected virtual ISiteMapNode GetSiteMapNodeFromMvcSiteMapNodeAttribute(ISiteMa siteMapNode.HttpMethod = httpMethod; if (!string.IsNullOrEmpty(attribute.Url)) siteMapNode.Url = attribute.Url; siteMapNode.CacheResolvedUrl = attribute.CacheResolvedUrl; + siteMapNode.IncludeAmbientRequestValues = attribute.IncludeAmbientRequestValues; siteMapNode.CanonicalUrl = attribute.CanonicalUrl; siteMapNode.CanonicalKey = attribute.CanonicalKey; siteMapNode.MetaRobotsValues.AddRange(attribute.MetaRobotsValues); @@ -464,7 +465,7 @@ protected virtual ISiteMapNode GetSiteMapNodeFromMvcSiteMapNodeAttribute(ISiteMa siteMapNode.RouteValues.AddRange(attribute.Attributes, false); siteMapNode.PreservedRouteParameters.AddRange(attribute.PreservedRouteParameters, new[] { ',', ';' }); siteMapNode.UrlResolver = attribute.UrlResolver; - + // Specified area, controller and action properties will override any // provided in the attributes collection. if (!string.IsNullOrEmpty(area)) siteMapNode.RouteValues.Add("area", area); diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReflectionSiteMapNodeProvider.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReflectionSiteMapNodeProvider.cs index d7f1a4af..571a429d 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReflectionSiteMapNodeProvider.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReflectionSiteMapNodeProvider.cs @@ -248,6 +248,7 @@ protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromMvcSiteMapNodeA node.HttpMethod = httpMethod; if (!string.IsNullOrEmpty(attribute.Url)) node.Url = attribute.Url; node.CacheResolvedUrl = attribute.CacheResolvedUrl; + node.IncludeAmbientRequestValues = attribute.IncludeAmbientRequestValues; node.CanonicalUrl = attribute.CanonicalUrl; node.CanonicalKey = attribute.CanonicalKey; node.MetaRobotsValues.AddRange(attribute.MetaRobotsValues); @@ -261,7 +262,7 @@ protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromMvcSiteMapNodeA node.RouteValues.AddRange(attribute.Attributes, false); node.PreservedRouteParameters.AddRange(attribute.PreservedRouteParameters, new[] { ',', ';' }); node.UrlResolver = attribute.UrlResolver; - + // Specified area, controller and action properties will override any // provided in the attributes collection. if (!string.IsNullOrEmpty(area)) node.RouteValues.Add("area", area); diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReservedAttributeNameProvider.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReservedAttributeNameProvider.cs index 05b7bb8b..9b2ae728 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReservedAttributeNameProvider.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/ReservedAttributeNameProvider.cs @@ -67,6 +67,7 @@ protected virtual bool IsKnownAttribute(string attributeName) || attributeName == "imageUrl" || attributeName == "inheritedRouteParameters" || attributeName == "preservedRouteParameters" + || attributeName == "includeAmbientRequestValues" || attributeName == "canonicalUrl" || attributeName == "canonicalKey" || attributeName == "metaRobotsValues"; diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/XmlSiteMapBuilder.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/XmlSiteMapBuilder.cs index a8fe9343..3faecadc 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/XmlSiteMapBuilder.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/XmlSiteMapBuilder.cs @@ -154,6 +154,7 @@ protected virtual ISiteMapNode GetSiteMapNodeFromXmlElement(ISiteMap siteMap, XE siteMapNode.HttpMethod = httpMethod; siteMapNode.Url = url; siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true")); + siteMapNode.IncludeAmbientRequestValues = bool.Parse(node.GetAttributeValueOrFallback("includeAmbientRequestValues", "false")); siteMapNode.CanonicalUrl = node.GetAttributeValue("canonicalUrl"); siteMapNode.CanonicalKey = node.GetAttributeValue("canonicalKey"); siteMapNode.MetaRobotsValues.AddRange(node.GetAttributeValue("metaRobotsValues"), new[] { ' ' }); @@ -169,7 +170,7 @@ protected virtual ISiteMapNode GetSiteMapNodeFromXmlElement(ISiteMap siteMap, XE siteMapNode.RouteValues.AddRange(node, false); siteMapNode.PreservedRouteParameters.AddRange(node.GetAttributeValue("preservedRouteParameters"), new[] { ',', ';' }); siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver"); - + // Area and controller may need inheriting from the parent node, so set (or reset) them explicitly siteMapNode.Area = area; siteMapNode.Controller = controller; diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/XmlSiteMapNodeProvider.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/XmlSiteMapNodeProvider.cs index fe625f84..53484ae4 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/XmlSiteMapNodeProvider.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Builder/XmlSiteMapNodeProvider.cs @@ -229,6 +229,7 @@ protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromXmlElement(XEle siteMapNode.HttpMethod = httpMethod; siteMapNode.Url = url; siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true")); + siteMapNode.IncludeAmbientRequestValues = bool.Parse(node.GetAttributeValueOrFallback("includeAmbientRequestValues", "false")); siteMapNode.CanonicalUrl = node.GetAttributeValue("canonicalUrl"); siteMapNode.CanonicalKey = node.GetAttributeValue("canonicalKey"); siteMapNode.MetaRobotsValues.AddRange(node.GetAttributeValue("metaRobotsValues"), new[] { ' ' }); @@ -242,7 +243,7 @@ protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromXmlElement(XEle siteMapNode.RouteValues.AddRange(node, false); siteMapNode.PreservedRouteParameters.AddRange(node.GetAttributeValue("preservedRouteParameters"), new[] { ',', ';' }); siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver"); - + // Area and controller may need inheriting from the parent node, so set (or reset) them explicitly siteMapNode.Area = area; siteMapNode.Controller = controller; diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/DynamicNode.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/DynamicNode.cs index d572775b..2c9dac90 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/DynamicNode.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/DynamicNode.cs @@ -191,6 +191,13 @@ public virtual UpdatePriority UpdatePriority /// public virtual bool? Clickable { get; set; } + /// + /// Gets or sets a value indicating whether to include ambient request values + /// (from the RouteValues and/or query string) when resolving URLs. + /// + /// true to include ambient values (like MVC does); otherwise false. + public virtual bool? IncludeAmbientRequestValues { get; set; } + /// /// Copies the values for matching properties on an instance, but /// doesn't overwrite any values that are not set in this instance. @@ -276,6 +283,8 @@ public virtual void SafeCopyTo(ISiteMapNode node) node.UrlResolver = this.UrlResolver; if (this.Clickable != null) node.Clickable = (bool)this.Clickable; + if (this.IncludeAmbientRequestValues != null) + node.IncludeAmbientRequestValues = (bool)this.IncludeAmbientRequestValues; } diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/IMvcSiteMapNodeAttribute.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/IMvcSiteMapNodeAttribute.cs index 7dbb1ed1..bec5d984 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/IMvcSiteMapNodeAttribute.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/IMvcSiteMapNodeAttribute.cs @@ -152,6 +152,13 @@ public interface IMvcSiteMapNodeAttribute /// string PreservedRouteParameters { get; set; } + /// + /// Gets or sets a value indicating whether to include ambient request values + /// (from the RouteValues and/or query string) when resolving URLs. + /// + /// true to include ambient values (like MVC does); otherwise false. + bool IncludeAmbientRequestValues { get; set; } + /// /// Gets or sets the attributes (optional). /// diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMapNode.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMapNode.cs index 685f0f9d..a27bdcff 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMapNode.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMapNode.cs @@ -59,6 +59,7 @@ public interface ISiteMapNode string ResolvedUrl { get; } bool CacheResolvedUrl { get; set; } void ResolveUrl(); + bool IncludeAmbientRequestValues { get; set; } bool HasAbsoluteUrl(); bool HasExternalUrl(HttpContextBase httpContext); @@ -74,7 +75,7 @@ public interface ISiteMapNode IPreservedRouteParameterCollection PreservedRouteParameters { get; } RouteData GetRouteData(HttpContextBase httpContext); bool MatchesRoute(IDictionary routeValues); - + string Area { get; set; } string Controller { get; set; } string Action { get; set; } diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/LockableSiteMapNode.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/LockableSiteMapNode.cs index 3cebe9f1..c5aaca06 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/LockableSiteMapNode.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/LockableSiteMapNode.cs @@ -269,6 +269,20 @@ public override bool CacheResolvedUrl } } + /// + /// Gets or sets a value indicating whether to include ambient request values + /// (from the RouteValues and/or query string) when resolving URLs. + /// + /// true to include ambient values (like MVC does); otherwise false. + public override bool IncludeAmbientRequestValues + { + get { return base.IncludeAmbientRequestValues; } + set + { + this.ThrowIfReadOnly("IncludeAmbientRequestValues"); + base.IncludeAmbientRequestValues = value; + } + } /// /// Sets the ResolvedUrl using the current Url or Url resolver. @@ -279,7 +293,6 @@ public override void ResolveUrl() base.ResolveUrl(); } - #endregion #region Canonical Tag diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapNodeAttribute.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapNodeAttribute.cs index 7e04900b..93faa029 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapNodeAttribute.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapNodeAttribute.cs @@ -15,6 +15,7 @@ public class MvcSiteMapNodeAttribute : Attribute, IMvcSiteMapNodeAttribute public MvcSiteMapNodeAttribute() { Clickable = true; + IncludeAmbientRequestValues = false; } /// @@ -163,6 +164,13 @@ public MvcSiteMapNodeAttribute() /// public string PreservedRouteParameters { get; set; } + /// + /// Gets or sets a value indicating whether to include ambient request values + /// (from the RouteValues and/or query string) when resolving URLs. + /// + /// true to include ambient values (like MVC does); otherwise false. + public bool IncludeAmbientRequestValues { get; set; } + /// /// Gets or sets the attributes (optional). /// diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs index c5f16eba..7e195816 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNode.cs @@ -375,7 +375,7 @@ public override string Url public override void ResolveUrl() { if (this.CacheResolvedUrl && string.IsNullOrEmpty(this.UnresolvedUrl) && - this.preservedRouteParameters.Count == 0 && !this.RouteValues.ContainsCustomKeys) + this.preservedRouteParameters.Count == 0 && !this.IncludeAmbientRequestValues) { this.resolvedUrl = this.GetResolvedUrl(); } @@ -389,6 +389,13 @@ protected string GetResolvedUrl() this.UrlResolver, this, this.Area, this.Controller, this.Action, this.RouteValues); } + /// + /// Gets or sets a value indicating whether to include ambient request values + /// (from the RouteValues and/or query string) when resolving URLs. + /// + /// true to include ambient values (like MVC does); otherwise false. + public override bool IncludeAmbientRequestValues { get; set; } + /// /// Gets a boolean value that indicates this is an external URL by checking whether it /// looks like an absolute path. @@ -723,6 +730,7 @@ public override void CopyTo(ISiteMapNode node) node.Route = this.Route; this.RouteValues.CopyTo(node.RouteValues); this.PreservedRouteParameters.CopyTo(node.PreservedRouteParameters); + node.IncludeAmbientRequestValues = this.IncludeAmbientRequestValues; // NOTE: Area, Controller, and Action are covered under RouteValues. } diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNodeSecurityBase.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNodeSecurityBase.cs index 675d2b4b..d7e9981f 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNodeSecurityBase.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMapNodeSecurityBase.cs @@ -69,6 +69,7 @@ public virtual bool IsAccessibleToUser() public abstract string ResolvedUrl { get; } public abstract bool CacheResolvedUrl { get; set; } public abstract void ResolveUrl(); + public abstract bool IncludeAmbientRequestValues { get; set; } public abstract bool HasAbsoluteUrl(); public abstract bool HasExternalUrl(HttpContextBase httpContext); public abstract string CanonicalUrl { get; set; } diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/UrlResolver/SiteMapNodeUrlResolver.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/UrlResolver/SiteMapNodeUrlResolver.cs index 4f5461e8..8d58d798 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/UrlResolver/SiteMapNodeUrlResolver.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/UrlResolver/SiteMapNodeUrlResolver.cs @@ -69,7 +69,7 @@ protected virtual string ResolveRouteUrl(ISiteMapNode node, string area, string // which doesn't consume resources using (var nullWriter = new StreamWriter(Stream.Null)) { - var requestContext = this.CreateRequestContext(node, true, nullWriter); + var requestContext = this.CreateRequestContext(node, nullWriter); result = this.ResolveRouteUrl(node, area, controller, action, routeValues, requestContext); } @@ -110,9 +110,9 @@ protected virtual HttpContextBase CreateHttpContext(ISiteMapNode node, TextWrite return this.mvcContextFactory.CreateHttpContext(node, uri, writer); } - protected virtual RequestContext CreateRequestContext(ISiteMapNode node, bool includeAmbientRequestValues, TextWriter writer) + protected virtual RequestContext CreateRequestContext(ISiteMapNode node, TextWriter writer) { - if (!includeAmbientRequestValues) + if (!node.IncludeAmbientRequestValues) { var httpContext = this.CreateHttpContext(node, writer); return this.mvcContextFactory.CreateRequestContext(httpContext); diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Xml/MvcSiteMapSchema.xsd b/src/MvcSiteMapProvider/MvcSiteMapProvider/Xml/MvcSiteMapSchema.xsd index 2a291612..591e0744 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Xml/MvcSiteMapSchema.xsd +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Xml/MvcSiteMapSchema.xsd @@ -137,6 +137,14 @@ + + + + Optional. Whether or not to include request route values and/or query string values when resolving the + URL (for route/action URLs only). Default is false. + + + @@ -144,7 +152,6 @@ - @@ -159,7 +166,6 @@ - @@ -167,7 +173,6 @@ - @@ -175,7 +180,6 @@ - @@ -191,7 +195,6 @@ - @@ -199,7 +202,6 @@ - @@ -207,7 +209,6 @@ -