From 186b1b1f1b04d1b14827cf55d101e564b6bfc657 Mon Sep 17 00:00:00 2001 From: Artyom Baranovskiy Date: Tue, 12 Mar 2013 09:24:22 +0300 Subject: [PATCH 1/2] Implement loading inherited attributes - The attribute value is got from current node OR from the closest parent node which contains not-null/non-empty value - Refactor getting inherited route values to remove several hard-coded strings and prevent copy-paste --- .../DefaultSiteMapProvider.cs | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/DefaultSiteMapProvider.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/DefaultSiteMapProvider.cs index 5ab257ea..bc412b5e 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/DefaultSiteMapProvider.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/DefaultSiteMapProvider.cs @@ -1442,36 +1442,13 @@ protected MvcSiteMapNode GetSiteMapNodeFromXmlElement(XElement node, SiteMapNode siteMapNode.ResourceKey = implicitResourceKey; // Create a route data dictionary - IDictionary routeValues = new Dictionary(); - AttributesToRouteValues(node, siteMapNode, routeValues); - - // Inherit area and controller from parent - if (parentMvcNode != null) - { - if (siteMapNode["area"] == null) - { - siteMapNode["area"] = parentMvcNode.Area; - routeValues.Add("area", parentMvcNode.Area); - } - if (node.GetAttributeValue("controller") == "") - { - siteMapNode["controller"] = parentMvcNode.Controller; - routeValues.Add("controller", parentMvcNode.Controller); - } - var action = "action"; - if (node.GetAttributeValue(action) == String.Empty) - { - siteMapNode[action] = parentMvcNode.Action; - routeValues.Add(action, parentMvcNode.Action); - } - } + siteMapNode.RouteValues = new Dictionary(); + AttributesToRouteValues(node, siteMapNode, siteMapNode.RouteValues); - // Add defaults for area - if (!routeValues.ContainsKey("area")) - { - siteMapNode["area"] = ""; - routeValues.Add("area", ""); - } + // Load inherited attributes + LoadInheritedAttribute("area", node, siteMapNode, parentMvcNode, defaultValue: string.Empty, isRouteValue: true); + LoadInheritedAttribute("controller", node, siteMapNode, parentMvcNode, isRouteValue: true); + LoadInheritedAttribute("action", node, siteMapNode, parentMvcNode, isRouteValue: true); // Add defaults for SiteMapNodeUrlResolver if (siteMapNode.UrlResolver == null) @@ -1497,13 +1474,10 @@ protected MvcSiteMapNode GetSiteMapNodeFromXmlElement(XElement node, SiteMapNode var item = inheritedRouteParameter.Trim(); if (parentMvcNode != null && parentMvcNode.RouteValues.ContainsKey(item)) { - routeValues[item] = parentMvcNode.RouteValues[item]; + siteMapNode.RouteValues[item] = parentMvcNode.RouteValues[item]; } } - // Add route values to sitemap node - siteMapNode.RouteValues = routeValues; - // Add node's route defaults var httpContext = new HttpContextWrapper(HttpContext.Current); RouteData routeData = siteMapNode.GetRouteData(httpContext); @@ -1791,6 +1765,33 @@ protected void DecodeExternalUrl(SiteMapNode node) node.Url = HttpContext.Current.Server.UrlDecode(node.Url); } + /// + /// Get the attribute value from current node or from the parent nodes + /// + /// Name of the attribute + /// Xml node + /// MvcSiteMapNode to set the attribute to. + /// Parent MvcSiteMapNode + /// Default attribute value + /// If this flag is set to "true", than the attribute value will also be added to routeValues + private void LoadInheritedAttribute(string attributeName, XElement xmlNode, MvcSiteMapNode siteMapNode, MvcSiteMapNode parentNode, string defaultValue = null, bool isRouteValue = false) + { + var value = xmlNode.GetAttributeValue(attributeName); + var currentNode = parentNode; + + while(currentNode != null && string.IsNullOrEmpty(value)) + { + value = currentNode[attributeName]; + currentNode = currentNode.ParentNode as MvcSiteMapNode; + } + + siteMapNode[attributeName] = value ?? defaultValue; + if(isRouteValue) + { + siteMapNode.RouteValues[attributeName] = value ?? defaultValue; + } + } + #endregion } } From 78bed02a7fb4f9c2e882007754353b1536ad3584 Mon Sep 17 00:00:00 2001 From: Artyom Baranovskiy Date: Tue, 12 Mar 2013 09:43:59 +0300 Subject: [PATCH 2/2] Add config property to setup custom inherited attributes --- .../DefaultSiteMapProvider.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/DefaultSiteMapProvider.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/DefaultSiteMapProvider.cs index bc412b5e..8d6a1aa9 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/DefaultSiteMapProvider.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/DefaultSiteMapProvider.cs @@ -25,8 +25,16 @@ namespace MvcSiteMapProvider public class DefaultSiteMapProvider : StaticSiteMapProvider { + #region Attribute names + + protected const string AttributesToInheritKey = "attributesToInherit"; + + #endregion + #region Private + private readonly char[] configValueSeparators = new[] { ';', ',' }; + protected const string RootName = "mvcSiteMap"; protected const string NodeName = "mvcSiteMapNode"; protected readonly XNamespace ns = "http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0"; @@ -42,6 +50,8 @@ public class DefaultSiteMapProvider protected List excludeAssembliesForScan = new List(); protected List includeAssembliesForScan = new List(); protected List attributesToIgnore = new List(); + protected string[] attributesToInherit = new string[0]; + #endregion #region Properties @@ -296,6 +306,12 @@ public override void Initialize(string name, NameValueCollection attributes) } } + // Which attributes in the sitemap XML should be inherited from parent nodes? + if(!string.IsNullOrEmpty(attributes[AttributesToInheritKey])) + { + attributesToInherit = attributes[AttributesToInheritKey].Split(configValueSeparators); + } + // Is a node key generator given? if (!string.IsNullOrEmpty(attributes["nodeKeyGenerator"])) { @@ -1450,6 +1466,11 @@ protected MvcSiteMapNode GetSiteMapNodeFromXmlElement(XElement node, SiteMapNode LoadInheritedAttribute("controller", node, siteMapNode, parentMvcNode, isRouteValue: true); LoadInheritedAttribute("action", node, siteMapNode, parentMvcNode, isRouteValue: true); + foreach(var attributeName in attributesToInherit) + { + LoadInheritedAttribute(attributeName, node, siteMapNode, parentMvcNode); + } + // Add defaults for SiteMapNodeUrlResolver if (siteMapNode.UrlResolver == null) {