protected virtual IEnumerable<ISiteMapNodeToParentRelation> LoadSiteMapNodesFromXml(XDocument xml, ISiteMapNodeHelper helper)
        {
            var result = new List<ISiteMapNodeToParentRelation>();
            xmlNameProvider.FixXmlNamespaces(xml);

            // Get the root mvcSiteMapNode element, and map this to an MvcSiteMapNode
            var rootElement = GetRootElement(xml);
            if (rootElement == null)
            {
                // No root element - inform the user this isn't allowed.
                throw new MvcSiteMapException(string.Format(Resources.Messages.XmlSiteMapNodeProviderRootNodeNotDefined, helper.SiteMapCacheKey));
            }
            // Add the root node
            var rootNode = GetRootNode(xml, rootElement, helper);
            if (includeRootNode)
            {
                result.Add(rootNode);
            }

            // Process our XML, passing in the main root sitemap node and xml element.
            result.AddRange(ProcessXmlNodes(rootNode.Node, rootElement, NodesToProcess.All, helper));

            // Done!
            return result;
        }
 public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
 {
     var result = new List<ISiteMapNodeToParentRelation>();
     foreach (var provider in this.siteMapNodeProviders)
     {
         result.AddRange(provider.GetSiteMapNodes(helper));
     }
     return result;
 }
        protected virtual IEnumerable <ISiteMapNodeToParentRelation> LoadSiteMapNodesNodesFromMvcSiteMapNodeAttributeDefinitions(
            IEnumerable <IMvcSiteMapNodeAttributeDefinition> definitions, ISiteMapNodeHelper helper)
        {
            var sourceNodes = new List <ISiteMapNodeToParentRelation>();

            sourceNodes.AddRange(this.CreateNodesFromAttributeDefinitions(definitions, helper));
            sourceNodes.AddRange(this.CreateDynamicNodes(sourceNodes, helper));

            return(sourceNodes);
        }
        protected virtual IEnumerable<ISiteMapNodeToParentRelation> LoadSiteMapNodesNodesFromMvcSiteMapNodeAttributeDefinitions(
            IEnumerable<IMvcSiteMapNodeAttributeDefinition> definitions, ISiteMapNodeHelper helper)
        {
            var sourceNodes = new List<ISiteMapNodeToParentRelation>();

            sourceNodes.AddRange(this.CreateNodesFromAttributeDefinitions(definitions, helper));
            sourceNodes.AddRange(this.CreateDynamicNodes(sourceNodes, helper));

            return sourceNodes;
        }
        public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            var result = new List<ISiteMapNodeToParentRelation>();

            var definitions = this.GetMvcSiteMapNodeAttributeDefinitions();
            result.AddRange(this.LoadSiteMapNodesNodesFromMvcSiteMapNodeAttributeDefinitions(definitions, helper));

            // Done!
            return result;
        }
Exemple #6
0
        public IEnumerable <ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            var result = new List <ISiteMapNodeToParentRelation>();

            foreach (var provider in this.siteMapNodeProviders)
            {
                result.AddRange(provider.GetSiteMapNodes(helper));
            }
            return(result);
        }
        public IEnumerable <ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            var result = new List <ISiteMapNodeToParentRelation>();

            var definitions = this.GetMvcSiteMapNodeAttributeDefinitions();

            result.AddRange(this.LoadSiteMapNodesNodesFromMvcSiteMapNodeAttributeDefinitions(definitions, helper));

            // Done!
            return(result);
        }
        protected virtual IList<ISiteMapNodeToParentRelation> CreateDynamicNodes(IList<ISiteMapNodeToParentRelation> sourceNodes, ISiteMapNodeHelper helper)
        {
            var result = new List<ISiteMapNodeToParentRelation>();
            foreach (var sourceNode in sourceNodes.Where(x => x.Node.HasDynamicNodeProvider).ToArray())
            {
                result.AddRange(helper.CreateDynamicNodes(sourceNode));

                // Remove the dynamic node from the sources - we are replacing its definition.
                sourceNodes.Remove(sourceNode);
            }
            return result;
        }
        /// <summary>
        /// Acquires the attributes from a given <see cref="T:IMvcSiteMapNodeAttribute"/>
        /// </summary>
        /// <param name="attribute">The source attribute.</param>
        /// <param name="attributes">The attribute dictionary to populate.</param>
        /// <param name="helper">The node helper.</param>
        /// <returns></returns>
        protected virtual void AcquireAttributesFrom(IMvcSiteMapNodeAttribute attribute, IDictionary<string, object> attributes, ISiteMapNodeHelper helper)
        {
            foreach (var att in attribute.Attributes)
            {
                var attributeName = att.Key.ToString();
                var attributeValue = att.Value;

                if (helper.ReservedAttributeNames.IsRegularAttribute(attributeName))
                {
                    attributes[attributeName] = attributeValue;
                }
            }
        }
        public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            var result = new List<ISiteMapNodeToParentRelation>();
            var provider = siteMapProvider.GetProvider();

            var rootNode = GetRootNode(provider, helper);
            if (this.includeRootNode)
            {
                result.Add(rootNode);
            }

            result.AddRange(ProcessNodes(rootNode, provider.RootNode, helper));

            return result;
        }
        protected virtual IEnumerable<ISiteMapNodeToParentRelation> ProcessNodes(ISiteMapNodeToParentRelation parentNode, System.Web.SiteMapNode providerParentNode, ISiteMapNodeHelper helper)
        {
            var result = new List<ISiteMapNodeToParentRelation>();

            foreach (System.Web.SiteMapNode childNode in providerParentNode.ChildNodes)
            {
                var node = GetSiteMapNodeFromProviderNode(childNode, parentNode.Node, helper);

                result.Add(node);

                // Continue recursively processing
                ProcessNodes(node, childNode, helper);
            }
            return result;
        }
        public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            var result = new List<ISiteMapNodeToParentRelation>();
            var xml = xmlSource.GetXml();
            if (xml != null)
            {
                result.AddRange(LoadSiteMapNodesFromXml(xml, helper));
            }
            else
            {
                // Throw exception because XML was not defined
                throw new MvcSiteMapException(String.Format(Resources.Messages.XmlSiteMapNodeProviderXmlNotDefined, helper.SiteMapCacheKey));
            }

            return result;
        }
        protected virtual IList<ISiteMapNodeToParentRelation> CreateNodesFromAttributeDefinitions(
            IEnumerable<IMvcSiteMapNodeAttributeDefinition> definitions, ISiteMapNodeHelper helper)
        {
            var result = new List<ISiteMapNodeToParentRelation>();
            foreach (var definition in definitions)
            {
                var node = this.CreateNodeFromAttributeDefinition(definition, helper);

                // Note: A null node indicates that it doesn't apply to the current siteMapCacheKey
                if (node != null)
                {
                    result.Add(node);
                }
            }
            return result;
        }
        public IEnumerable <ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            var result   = new List <ISiteMapNodeToParentRelation>();
            var provider = siteMapProvider.GetProvider();

            var rootNode = GetRootNode(provider, helper);

            if (this.includeRootNode)
            {
                result.Add(rootNode);
            }

            result.AddRange(ProcessNodes(rootNode, provider.RootNode, helper));

            return(result);
        }
        protected virtual IList <ISiteMapNodeToParentRelation> CreateNodesFromAttributeDefinitions(
            IEnumerable <IMvcSiteMapNodeAttributeDefinition> definitions, ISiteMapNodeHelper helper)
        {
            var result = new List <ISiteMapNodeToParentRelation>();

            foreach (var definition in definitions)
            {
                var node = this.CreateNodeFromAttributeDefinition(definition, helper);

                // Note: A null node indicates that it doesn't apply to the current siteMapCacheKey
                if (node != null)
                {
                    result.Add(node);
                }
            }
            return(result);
        }
        public IEnumerable <ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            var result = new List <ISiteMapNodeToParentRelation>();
            var xml    = xmlSource.GetXml();

            if (xml != null)
            {
                result.AddRange(LoadSiteMapNodesFromXml(xml, helper));
            }
            else
            {
                // Throw exception because XML was not defined
                throw new MvcSiteMapException(string.Format(Resources.Messages.XmlSiteMapNodeProviderXmlNotDefined, helper.SiteMapCacheKey));
            }

            return(result);
        }
        /// <summary>
        /// Maps an XMLElement from the XML file to an MvcSiteMapNode.
        /// </summary>
        /// <param name="node">The element to map.</param>
        /// <param name="parentNode">The parent ISiteMapNode</param>
        /// <param name="helper">The node helper.</param>
        /// <returns>An MvcSiteMapNode which represents the XMLElement.</returns>
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromXmlElement(XElement node, ISiteMapNode parentNode, ISiteMapNodeHelper helper)
        {
            // Get data required to generate the node instance

            // Get area and controller from node declaration or the parent node
            var area = this.InheritAreaIfNotProvided(node, parentNode);
            var controller = this.InheritControllerIfNotProvided(node, parentNode);
            var action = node.GetAttributeValue("action");
            var url = node.GetAttributeValue("url");
            var explicitKey = node.GetAttributeValue("key");
            var parentKey = parentNode == null ? "" : parentNode.Key;
            var httpMethod = node.GetAttributeValueOrFallback("httpMethod", HttpVerbs.Get.ToString()).ToUpper();
            var clickable = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true"));
            var title = node.GetAttributeValue("title");
            var implicitResourceKey = node.GetAttributeValue("resourceKey");

            // Generate key for node
            string key = helper.CreateNodeKey(
                parentKey,
                explicitKey,
                url,
                title,
                area,
                controller,
                action,
                httpMethod,
                clickable);

            // Create node
            var nodeParentMap = helper.CreateNode(key, parentKey, SourceName, implicitResourceKey);
            var siteMapNode = nodeParentMap.Node;

            // Assign values
            siteMapNode.Title = title;
            siteMapNode.Description = node.GetAttributeValue("description");
            siteMapNode.Attributes.AddRange(node, false);
            siteMapNode.Roles.AddRange(node.GetAttributeValue("roles"), new[] { ',', ';' });
            siteMapNode.Clickable = clickable;
            siteMapNode.VisibilityProvider = node.GetAttributeValue("visibilityProvider");
            siteMapNode.DynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider");
            siteMapNode.ImageUrl = node.GetAttributeValue("imageUrl");
            siteMapNode.ImageUrlProtocol = node.GetAttributeValue("imageUrlProtocol");
            siteMapNode.ImageUrlHostName = node.GetAttributeValue("imageUrlHostName");
            siteMapNode.TargetFrame = node.GetAttributeValue("targetFrame");
            siteMapNode.HttpMethod = httpMethod;
            siteMapNode.Url = url;
            siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true"));
            siteMapNode.IncludeAmbientValuesInUrl = bool.Parse(node.GetAttributeValueOrFallback("includeAmbientValuesInUrl", "false"));
            siteMapNode.Protocol = node.GetAttributeValue("protocol");
            siteMapNode.HostName = node.GetAttributeValue("hostName");
            siteMapNode.CanonicalKey = node.GetAttributeValue("canonicalKey");
            siteMapNode.CanonicalUrl = node.GetAttributeValue("canonicalUrl");
            siteMapNode.CanonicalUrlProtocol = node.GetAttributeValue("canonicalUrlProtocol");
            siteMapNode.CanonicalUrlHostName = node.GetAttributeValue("canonicalUrlHostName");
            siteMapNode.MetaRobotsValues.AddRange(node.GetAttributeValue("metaRobotsValues"), new[] { ' ' });
            siteMapNode.ChangeFrequency = (ChangeFrequency)Enum.Parse(typeof(ChangeFrequency), node.GetAttributeValueOrFallback("changeFrequency", "Undefined"));
            siteMapNode.UpdatePriority = (UpdatePriority)Enum.Parse(typeof(UpdatePriority), node.GetAttributeValueOrFallback("updatePriority", "Undefined"));
            siteMapNode.LastModifiedDate = DateTime.Parse(node.GetAttributeValueOrFallback("lastModifiedDate", DateTime.MinValue.ToString()));
            siteMapNode.Order = int.Parse(node.GetAttributeValueOrFallback("order", "0"));

            // Handle route details
            siteMapNode.Route = node.GetAttributeValue("route");
            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;
            siteMapNode.Action = action;

            // Add inherited route values to sitemap node
            foreach (var inheritedRouteParameter in node.GetAttributeValue("inheritedRouteParameters").Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var item = inheritedRouteParameter.Trim();
                if (node.Attribute(item) != null)
                    throw new MvcSiteMapException(string.Format(Resources.Messages.SiteMapNodeSameKeyInRouteValueAndInheritedRouteParameter, key, title, item));

                if (parentNode.RouteValues.ContainsKey(item))
                {
                    siteMapNode.RouteValues.Add(item, parentNode.RouteValues[item]);
                }
            }

            return nodeParentMap;
        }
 protected virtual ISiteMapNodeToParentRelation GetRootNode(SiteMapProvider provider, ISiteMapNodeHelper helper)
 {
     var root = provider.RootNode;
     return helper.CreateNode(root.Key, null, SourceName, root.ResourceKey);
 }
        protected virtual IList <ISiteMapNodeToParentRelation> CreateDynamicNodes(IList <ISiteMapNodeToParentRelation> sourceNodes, ISiteMapNodeHelper helper)
        {
            var result = new List <ISiteMapNodeToParentRelation>();

            foreach (var sourceNode in sourceNodes.Where(x => x.Node.HasDynamicNodeProvider).ToArray())
            {
                result.AddRange(helper.CreateDynamicNodes(sourceNode));

                // Remove the dynamic node from the sources - we are replacing its definition.
                sourceNodes.Remove(sourceNode);
            }
            return(result);
        }
        protected virtual IEnumerable <ISiteMapNodeToParentRelation> ProcessNodes(ISiteMapNodeToParentRelation parentNode, System.Web.SiteMapNode providerParentNode, ISiteMapNodeHelper helper)
        {
            var result = new List <ISiteMapNodeToParentRelation>();

            foreach (System.Web.SiteMapNode childNode in providerParentNode.ChildNodes)
            {
                var node = GetSiteMapNodeFromProviderNode(childNode, parentNode.Node, helper);

                result.Add(node);

                // Continue recursively processing
                ProcessNodes(node, childNode, helper);
            }
            return(result);
        }
        /// <summary>
        /// Gets the site map node from MVC site map node attribute.
        /// </summary>
        /// <param name="attribute">The attribute.</param>
        /// <param name="type">The type.</param>
        /// <param name="methodInfo">The method info.</param>
        /// <param name="helper">The node helper.</param>
        /// <returns></returns>
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromMvcSiteMapNodeAttribute(
            IMvcSiteMapNodeAttribute attribute, Type type, MethodInfo methodInfo, ISiteMapNodeHelper helper)
        {
            if (attribute == null)
            {
                throw new ArgumentNullException("attribute");
            }
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (!string.IsNullOrEmpty(attribute.SiteMapCacheKey))
            {
                // Return null if the attribute doesn't apply to this cache key
                if (!helper.SiteMapCacheKey.Equals(attribute.SiteMapCacheKey))
                {
                    return null;
                }
            }

            if (methodInfo == null) // try to find Index action
            {
                var ms = type.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(x => x.Name.Equals("Index"));
                foreach (MethodInfo m in ms)
                {
                    var pars = m.GetParameters();
                    if (pars.Length == 0)
                    {
                        methodInfo = m;
                        break;
                    }
                }
            }

            string area = "";
#pragma warning disable 612,618
            if (!string.IsNullOrEmpty(attribute.AreaName))
            {
                area = attribute.AreaName;
            }
#pragma warning restore 612,618
            if (string.IsNullOrEmpty(area) && !string.IsNullOrEmpty(attribute.Area))
            {
                area = attribute.Area;
            }
            // Determine area (will only work if controller is defined as [<Anything>.]Areas.<Area>.Controllers.<AnyController>)
            if (string.IsNullOrEmpty(area))
            {
                var m = Regex.Match(type.Namespace, @"(?:[^\.]+\.|\s+|^)Areas\.(?<areaName>[^\.]+)\.Controllers");
                if (m.Success)
                {
                    area = m.Groups["areaName"].Value;
                }
            }

            // Determine controller and (index) action
            string controller = type.Name.Substring(0, type.Name.IndexOf("Controller"));
            string action = (methodInfo != null ? methodInfo.Name : null) ?? "Index";
            
            if (methodInfo != null)
            {
                // handle ActionNameAttribute
                var actionNameAttribute = methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), true).FirstOrDefault() as ActionNameAttribute;
                if (actionNameAttribute != null)
                {
                    action = actionNameAttribute.Name;
                }
            }

            string httpMethod = (string.IsNullOrEmpty(attribute.HttpMethod) ? HttpVerbs.Get.ToString() : attribute.HttpMethod).ToUpper();

            // Handle title
            var title = attribute.Title;

            // Handle implicit resources
            var implicitResourceKey = attribute.ResourceKey;

            // Generate key for node
            string key = helper.CreateNodeKey(
                attribute.ParentKey,
                attribute.Key,
                attribute.Url,
                title,
                area,
                controller, action, httpMethod,
                attribute.Clickable);

            var nodeParentMap = helper.CreateNode(key, attribute.ParentKey, SourceName, implicitResourceKey);
            var node = nodeParentMap.Node;

            // Assign defaults
            node.Title = title;
            node.Description = attribute.Description;
            node.Attributes.AddRange(attribute.Attributes, false);
            node.Roles.AddRange(attribute.Roles);
            node.Clickable = attribute.Clickable;
            node.VisibilityProvider = attribute.VisibilityProvider;
            node.DynamicNodeProvider = attribute.DynamicNodeProvider;
            node.ImageUrl = attribute.ImageUrl;
            node.ImageUrlProtocol = attribute.ImageUrlProtocol;
            node.ImageUrlHostName = attribute.ImageUrlHostName;
            node.TargetFrame = attribute.TargetFrame;
            node.HttpMethod = httpMethod;
            if (!string.IsNullOrEmpty(attribute.Url)) node.Url = attribute.Url;
            node.CacheResolvedUrl = attribute.CacheResolvedUrl;
            node.IncludeAmbientValuesInUrl = attribute.IncludeAmbientValuesInUrl;
            node.Protocol = attribute.Protocol;
            node.HostName = attribute.HostName;
            node.CanonicalKey = attribute.CanonicalKey;
            node.CanonicalUrl = attribute.CanonicalUrl;
            node.CanonicalUrlProtocol = attribute.CanonicalUrlProtocol;
            node.CanonicalUrlHostName = attribute.CanonicalUrlHostName;
            node.MetaRobotsValues.AddRange(attribute.MetaRobotsValues);
            node.LastModifiedDate = string.IsNullOrEmpty(attribute.LastModifiedDate) ? DateTime.MinValue : DateTime.Parse(attribute.LastModifiedDate);
            node.ChangeFrequency = attribute.ChangeFrequency;
            node.UpdatePriority = attribute.UpdatePriority;
            node.Order = attribute.Order;

            // Handle route details
            node.Route = attribute.Route;
            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);
            if (!string.IsNullOrEmpty(controller)) node.RouteValues.Add("controller", controller);
            if (!string.IsNullOrEmpty(action)) node.RouteValues.Add("action", action);

            return nodeParentMap;
        }
Exemple #22
0
        /// <summary>
        /// Maps an XMLElement from the XML file to an MvcSiteMapNode.
        /// </summary>
        /// <param name="node">The element to map.</param>
        /// <param name="parentNode">The parent ISiteMapNode</param>
        /// <param name="helper">The node helper.</param>
        /// <returns>An MvcSiteMapNode which represents the XMLElement.</returns>
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromXmlElement(XElement node, ISiteMapNode parentNode, ISiteMapNodeHelper helper)
        {
            // Get area, controller and action from node declaration
            string area       = node.GetAttributeValue("area");
            string controller = node.GetAttributeValue("controller");
            var    parentKey  = parentNode == null ? "" : parentNode.Key;
            var    httpMethod = node.GetAttributeValueOrFallback("httpMethod", HttpVerbs.Get.ToString()).ToUpperInvariant();
            // Handle title and description
            var title       = node.GetAttributeValue("title");
            var description = String.IsNullOrEmpty(node.GetAttributeValue("description")) ? title : node.GetAttributeValue("description");

            // Generate key for node
            string key = helper.CreateNodeKey(
                parentKey,
                node.GetAttributeValue("key"),
                node.GetAttributeValue("url"),
                title,
                area,
                controller,
                node.GetAttributeValue("action"),
                httpMethod,
                !(node.GetAttributeValue("clickable") == "false"));

            // Handle implicit resources
            var implicitResourceKey = node.GetAttributeValue("resourceKey");

            // Create node
            var nodeParentMap = helper.CreateNode(key, parentKey, SourceName, implicitResourceKey);
            var siteMapNode   = nodeParentMap.Node;

            // Assign defaults
            siteMapNode.Title       = title;
            siteMapNode.Description = description;
            AcquireAttributesFrom(node, siteMapNode.Attributes, helper);
            AcquireRolesFrom(node, siteMapNode.Roles);
            siteMapNode.Clickable           = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true"));
            siteMapNode.VisibilityProvider  = node.GetAttributeValue("visibilityProvider");
            siteMapNode.DynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider");
            siteMapNode.ImageUrl            = node.GetAttributeValue("imageUrl");
            siteMapNode.TargetFrame         = node.GetAttributeValue("targetFrame");
            siteMapNode.HttpMethod          = httpMethod;
            siteMapNode.Url = node.GetAttributeValue("url");
            siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true"));
            siteMapNode.CanonicalUrl     = node.GetAttributeValue("canonicalUrl");
            siteMapNode.CanonicalKey     = node.GetAttributeValue("canonicalKey");
            this.AcquireMetaRobotsValuesFrom(node, siteMapNode.MetaRobotsValues);
            siteMapNode.ChangeFrequency  = (ChangeFrequency)Enum.Parse(typeof(ChangeFrequency), node.GetAttributeValueOrFallback("changeFrequency", "Undefined"));
            siteMapNode.UpdatePriority   = (UpdatePriority)Enum.Parse(typeof(UpdatePriority), node.GetAttributeValueOrFallback("updatePriority", "Undefined"));
            siteMapNode.LastModifiedDate = DateTime.Parse(node.GetAttributeValueOrFallback("lastModifiedDate", DateTime.MinValue.ToString()));
            siteMapNode.Order            = int.Parse(node.GetAttributeValueOrFallback("order", "0"));

            // Handle route details

            // Assign to node
            siteMapNode.Route = node.GetAttributeValue("route");
            AcquireRouteValuesFrom(node, siteMapNode.RouteValues, helper);
            AcquirePreservedRouteParametersFrom(node, siteMapNode.PreservedRouteParameters);
            siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver");

            // Add inherited route values to sitemap node
            foreach (var inheritedRouteParameter in node.GetAttributeValue("inheritedRouteParameters").Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var item = inheritedRouteParameter.Trim();
                if (siteMapNode.RouteValues.ContainsKey(item))
                {
                    throw new MvcSiteMapException(String.Format(Resources.Messages.SiteMapNodeSameKeyInRouteValueAndInheritedRouteParameter, key, title, item));
                }

                if (parentNode.RouteValues.ContainsKey(item))
                {
                    siteMapNode.RouteValues.Add(item, parentNode.RouteValues[item]);
                }
            }

            // Handle MVC details

            // Inherit area and controller from parent
            if (parentNode != null)
            {
                if (string.IsNullOrEmpty(area) && !siteMapNode.RouteValues.ContainsKey("area"))
                {
                    siteMapNode.Area = parentNode.Area;
                }
                if (string.IsNullOrEmpty(controller) && !siteMapNode.RouteValues.ContainsKey("controller"))
                {
                    siteMapNode.Controller = parentNode.Controller;
                }
            }

            // Add defaults for area
            if (!siteMapNode.RouteValues.ContainsKey("area"))
            {
                siteMapNode.RouteValues.Add("area", "");
            }

            return(nodeParentMap);
        }
        /// <summary>
        /// Gets the site map node from MVC site map node attribute.
        /// </summary>
        /// <param name="attribute">The attribute.</param>
        /// <param name="type">The type.</param>
        /// <param name="methodInfo">The method info.</param>
        /// <param name="helper">The node helper.</param>
        /// <returns></returns>
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromMvcSiteMapNodeAttribute(
            IMvcSiteMapNodeAttribute attribute, Type type, MethodInfo methodInfo, ISiteMapNodeHelper helper)
        {
            if (attribute == null)
            {
                throw new ArgumentNullException("attribute");
            }
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (!String.IsNullOrEmpty(attribute.SiteMapCacheKey))
            {
                // Return null if the attribute doesn't apply to this cache key
                if (!helper.SiteMapCacheKey.Equals(attribute.SiteMapCacheKey))
                {
                    return null;
                }
            }

            if (methodInfo == null) // try to find Index action
            {
                var ms = type.FindMembers(MemberTypes.Method, BindingFlags.Instance | BindingFlags.Public,
                                          (mi, o) => mi != null && string.Equals(mi.Name, "Index"), null);
                foreach (MethodInfo m in ms.OfType<MethodInfo>())
                {
                    var pars = m.GetParameters();
                    if (pars.Length == 0)
                    {
                        methodInfo = m;
                        break;
                    }
                }
            }

            string area = "";
            if (!String.IsNullOrEmpty(attribute.AreaName))
            {
                area = attribute.AreaName;
            }
            if (String.IsNullOrEmpty(area) && !String.IsNullOrEmpty(attribute.Area))
            {
                area = attribute.Area;
            }
            // Determine area (will only work if controller is defined as [<Anything>.]Areas.<Area>.Controllers.<AnyController>)
            if (String.IsNullOrEmpty(area))
            {
                var m = Regex.Match(type.Namespace, @"(?:[^\.]+\.|\s+|^)Areas\.(?<areaName>[^\.]+)\.Controllers");
                if (m.Success)
                {
                    area = m.Groups["areaName"].Value;
                }
            }

            // Determine controller and (index) action
            string controller = type.Name.Substring(0, type.Name.IndexOf("Controller"));
            string action = (methodInfo != null ? methodInfo.Name : null) ?? "Index";

            if (methodInfo != null)
            {
                // handle ActionNameAttribute
                var actionNameAttribute = methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), true).FirstOrDefault() as ActionNameAttribute;
                if (actionNameAttribute != null)
                {
                    action = actionNameAttribute.Name;
                }
            }

            string httpMethod = String.IsNullOrEmpty(attribute.HttpMethod) ? HttpVerbs.Get.ToString().ToUpperInvariant() : attribute.HttpMethod.ToUpperInvariant();

            // Handle title and description
            var title = attribute.Title;
            var description = String.IsNullOrEmpty(attribute.Description) ? title : attribute.Description;

            // Handle implicit resources
            var implicitResourceKey = attribute.ResourceKey;

            // Generate key for node
            string key = helper.CreateNodeKey(
                attribute.ParentKey,
                attribute.Key,
                attribute.Url,
                title,
                area,
                controller, action, httpMethod,
                attribute.Clickable);

            var nodeParentMap = helper.CreateNode(key, attribute.ParentKey, SourceName, implicitResourceKey);
            var node = nodeParentMap.Node;

            // Assign defaults
            node.Title = title;
            node.Description = description;
            AcquireAttributesFrom(attribute, node.Attributes, helper);
            AcquireRolesFrom(attribute, node.Roles);
            node.Clickable = attribute.Clickable;
            node.VisibilityProvider = attribute.VisibilityProvider;
            node.DynamicNodeProvider = attribute.DynamicNodeProvider;
            node.ImageUrl = attribute.ImageUrl;
            node.TargetFrame = attribute.TargetFrame;
            node.HttpMethod = httpMethod;
            if (!string.IsNullOrEmpty(attribute.Url)) node.Url = attribute.Url;
            node.CacheResolvedUrl = attribute.CacheResolvedUrl;
            node.CanonicalUrl = attribute.CanonicalUrl;
            node.CanonicalKey = attribute.CanonicalKey;
            AcquireMetaRobotsValuesFrom(attribute, node.MetaRobotsValues);
            node.LastModifiedDate = attribute.LastModifiedDate;
            node.ChangeFrequency = attribute.ChangeFrequency;
            node.UpdatePriority = attribute.UpdatePriority;
            node.Order = attribute.Order;

            // Handle route details
            node.Route = attribute.Route;
            AcquireRouteValuesFrom(attribute, node.RouteValues, helper);
            AcquirePreservedRouteParametersFrom(attribute, node.PreservedRouteParameters);
            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);
            if (!string.IsNullOrEmpty(controller)) node.RouteValues.Add("controller", controller);
            if (!string.IsNullOrEmpty(action)) node.RouteValues.Add("action", action);

            // Handle MVC details

            // Add defaults for area
            if (!node.RouteValues.ContainsKey("area"))
            {
                node.RouteValues.Add("area", "");
            }

            return nodeParentMap;
        }
        public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            // Try the API! Let us know if there is something we can do to make it better.

            // This is a replacement for all of the DynamicNodeProvider implementations within
            // the MvcMusicStore demo, to show how this could be done. Note that in a real-world scenario
            // you would need to remove all of the DynamicNodeProvider declarations in the SemanticSiteMapNodeProvider
            // because they would be completely unnecessary.

            // Be sure to try adding nodes yourself to see if you can suggest ways to make this
            // more intuitive, easier to read, or easier to write.

            using (var storeDB = new MusicStoreEntities())
            {
                // Create a node for each genre
                foreach (var genre in storeDB.Genres)
                {
                    // This is the original dynamic node definition

                    //DynamicNode dynamicNode = new DynamicNode("Genre_" + genre.Name, genre.Name);
                    //dynamicNode.RouteValues.Add("genre", genre.Name);

                    //yield return dynamicNode;

                    // This is the fluent API version.

                    // Note that because there is no inheritance when we do it this way, we are specifying controller and action here, too.

                    yield return helper.RegisterNode()
                        .MatchingRoute(x => x.WithController("Store").WithAction("Browse").AlwaysMatchingKey("browse").WithValue("genre", genre.Name))
                        .WithDisplayValues(x => x.WithTitle(genre.Name))
                        .WithKey("Genre_" + genre.Name)
                        .Single();
                }

                // Create a node for each album
                foreach (var album in storeDB.Albums.Include("Genre"))
                {
                    // This is the original dynamic node definition

                    //DynamicNode dynamicNode = new DynamicNode();
                    //dynamicNode.Title = album.Title;
                    //dynamicNode.ParentKey = "Genre_" + album.Genre.Name;
                    //dynamicNode.RouteValues.Add("id", album.AlbumId);

                    //if (album.Title.Contains("Hit") || album.Title.Contains("Best"))
                    //{
                    //    dynamicNode.Attributes.Add("bling", "<span style=\"color: Red;\">hot!</span>");
                    //}

                    //yield return dynamicNode;

                    // This is the fluent API version.

                    // Note that because there is no inheritance when we do it this way, we are specifying controller and action here, too.

                    var customAttributes = new Dictionary<string, object>();
                    if (album.Title.Contains("Hit") || album.Title.Contains("Best"))
                    {
                        customAttributes.Add("bling", "<span style=\"color: Red;\">hot!</span>");
                    }

                    yield return helper.RegisterNode()
                        .MatchingRoute(x => x.WithController("Store").WithAction("Details").WithValue("id", album.AlbumId))
                        .WithDisplayValues(x => x.WithTitle(album.Title))
                        .WithParentKey("Genre_" + album.Genre.Name)
                        .WithCustomAttributes(customAttributes)
                        .Single();
                }
            }
        }
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromProviderNode(System.Web.SiteMapNode node, ISiteMapNode parentNode, ISiteMapNodeHelper helper)
        {
            // Use the same keys as the underlying provider.
            string key = node.Key;
            var implicitResourceKey = node.ResourceKey;

            // Create Node
            var nodeParentMap = helper.CreateNode(key, parentNode.Key, SourceName, implicitResourceKey);
            var siteMapNode = nodeParentMap.Node;

            siteMapNode.Title = node.Title;
            siteMapNode.Description = node.Description;
            if (this.reflectAttributes)
            {
                // Unfortunately, the ASP.NET implementation uses a protected member variable to store
                // the attributes, so there is no way to loop through them without reflection or some
                // fancy dynamic subclass implementation.
                var attributeDictionary = node.GetPrivateFieldValue<NameValueCollection>("_attributes");
                siteMapNode.Attributes.AddRange(attributeDictionary, false);
            }
            siteMapNode.Roles.AddRange(node.Roles);
            siteMapNode.Clickable = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true"));
            siteMapNode.VisibilityProvider = node.GetAttributeValue("visibilityProvider");
            siteMapNode.DynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider");
            siteMapNode.ImageUrl = node.GetAttributeValue("imageUrl");
            siteMapNode.ImageUrlProtocol = node.GetAttributeValue("imageUrlProtocol");
            siteMapNode.ImageUrlHostName = node.GetAttributeValue("imageUrlHostName");
            siteMapNode.TargetFrame = node.GetAttributeValue("targetFrame");
            siteMapNode.HttpMethod = node.GetAttributeValueOrFallback("httpMethod", "*").ToUpperInvariant();
            siteMapNode.Url = node.Url;
            siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true"));
            siteMapNode.IncludeAmbientValuesInUrl = bool.Parse(node.GetAttributeValueOrFallback("includeAmbientValuesInUrl", "false"));
            siteMapNode.Protocol = node.GetAttributeValue("protocol");
            siteMapNode.HostName = node.GetAttributeValue("hostName");
            siteMapNode.CanonicalKey = node.GetAttributeValue("canonicalKey");
            siteMapNode.CanonicalUrl = node.GetAttributeValue("canonicalUrl");
            siteMapNode.CanonicalUrlProtocol = node.GetAttributeValue("canonicalUrlProtocol");
            siteMapNode.CanonicalUrlHostName = node.GetAttributeValue("canonicalUrlHostName");
            siteMapNode.MetaRobotsValues.AddRange(node.GetAttributeValue("metaRobotsValues"), new[] { ' ' });
            siteMapNode.ChangeFrequency = (ChangeFrequency)Enum.Parse(typeof(ChangeFrequency), node.GetAttributeValueOrFallback("changeFrequency", "Undefined"));
            siteMapNode.UpdatePriority = (UpdatePriority)Enum.Parse(typeof(UpdatePriority), node.GetAttributeValueOrFallback("updatePriority", "Undefined"));
            siteMapNode.LastModifiedDate = DateTime.Parse(node.GetAttributeValueOrFallback("lastModifiedDate", DateTime.MinValue.ToString()));
            siteMapNode.Order = int.Parse(node.GetAttributeValueOrFallback("order", "0"));

            // Handle route details

            // Assign to node
            siteMapNode.Route = node.GetAttributeValue("route");
            if (this.reflectRouteValues)
            {
                // Unfortunately, the ASP.NET implementation uses a protected member variable to store
                // the attributes, so there is no way to loop through them without reflection or some
                // fancy dynamic subclass implementation.
                var attributeDictionary = node.GetPrivateFieldValue<NameValueCollection>("_attributes");
                siteMapNode.RouteValues.AddRange(attributeDictionary);
            }
            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))
            {
                var item = inheritedRouteParameter.Trim();
                if (parentNode.RouteValues.ContainsKey(item))
                {
                    siteMapNode.RouteValues.Add(item, parentNode.RouteValues[item]);
                }
            }

            // Handle MVC details

            // Get area and controller from node declaration
            siteMapNode.Area = this.InheritAreaIfNotProvided(node, parentNode);
            siteMapNode.Controller = this.InheritControllerIfNotProvided(node, parentNode);

            return nodeParentMap;
        }
        /// <summary>
        /// Recursively processes our XML document, parsing our siteMapNodes and dynamicNode(s).
        /// </summary>
        /// <param name="parentNode">The parent node to process.</param>
        /// <param name="parentElement">The corresponding parent XML element.</param>
        /// <param name="processFlags">Flags to indicate which nodes to process.</param>
        /// <param name="helper">The node helper.</param>
        protected virtual IList <ISiteMapNodeToParentRelation> ProcessXmlNodes(ISiteMapNode parentNode, XElement parentElement, NodesToProcess processFlags, ISiteMapNodeHelper helper)
        {
            var  result = new List <ISiteMapNodeToParentRelation>();
            bool processStandardNodes = (processFlags & NodesToProcess.StandardNodes) == NodesToProcess.StandardNodes;
            bool processDynamicNodes  = (processFlags & NodesToProcess.DynamicNodes) == NodesToProcess.DynamicNodes;

            foreach (XElement node in parentElement.Elements())
            {
                if (node.Name != xmlNameProvider.NodeName)
                {
                    // If the current node is not one of the known node types throw and exception
                    throw new MvcSiteMapException(string.Format(Resources.Messages.XmlSiteMapNodeProviderInvalidSiteMapElement, helper.SiteMapCacheKey));
                }

                var child = GetSiteMapNodeFromXmlElement(node, parentNode, helper);

                if (processStandardNodes && !child.Node.HasDynamicNodeProvider)
                {
                    result.Add(child);

                    // Continue recursively processing the XML file.
                    result.AddRange(ProcessXmlNodes(child.Node, node, processFlags, helper));
                }
                else if (processDynamicNodes && child.Node.HasDynamicNodeProvider)
                {
                    // We pass in the parent node key as the default parent because the dynamic node (child) is never added to the sitemap.
                    var dynamicNodes = helper.CreateDynamicNodes(child, parentNode.Key);

                    foreach (var dynamicNode in dynamicNodes)
                    {
                        result.Add(dynamicNode);

                        if (!this.useNestedDynamicNodeRecursion)
                        {
                            // Recursively add non-dynamic children for every dynamic node
                            result.AddRange(ProcessXmlNodes(dynamicNode.Node, node, NodesToProcess.StandardNodes, helper));
                        }
                        else
                        {
                            // Recursively process both dynamic nodes and static nodes.
                            // This is to allow V3 recursion behavior for those who depended on it - it is not a feature.
                            result.AddRange(ProcessXmlNodes(dynamicNode.Node, node, NodesToProcess.All, helper));
                        }
                    }

                    if (!this.useNestedDynamicNodeRecursion)
                    {
                        // Process the next nested dynamic node provider. We pass in the parent node as the default
                        // parent because the dynamic node definition node (child) is never added to the sitemap.
                        result.AddRange(ProcessXmlNodes(parentNode, node, NodesToProcess.DynamicNodes, helper));
                    }
                    else
                    {
                        // Continue recursively processing the XML file.
                        // Can't figure out why this is here, but this is the way it worked in V3 and if
                        // anyone depends on the broken recursive behavior, they probably also depend on this.
                        result.AddRange(ProcessXmlNodes(child.Node, node, processFlags, helper));
                    }
                }
            }
            return(result);
        }
        /// <summary>
        /// Acquires the attributes from a given <see cref="T:System.Web.SiteMapNode"/>.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <returns></returns>
        protected virtual void AcquireAttributesFrom(System.Web.SiteMapNode node, IDictionary<string, object> attributes, ISiteMapNodeHelper helper)
        {
            // Unfortunately, the ASP.NET implementation uses a protected member variable to store
            // the attributes, so there is no way to loop through them without reflection or some
            // fancy dynamic subclass implementation.
            var attributeDictionary = node.GetPrivateFieldValue<NameValueCollection>("_attributes");
            foreach (string key in attributeDictionary.Keys)
            {
                var attributeName = key;
                var attributeValue = node[key];

                if (helper.ReservedAttributeNames.IsRegularAttribute(attributeName))
                {
                    attributes.Add(attributeName, attributeValue);
                }
            }
        }
        /// <summary>
        /// Acquires the route values from a given XElement.
        /// </summary>
        /// <param name="attribute">The source attribute.</param>
        /// <param name="routeValues">The route value dictionary to populate.</param>
        /// <param name="helper">The node helper.</param>
        /// <returns></returns>
        protected virtual void AcquireRouteValuesFrom(IMvcSiteMapNodeAttribute attribute, IRouteValueDictionary routeValues, ISiteMapNodeHelper helper)
        {
            foreach (var att in attribute.Attributes)
            {
                var attributeName  = att.Key.ToString();
                var attributeValue = att.Value;

                if (helper.ReservedAttributeNames.IsRouteAttribute(attributeName))
                {
                    routeValues[attributeName] = attributeValue;
                }
            }
        }
        /// <summary>
        /// Gets the site map node from MVC site map node attribute.
        /// </summary>
        /// <param name="attribute">The attribute.</param>
        /// <param name="type">The type.</param>
        /// <param name="methodInfo">The method info.</param>
        /// <param name="helper">The node helper.</param>
        /// <returns></returns>
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromMvcSiteMapNodeAttribute(
            IMvcSiteMapNodeAttribute attribute, Type type, MethodInfo methodInfo, ISiteMapNodeHelper helper)
        {
            if (attribute == null)
            {
                throw new ArgumentNullException("attribute");
            }
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (!string.IsNullOrEmpty(attribute.SiteMapCacheKey))
            {
                // Return null if the attribute doesn't apply to this cache key
                if (!helper.SiteMapCacheKey.Equals(attribute.SiteMapCacheKey))
                {
                    return(null);
                }
            }

            if (methodInfo == null) // try to find Index action
            {
                var ms = type.FindMembers(MemberTypes.Method, BindingFlags.Instance | BindingFlags.Public,
                                          (mi, o) => mi != null && string.Equals(mi.Name, "Index"), null);
                foreach (MethodInfo m in ms.OfType <MethodInfo>())
                {
                    var pars = m.GetParameters();
                    if (pars.Length == 0)
                    {
                        methodInfo = m;
                        break;
                    }
                }
            }

            string area = "";

            if (!string.IsNullOrEmpty(attribute.AreaName))
            {
                area = attribute.AreaName;
            }
            if (string.IsNullOrEmpty(area) && !string.IsNullOrEmpty(attribute.Area))
            {
                area = attribute.Area;
            }
            // Determine area (will only work if controller is defined as [<Anything>.]Areas.<Area>.Controllers.<AnyController>)
            if (string.IsNullOrEmpty(area))
            {
                var m = Regex.Match(type.Namespace, @"(?:[^\.]+\.|\s+|^)Areas\.(?<areaName>[^\.]+)\.Controllers");
                if (m.Success)
                {
                    area = m.Groups["areaName"].Value;
                }
            }

            // Determine controller and (index) action
            string controller = type.Name.Substring(0, type.Name.IndexOf("Controller"));
            string action     = (methodInfo != null ? methodInfo.Name : null) ?? "Index";

            if (methodInfo != null)
            {
                // handle ActionNameAttribute
                var actionNameAttribute = methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), true).FirstOrDefault() as ActionNameAttribute;
                if (actionNameAttribute != null)
                {
                    action = actionNameAttribute.Name;
                }
            }

            string httpMethod = (string.IsNullOrEmpty(attribute.HttpMethod) ? HttpVerbs.Get.ToString() : attribute.HttpMethod).ToUpper();

            // Handle title
            var title = attribute.Title;

            // Handle implicit resources
            var implicitResourceKey = attribute.ResourceKey;

            // Generate key for node
            string key = helper.CreateNodeKey(
                attribute.ParentKey,
                attribute.Key,
                attribute.Url,
                title,
                area,
                controller, action, httpMethod,
                attribute.Clickable);

            var nodeParentMap = helper.CreateNode(key, attribute.ParentKey, SourceName, implicitResourceKey);
            var node          = nodeParentMap.Node;

            // Assign defaults
            node.Site        = attribute.Site;
            node.Title       = title;
            node.Description = attribute.Description;
            node.Attributes.AddRange(attribute.Attributes, false);
            node.Roles.AddRange(attribute.Roles);
            node.Clickable           = attribute.Clickable;
            node.VisibilityProvider  = attribute.VisibilityProvider;
            node.DynamicNodeProvider = attribute.DynamicNodeProvider;
            node.ImageUrl            = attribute.ImageUrl;
            node.ImageUrlProtocol    = attribute.ImageUrlProtocol;
            node.ImageUrlHostName    = attribute.ImageUrlHostName;
            node.TargetFrame         = attribute.TargetFrame;
            node.HttpMethod          = httpMethod;
            if (!string.IsNullOrEmpty(attribute.Url))
            {
                node.Url = attribute.Url;
            }
            node.CacheResolvedUrl          = attribute.CacheResolvedUrl;
            node.IncludeAmbientValuesInUrl = attribute.IncludeAmbientValuesInUrl;
            node.Protocol             = attribute.Protocol;
            node.HostName             = attribute.HostName;
            node.CanonicalKey         = attribute.CanonicalKey;
            node.CanonicalUrl         = attribute.CanonicalUrl;
            node.CanonicalUrlSeo      = attribute.CanonicalUrlSeo;
            node.CanonicalUrlProtocol = attribute.CanonicalUrlProtocol;
            node.CanonicalUrlHostName = attribute.CanonicalUrlHostName;
            node.MetaRobotsValues.AddRange(attribute.MetaRobotsValues);
            node.Include          = attribute.Include;
            node.Exclude          = attribute.Exclude;
            node.LastModifiedDate = string.IsNullOrEmpty(attribute.LastModifiedDate) ? DateTime.MinValue : DateTime.Parse(attribute.LastModifiedDate);
            node.ExpirationDate   = string.IsNullOrEmpty(attribute.ExpirationDate) ? DateTime.Today.AddYears(2) : DateTime.Parse(attribute.ExpirationDate);
            node.ChangeFrequency  = attribute.ChangeFrequency;
            node.UpdatePriority   = attribute.UpdatePriority;
            node.Order            = attribute.Order;

            node.IsVideo              = attribute.IsVideo;
            node.ContentLocationUrl   = attribute.ContentLocationUrl;
            node.PlayerLocationUrl    = attribute.PlayerLocationUrl;
            node.PlayerAllowEmbed     = attribute.PlayerAllowEmbed;
            node.PlayerAutoplay       = attribute.PlayerAutoplay;
            node.VideoDuration        = attribute.VideoDuration;
            node.ViewCount            = attribute.ViewCount;
            node.VideoRating          = attribute.VideoRating;
            node.FamilyFriendly       = attribute.FamilyFriendly;
            node.GalleryLocation      = attribute.GalleryLocation;
            node.GalleryTitle         = attribute.GalleryTitle;
            node.RequiresSubscription = attribute.RequiresSubscription;
            node.VideoUploader        = attribute.VideoUploader;
            node.VideoUploaderUrl     = attribute.VideoUploaderUrl;
            node.VideoLive            = attribute.VideoLive;

            // Handle route details
            node.Route = attribute.Route;
            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);
            }
            if (!string.IsNullOrEmpty(controller))
            {
                node.RouteValues.Add("controller", controller);
            }
            if (!string.IsNullOrEmpty(action))
            {
                node.RouteValues.Add("action", action);
            }

            return(nodeParentMap);
        }
        public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
        {
            // Try the API! Let us know if there is something we can do to make it better.

            // This is the same sample as the MvcMusicStore demo, and shows how you can
            // mark up the API semantically as a replacement for XML.

            // Note that the base node of this tree doesn't necessarily have to be the home page.
            // You can specify .WithParentKey(string) to indicate that this branch is descending from
            // any node defined in any other node source (XML, .NET Attributes, IDynamicNodeProivder,
            // ISiteMapNodeBuilder).

            // Be sure to try adding nodes yourself to see if you can suggest ways to make this
            // more intuitive, easier to read, or easier to write.

            return helper.RegisterNode()
                .MatchingRoute(x => x.WithController("Home").WithAction("Index"))
                .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,HomeTitle").WithDescription("This is the home page"))
                .WithSeoValues(x => x.WithSiteMaps(y => y.WithChangeFrequency(ChangeFrequency.Always).WithUpdatePriority(UpdatePriority.Normal).WithLastModifiedDate(DateTime.Parse("2002-05-30T09:00:00"))))
                .WithChildNodes(homeChildren =>
                {
                    homeChildren.RegisterNode()
                        .MatchingRoute(x => x.WithController("Store").WithAction("Index"))
                        .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,BrowseGenresTitle"))
                        .WithChildNodes(genreChildren =>
                        {
                            genreChildren.RegisterNode()
                                .MatchingRoute(x => x.WithController("Store").WithAction("Browse").WithValue("id", "Jazz").WithValue("someOtherParameter", "whatever2"))
                                .WithDisplayValues(x => x.WithTitle("Jazz 4"))
                                .WithSeoValues(x => x.WithCanonicalKey("ABC123"));
                            genreChildren.RegisterNode()
                                .WithDynamicNodeProvider("MvcMusicStore.Code.StoreBrowseDynamicNodeProvider, Mvc Music Store")
                                .WithInheritableRouteValues(x => x.WithAction("Browse").AlwaysMatchingKey("browse"))
                                .WithInheritableDisplayValues(x => x.WithTitle("Browse"))
                                .WithChildNodes(browseChildren =>
                                {
                                    browseChildren.RegisterNode()
                                        .WithDynamicNodeProvider("MvcMusicStore.Code.StoreBrowseDynamicNodeProvider, Mvc Music Store")
                                        .WithInheritableDisplayValues(x => x.WithTitle("Details"))
                                        .WithInheritableRouteValues(x => x.WithAction("Details"));
                                });
                            genreChildren.RegisterNode()
                                .MatchingRoute(x => x.WithController("Store").WithAction("Browse").WithValue("id", "Jazz").WithValue("someParameter", "hello"))
                                .WithDisplayValues(x => x.WithTitle("Jazz 2"))
                                .WithSeoValues(x => x.WithCanonicalUrl("/Store/Browse/Jazz").WithMetaRobotsValues(MetaRobots.NoIndex | MetaRobots.NoFollow | MetaRobots.NoOpenDirectoryProject))
                                .WithKey("ABC123");
                            genreChildren.RegisterNode()
                                .MatchingRoute(x => x.WithController("Store").WithAction("Browse").WithValue("id", "Jazz").WithValue("someParameter", "goodbye"))
                                .WithDisplayValues(x => x.WithTitle("Jazz 5"))
                                .WithSeoValues(x => x.WithMetaRobotsValues(MetaRobots.NoIndex | MetaRobots.NoFollow | MetaRobots.NoOpenDirectoryProject | MetaRobots.NoYahooDirectory));
                            genreChildren.RegisterNode()
                                .MatchingUrl("~//Store/Browse/Jazz?someParameter=goodbye3") // NOTE: It is not valid to apply route values to a URL based node // TODO: Add inheritable route values.
                                .WithDisplayValues(x => x.WithTitle("Jazz 6"))
                                .WithInheritableRouteValues(x => x.WithController("Store").WithAction("Browse").WithValues(new Dictionary<string, object> { { "id", "Jazz" }, { "someOtherParameter", "whatever" }}))
                                .WithSeoValues(x => x.WithMetaRobotsValues(MetaRobots.NoIndex | MetaRobots.NoFollow | MetaRobots.NoOpenDirectoryProject | MetaRobots.NoYahooDirectory));
                        });
                    homeChildren.RegisterNode()
                        .MatchingRoute(x => x.WithController("ShoppingCart").WithAction("Index"))
                        .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,ReviewCartTitle"));
                    homeChildren.RegisterNode()
                        .AsGroupingNodeTitled("$resources:SiteMapLocalizations,CheckoutTitle")
                        .WithKey("Checkout")
                        .WithInheritableRouteValues(x => x.WithController("Checkout"));
                    homeChildren.RegisterNode()
                        .AsGroupingNodeTitled("$resources:SiteMapLocalizations,AccountTitle")
                        .WithInheritableRouteValues(x => x.WithController("Account"))
                        .WithChildNodes(accountChildren =>
                        {
                            accountChildren.RegisterNode()
                                .MatchingRoute(x => x.WithAction("LogOn"))
                                .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,LogOnTitle").WithVisibilityProvider("MvcMusicStore.Code.NonAuthenticatedVisibilityProvider, Mvc Music Store"));
                            accountChildren.RegisterNode()
                                .MatchingRoute(x => x.WithAction("LogOff"))
                                .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,LogOffTitle").WithVisibilityProvider("MvcMusicStore.Code.AuthenticatedVisibilityProvider, Mvc Music Store"));
                            accountChildren.RegisterNode()
                                .MatchingRoute(x => x.WithAction("Register"))
                                .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,RegisterTitle").WithVisibilityProvider("MvcMusicStore.Code.NonAuthenticatedVisibilityProvider, Mvc Music Store"));
                            accountChildren.RegisterNode()
                                .MatchingRoute(x => x.WithAction("ChangePassword"))
                                .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,ChangePasswordTitle").WithVisibilityProvider("MvcMusicStore.Code.AuthenticatedVisibilityProvider, Mvc Music Store"));
                            accountChildren.RegisterNode()
                                .MatchingRoute(x => x.WithController("Store").WithAction("Browse").WithValue("id", "Jazz").WithValue("someOtherParameter", "whatever"))
                                .WithDisplayValues(x => x.WithTitle("Jazz 3").WithVisibilityProvider("MvcMusicStore.Code.AuthenticatedVisibilityProvider, Mvc Music Store"))
                                .WithSeoValues(x => x.WithCanonicalUrl("http://www.whatever.com/Store/Browse/Jazz"));
                        });
                    homeChildren.RegisterNode()
                        .MatchingRoute(x => x.WithArea("Admin").WithController("Home").WithAction("Index"))
                        .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,AdministrationTitle").WithVisibility("SiteMapPathHelper,!*").WithVisibilityProvider("MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider"))
                        .WithChildNodes(adminChildren =>
                        {
                            adminChildren.RegisterNode()
                                .MatchingRoute(x => x.WithArea("Admin").WithController("StoreManager").WithAction("Index"))
                                .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,StoreManagerTitle"))
                                .WithChildNodes(storeManagerChildren =>
                                {
                                    storeManagerChildren.RegisterNode()
                                        .MatchingRoute(x => x.WithAction("Create"))
                                        .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,CreateAlbumTitle"));
                                    storeManagerChildren.RegisterNode()
                                        .MatchingRoute(x => x.WithAction("Edit"))
                                        .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,EditAlbumTitle"));
                                    storeManagerChildren.RegisterNode()
                                        .MatchingRoute(x => x.WithAction("Delete"))
                                        .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,DeleteAlbumTitle"));
                                });
                        });
                    homeChildren.RegisterNode()
                        .MatchingRoute(x => x.WithAction("SiteMap"))
                        .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,SitemapTitle"))
                        .WithUrlResolutionValues(x => x.WithUrlResolver("MvcMusicStore.Code.UpperCaseSiteMapNodeUrlResolver, Mvc Music Store"));
                    homeChildren.RegisterNode()
                        .MatchingUrl("http://www.microsoft.com/")
                        .WithDisplayValues(x => x.WithTitle("Microsoft"))
                        .WithKey("Microsoft");
                })
                .ToList();
        }
 protected virtual ISiteMapNodeToParentRelation GetRootNode(XDocument xml, XElement rootElement, ISiteMapNodeHelper helper)
 {
     return GetSiteMapNodeFromXmlElement(rootElement, null, helper);
 }
        protected virtual ISiteMapNodeToParentRelation CreateNodeFromAttributeDefinition(IMvcSiteMapNodeAttributeDefinition definition, ISiteMapNodeHelper helper)
        {
            ISiteMapNodeToParentRelation result = null;

            // Create node
            var actionNode = definition as MvcSiteMapNodeAttributeDefinitionForAction;
            if (actionNode != null)
            {
                // Create node for action
                result = this.GetSiteMapNodeFromMvcSiteMapNodeAttribute(
                     actionNode.SiteMapNodeAttribute, actionNode.ControllerType, actionNode.ActionMethodInfo, helper);
            }
            else
            {
                var controllerNode = definition as MvcSiteMapNodeAttributeDefinitionForController;
                if (controllerNode != null)
                {
                    // Create node for controller
                    result = this.GetSiteMapNodeFromMvcSiteMapNodeAttribute(
                        controllerNode.SiteMapNodeAttribute, controllerNode.ControllerType, null, helper);
                }
            }
            return result;
        }
        /// <summary>
        /// Maps an XMLElement from the XML file to an MvcSiteMapNode.
        /// </summary>
        /// <param name="node">The element to map.</param>
        /// <param name="parentNode">The parent ISiteMapNode</param>
        /// <param name="helper">The node helper.</param>
        /// <returns>An MvcSiteMapNode which represents the XMLElement.</returns>
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromXmlElement(XElement node, ISiteMapNode parentNode, ISiteMapNodeHelper helper)
        {
            // Get area, controller and action from node declaration
            string area = node.GetAttributeValue("area");
            string controller = node.GetAttributeValue("controller");
            var parentKey = parentNode == null ? "" : parentNode.Key;
            var httpMethod = node.GetAttributeValueOrFallback("httpMethod", HttpVerbs.Get.ToString()).ToUpperInvariant();
            // Handle title and description
            var title = node.GetAttributeValue("title");
            var description = String.IsNullOrEmpty(node.GetAttributeValue("description")) ? title : node.GetAttributeValue("description");

            // Generate key for node
            string key = helper.CreateNodeKey(
                parentKey,
                node.GetAttributeValue("key"),
                node.GetAttributeValue("url"),
                title,
                area,
                controller,
                node.GetAttributeValue("action"),
                httpMethod,
                !(node.GetAttributeValue("clickable") == "false"));

            // Handle implicit resources
            var implicitResourceKey = node.GetAttributeValue("resourceKey");

            // Create node
            var nodeParentMap = helper.CreateNode(key, parentKey, SourceName, implicitResourceKey);
            var siteMapNode = nodeParentMap.Node;

            // Assign defaults
            siteMapNode.Title = title;
            siteMapNode.Description = description;
            AcquireAttributesFrom(node, siteMapNode.Attributes, helper);
            AcquireRolesFrom(node, siteMapNode.Roles);
            siteMapNode.Clickable = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true"));
            siteMapNode.VisibilityProvider = node.GetAttributeValue("visibilityProvider");
            siteMapNode.DynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider");
            siteMapNode.ImageUrl = node.GetAttributeValue("imageUrl");
            siteMapNode.TargetFrame = node.GetAttributeValue("targetFrame");
            siteMapNode.HttpMethod = httpMethod;
            siteMapNode.Url = node.GetAttributeValue("url");
            siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true"));
            siteMapNode.CanonicalUrl = node.GetAttributeValue("canonicalUrl");
            siteMapNode.CanonicalKey = node.GetAttributeValue("canonicalKey");
            this.AcquireMetaRobotsValuesFrom(node, siteMapNode.MetaRobotsValues);
            siteMapNode.ChangeFrequency = (ChangeFrequency)Enum.Parse(typeof(ChangeFrequency), node.GetAttributeValueOrFallback("changeFrequency", "Undefined"));
            siteMapNode.UpdatePriority = (UpdatePriority)Enum.Parse(typeof(UpdatePriority), node.GetAttributeValueOrFallback("updatePriority", "Undefined"));
            siteMapNode.LastModifiedDate = DateTime.Parse(node.GetAttributeValueOrFallback("lastModifiedDate", DateTime.MinValue.ToString()));
            siteMapNode.Order = int.Parse(node.GetAttributeValueOrFallback("order", "0"));

            // Handle route details

            // Assign to node
            siteMapNode.Route = node.GetAttributeValue("route");
            AcquireRouteValuesFrom(node, siteMapNode.RouteValues, helper);
            AcquirePreservedRouteParametersFrom(node, siteMapNode.PreservedRouteParameters);
            siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver");

            // Add inherited route values to sitemap node
            foreach (var inheritedRouteParameter in node.GetAttributeValue("inheritedRouteParameters").Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var item = inheritedRouteParameter.Trim();
                if (siteMapNode.RouteValues.ContainsKey(item))
                    throw new MvcSiteMapException(String.Format(Resources.Messages.SiteMapNodeSameKeyInRouteValueAndInheritedRouteParameter, key, title, item));

                if (parentNode.RouteValues.ContainsKey(item))
                {
                    siteMapNode.RouteValues.Add(item, parentNode.RouteValues[item]);
                }
            }

            // Handle MVC details

            // Inherit area and controller from parent
            if (parentNode != null)
            {
                if (string.IsNullOrEmpty(area) && !siteMapNode.RouteValues.ContainsKey("area"))
                {
                    siteMapNode.Area = parentNode.Area;
                }
                if (string.IsNullOrEmpty(controller) && !siteMapNode.RouteValues.ContainsKey("controller"))
                {
                    siteMapNode.Controller = parentNode.Controller;
                }
            }

            // Add defaults for area
            if (!siteMapNode.RouteValues.ContainsKey("area"))
            {
                siteMapNode.RouteValues.Add("area", "");
            }

            return nodeParentMap;
        }
Exemple #34
0
        /// <summary>
        /// Acquires the route values from a given XElement.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="routeValues">The route values dictionary to populate.</param>
        /// <param name="helper">The node helper.</param>
        /// <returns></returns>
        protected virtual void AcquireRouteValuesFrom(XElement node, IRouteValueDictionary routeValues, ISiteMapNodeHelper helper)
        {
            foreach (XAttribute attribute in node.Attributes())
            {
                var attributeName  = attribute.Name.ToString();
                var attributeValue = attribute.Value;

                if (helper.ReservedAttributeNames.IsRouteAttribute(attributeName))
                {
                    routeValues.Add(attributeName, attributeValue);
                }
            }
        }
        /// <summary>
        /// Recursively processes our XML document, parsing our siteMapNodes and dynamicNode(s).
        /// </summary>
        /// <param name="parentNode">The parent node to process.</param>
        /// <param name="parentElement">The correspoding parent XML element.</param>
        /// <param name="processFlags">Flags to indicate which nodes to process.</param>
        /// <param name="helper">The node helper.</param>
        protected virtual IList<ISiteMapNodeToParentRelation> ProcessXmlNodes(ISiteMapNode parentNode, XElement parentElement, NodesToProcess processFlags, ISiteMapNodeHelper helper)
        {
            var result = new List<ISiteMapNodeToParentRelation>();
            bool processStandardNodes = (processFlags & NodesToProcess.StandardNodes) == NodesToProcess.StandardNodes;
            bool processDynamicNodes = (processFlags & NodesToProcess.DynamicNodes) == NodesToProcess.DynamicNodes;

            foreach (XElement node in parentElement.Elements())
            {
                if (node.Name != xmlNameProvider.NodeName)
                {
                    // If the current node is not one of the known node types throw and exception
                    throw new MvcSiteMapException(String.Format(Resources.Messages.XmlSiteMapNodeProviderInvalidSiteMapElement, helper.SiteMapCacheKey));
                }

                var child = GetSiteMapNodeFromXmlElement(node, parentNode, helper);

                if (processStandardNodes && !child.Node.HasDynamicNodeProvider)
                {
                    result.Add(child);

                    // Continue recursively processing the XML file.
                    result.AddRange(ProcessXmlNodes(child.Node, node, processFlags, helper));
                }
                else if (processDynamicNodes && child.Node.HasDynamicNodeProvider)
                {
                    // We pass in the parent node key as the default parent because the dynamic node (child) is never added to the sitemap.
                    var dynamicNodes = helper.CreateDynamicNodes(child, parentNode.Key);

                    foreach (var dynamicNode in dynamicNodes)
                    {
                        result.Add(dynamicNode);

                        if (!this.useNestedDynamicNodeRecursion)
                        {
                            // Recursively add non-dynamic childs for every dynamic node
                            result.AddRange(ProcessXmlNodes(dynamicNode.Node, node, NodesToProcess.StandardNodes, helper));
                        }
                        else
                        {
                            // Recursively process both dynamic nodes and static nodes.
                            // This is to allow V3 recursion behavior for those who depended on it - it is not a feature.
                            result.AddRange(ProcessXmlNodes(dynamicNode.Node, node, NodesToProcess.All, helper));
                        }
                    }

                    if (!this.useNestedDynamicNodeRecursion)
                    {
                        // Process the next nested dynamic node provider. We pass in the parent node as the default
                        // parent because the dynamic node definition node (child) is never added to the sitemap.
                        result.AddRange(ProcessXmlNodes(parentNode, node, NodesToProcess.DynamicNodes, helper));
                    }
                    else
                    {
                        // Continue recursively processing the XML file.
                        // Can't figure out why this is here, but this is the way it worked in V3 and if
                        // anyone depends on the broken recursive behavior, they probably also depend on this.
                        result.AddRange(ProcessXmlNodes(child.Node, node, processFlags, helper));
                    }
                }
            }
            return result;
        }
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromProviderNode(System.Web.SiteMapNode node, ISiteMapNode parentNode, ISiteMapNodeHelper helper)
        {
            // Use the same keys as the underlying provider.
            string key = node.Key;
            var    implicitResourceKey = node.ResourceKey;

            // Create Node
            var nodeParentMap = helper.CreateNode(key, parentNode.Key, SourceName, implicitResourceKey);
            var siteMapNode   = nodeParentMap.Node;

            siteMapNode.Title       = node.Title;
            siteMapNode.Description = node.Description;
            if (this.reflectAttributes)
            {
                // Unfortunately, the ASP.NET implementation uses a protected member variable to store
                // the attributes, so there is no way to loop through them without reflection or some
                // fancy dynamic subclass implementation.
                var attributeDictionary = node.GetPrivateFieldValue <NameValueCollection>("_attributes");
                siteMapNode.Attributes.AddRange(attributeDictionary, false);
            }
            siteMapNode.Roles.AddRange(node.Roles);
            siteMapNode.Clickable           = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true"));
            siteMapNode.VisibilityProvider  = node.GetAttributeValue("visibilityProvider");
            siteMapNode.DynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider");
            siteMapNode.ImageUrl            = node.GetAttributeValue("imageUrl");
            siteMapNode.ImageUrlProtocol    = node.GetAttributeValue("imageUrlProtocol");
            siteMapNode.ImageUrlHostName    = node.GetAttributeValue("imageUrlHostName");
            siteMapNode.TargetFrame         = node.GetAttributeValue("targetFrame");
            siteMapNode.HttpMethod          = node.GetAttributeValueOrFallback("httpMethod", "*").ToUpperInvariant();
            siteMapNode.Url = node.Url;
            siteMapNode.CacheResolvedUrl          = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true"));
            siteMapNode.IncludeAmbientValuesInUrl = bool.Parse(node.GetAttributeValueOrFallback("includeAmbientValuesInUrl", "false"));
            siteMapNode.Protocol             = node.GetAttributeValue("protocol");
            siteMapNode.HostName             = node.GetAttributeValue("hostName");
            siteMapNode.CanonicalKey         = node.GetAttributeValue("canonicalKey");
            siteMapNode.CanonicalUrl         = node.GetAttributeValue("canonicalUrl");
            siteMapNode.CanonicalUrlProtocol = node.GetAttributeValue("canonicalUrlProtocol");
            siteMapNode.CanonicalUrlHostName = node.GetAttributeValue("canonicalUrlHostName");
            siteMapNode.MetaRobotsValues.AddRange(node.GetAttributeValue("metaRobotsValues"), new[] { ' ' });
            siteMapNode.ChangeFrequency  = (ChangeFrequency)Enum.Parse(typeof(ChangeFrequency), node.GetAttributeValueOrFallback("changeFrequency", "Undefined"));
            siteMapNode.UpdatePriority   = (UpdatePriority)Enum.Parse(typeof(UpdatePriority), node.GetAttributeValueOrFallback("updatePriority", "Undefined"));
            siteMapNode.LastModifiedDate = DateTime.Parse(node.GetAttributeValueOrFallback("lastModifiedDate", DateTime.MinValue.ToString()));
            siteMapNode.Order            = int.Parse(node.GetAttributeValueOrFallback("order", "0"));

            // Handle route details

            // Assign to node
            siteMapNode.Route = node.GetAttributeValue("route");
            if (this.reflectRouteValues)
            {
                // Unfortunately, the ASP.NET implementation uses a protected member variable to store
                // the attributes, so there is no way to loop through them without reflection or some
                // fancy dynamic subclass implementation.
                var attributeDictionary = node.GetPrivateFieldValue <NameValueCollection>("_attributes");
                siteMapNode.RouteValues.AddRange(attributeDictionary);
            }
            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))
            {
                var item = inheritedRouteParameter.Trim();
                if (parentNode.RouteValues.ContainsKey(item))
                {
                    siteMapNode.RouteValues.Add(item, parentNode.RouteValues[item]);
                }
            }

            // Handle MVC details

            // Get area and controller from node declaration
            siteMapNode.Area       = this.InheritAreaIfNotProvided(node, parentNode);
            siteMapNode.Controller = this.InheritControllerIfNotProvided(node, parentNode);

            return(nodeParentMap);
        }
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromProviderNode(System.Web.SiteMapNode node, ISiteMapNode parentNode, ISiteMapNodeHelper helper)
        {
            // Use the same keys as the underlying provider.
            string key = node.Key;
            var implicitResourceKey = node.ResourceKey;

            // Create Node
            var nodeParentMap = helper.CreateNode(key, parentNode.Key, SourceName, implicitResourceKey);
            var siteMapNode = nodeParentMap.Node;

            siteMapNode.Title = node.Title;
            siteMapNode.Description = String.IsNullOrEmpty(node.Description) ? siteMapNode.Title : node.Description;
            if (this.reflectAttributes)
            {
                AcquireAttributesFrom(node, siteMapNode.Attributes, helper);
            }
            AcquireRolesFrom(node, siteMapNode.Roles);
            siteMapNode.Clickable = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true"));
            siteMapNode.VisibilityProvider = node.GetAttributeValue("visibilityProvider");
            siteMapNode.DynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider");
            siteMapNode.ImageUrl = node.GetAttributeValue("imageUrl");
            siteMapNode.TargetFrame = node.GetAttributeValue("targetFrame");
            siteMapNode.HttpMethod = node.GetAttributeValueOrFallback("httpMethod", "*").ToUpperInvariant();
            siteMapNode.Url = node.Url;
            siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true"));
            siteMapNode.CanonicalUrl = node.GetAttributeValue("canonicalUrl");
            siteMapNode.CanonicalKey = node.GetAttributeValue("canonicalKey");
            this.AcquireMetaRobotsValuesFrom(node, siteMapNode.MetaRobotsValues);
            siteMapNode.ChangeFrequency = (ChangeFrequency)Enum.Parse(typeof(ChangeFrequency), node.GetAttributeValueOrFallback("changeFrequency", "Undefined"));
            siteMapNode.UpdatePriority = (UpdatePriority)Enum.Parse(typeof(UpdatePriority), node.GetAttributeValueOrFallback("updatePriority", "Undefined"));
            siteMapNode.LastModifiedDate = DateTime.Parse(node.GetAttributeValueOrFallback("lastModifiedDate", DateTime.MinValue.ToString()));
            siteMapNode.Order = int.Parse(node.GetAttributeValueOrFallback("order", "0"));

            // Handle route details

            // Assign to node
            siteMapNode.Route = node.GetAttributeValue("route");
            if (this.reflectRouteValues)
            {
                AcquireRouteValuesFrom(node, siteMapNode.RouteValues, helper);
            }
            AcquirePreservedRouteParametersFrom(node, siteMapNode.PreservedRouteParameters);
            siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver");

            // Add inherited route values to sitemap node
            foreach (var inheritedRouteParameter in node.GetAttributeValue("inheritedRouteParameters").Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var item = inheritedRouteParameter.Trim();
                if (parentNode.RouteValues.ContainsKey(item))
                {
                    siteMapNode.RouteValues.Add(item, parentNode.RouteValues[item]);
                }
            }

            // Handle MVC details

            // Get area, controller and action from node declaration
            string area = node.GetAttributeValue("area");
            string controller = node.GetAttributeValue("controller");

            siteMapNode.Area = area;
            siteMapNode.Controller = controller;

            // Inherit area and controller from parent
            if (parentNode != null)
            {
                if (string.IsNullOrEmpty(area))
                {
                    siteMapNode.Area = parentNode.Area;
                }
                if (string.IsNullOrEmpty(controller))
                {
                    siteMapNode.Controller = parentNode.Controller;
                }
            }

            // Add defaults for area
            if (!siteMapNode.RouteValues.ContainsKey("area"))
            {
                siteMapNode.RouteValues.Add("area", "");
            }

            return nodeParentMap;
        }
        protected virtual ISiteMapNodeToParentRelation GetRootNode(SiteMapProvider provider, ISiteMapNodeHelper helper)
        {
            var root = provider.RootNode;

            return(helper.CreateNode(root.Key, null, SourceName, root.ResourceKey));
        }
        /// <summary>
        /// Acquires the attributes from a given XElement.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="attributes">The attributes dictionary to populate.</param>
        /// <param name="helper">The node helper.</param>
        /// <returns></returns>
        protected virtual void AcquireAttributesFrom(XElement node, IDictionary<string, object> attributes, ISiteMapNodeHelper helper)
        {
            foreach (XAttribute attribute in node.Attributes())
            {
                var attributeName = attribute.Name.ToString();
                var attributeValue = attribute.Value;

                if (helper.ReservedAttributeNames.IsRegularAttribute(attributeName))
                {
                    attributes.Add(attributeName, attributeValue);
                }
            }
        }
 protected virtual ISiteMapNodeToParentRelation GetRootNode(XDocument xml, XElement rootElement, ISiteMapNodeHelper helper)
 {
     return(GetSiteMapNodeFromXmlElement(rootElement, null, helper));
 }
        protected virtual ISiteMapNodeToParentRelation CreateNodeFromAttributeDefinition(IMvcSiteMapNodeAttributeDefinition definition, ISiteMapNodeHelper helper)
        {
            ISiteMapNodeToParentRelation result = null;

            // Create node
            var actionNode = definition as MvcSiteMapNodeAttributeDefinitionForAction;

            if (actionNode != null)
            {
                // Create node for action
                result = this.GetSiteMapNodeFromMvcSiteMapNodeAttribute(
                    actionNode.SiteMapNodeAttribute, actionNode.ControllerType, actionNode.ActionMethodInfo, helper);
            }
            else
            {
                var controllerNode = definition as MvcSiteMapNodeAttributeDefinitionForController;
                if (controllerNode != null)
                {
                    // Create node for controller
                    result = this.GetSiteMapNodeFromMvcSiteMapNodeAttribute(
                        controllerNode.SiteMapNodeAttribute, controllerNode.ControllerType, null, helper);
                }
            }
            return(result);
        }
        /// <summary>
        /// Maps an XMLElement from the XML file to an MvcSiteMapNode.
        /// </summary>
        /// <param name="node">The element to map.</param>
        /// <param name="parentNode">The parent ISiteMapNode</param>
        /// <param name="helper">The node helper.</param>
        /// <returns>An MvcSiteMapNode which represents the XMLElement.</returns>
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromXmlElement(XElement node, ISiteMapNode parentNode, ISiteMapNodeHelper helper)
        {
            // Get data required to generate the node instance

            // Get area and controller from node declaration or the parent node
            var area                = this.InheritAreaIfNotProvided(node, parentNode);
            var controller          = this.InheritControllerIfNotProvided(node, parentNode);
            var action              = node.GetAttributeValue("action");
            var url                 = node.GetAttributeValue("url");
            var explicitKey         = node.GetAttributeValue("key");
            var parentKey           = parentNode == null ? "" : parentNode.Key;
            var httpMethod          = node.GetAttributeValueOrFallback("httpMethod", HttpVerbs.Get.ToString()).ToUpper();
            var clickable           = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true"));
            var title               = node.GetAttributeValue("title");
            var implicitResourceKey = node.GetAttributeValue("resourceKey");

            // Generate key for node
            string key = helper.CreateNodeKey(
                parentKey,
                explicitKey,
                url,
                title,
                area,
                controller,
                action,
                httpMethod,
                clickable);

            // Create node
            var nodeParentMap = helper.CreateNode(key, parentKey, SourceName, implicitResourceKey);
            var siteMapNode   = nodeParentMap.Node;

            // Assign values
            siteMapNode.Title       = title;
            siteMapNode.Description = node.GetAttributeValue("description");
            siteMapNode.Attributes.AddRange(node, false);
            siteMapNode.Roles.AddRange(node.GetAttributeValue("roles"), new[] { ',', ';' });
            siteMapNode.Clickable           = clickable;
            siteMapNode.VisibilityProvider  = node.GetAttributeValue("visibilityProvider");
            siteMapNode.DynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider");
            siteMapNode.ImageUrl            = node.GetAttributeValue("imageUrl");
            siteMapNode.ImageUrlProtocol    = node.GetAttributeValue("imageUrlProtocol");
            siteMapNode.ImageUrlHostName    = node.GetAttributeValue("imageUrlHostName");
            siteMapNode.TargetFrame         = node.GetAttributeValue("targetFrame");
            siteMapNode.HttpMethod          = httpMethod;
            siteMapNode.Url = url;
            siteMapNode.CacheResolvedUrl          = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true"));
            siteMapNode.IncludeAmbientValuesInUrl = bool.Parse(node.GetAttributeValueOrFallback("includeAmbientValuesInUrl", "false"));
            siteMapNode.Protocol             = node.GetAttributeValue("protocol");
            siteMapNode.HostName             = node.GetAttributeValue("hostName");
            siteMapNode.CanonicalKey         = node.GetAttributeValue("canonicalKey");
            siteMapNode.CanonicalUrl         = node.GetAttributeValue("canonicalUrl");
            siteMapNode.CanonicalUrlProtocol = node.GetAttributeValue("canonicalUrlProtocol");
            siteMapNode.CanonicalUrlHostName = node.GetAttributeValue("canonicalUrlHostName");
            siteMapNode.MetaRobotsValues.AddRange(node.GetAttributeValue("metaRobotsValues"), new[] { ' ' });
            siteMapNode.ChangeFrequency  = (ChangeFrequency)Enum.Parse(typeof(ChangeFrequency), node.GetAttributeValueOrFallback("changeFrequency", "Undefined"));
            siteMapNode.UpdatePriority   = (UpdatePriority)Enum.Parse(typeof(UpdatePriority), node.GetAttributeValueOrFallback("updatePriority", "Undefined"));
            siteMapNode.LastModifiedDate = DateTime.Parse(node.GetAttributeValueOrFallback("lastModifiedDate", DateTime.MinValue.ToString()));
            siteMapNode.Order            = int.Parse(node.GetAttributeValueOrFallback("order", "0"));

            // Handle route details
            siteMapNode.Route = node.GetAttributeValue("route");
            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;
            siteMapNode.Action     = action;

            // Add inherited route values to sitemap node
            foreach (var inheritedRouteParameter in node.GetAttributeValue("inheritedRouteParameters").Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var item = inheritedRouteParameter.Trim();
                if (node.Attribute(item) != null)
                {
                    throw new MvcSiteMapException(string.Format(Resources.Messages.SiteMapNodeSameKeyInRouteValueAndInheritedRouteParameter, key, title, item));
                }

                if (parentNode.RouteValues.ContainsKey(item))
                {
                    siteMapNode.RouteValues.Add(item, parentNode.RouteValues[item]);
                }
            }

            return(nodeParentMap);
        }
Exemple #43
0
        protected virtual ISiteMapNodeToParentRelation GetSiteMapNodeFromProviderNode(System.Web.SiteMapNode node, ISiteMapNode parentNode, ISiteMapNodeHelper helper)
        {
            // Use the same keys as the underlying provider.
            string key = node.Key;
            var    implicitResourceKey = node.ResourceKey;

            // Create Node
            var nodeParentMap = helper.CreateNode(key, parentNode.Key, SourceName, implicitResourceKey);
            var siteMapNode   = nodeParentMap.Node;

            siteMapNode.Title       = node.Title;
            siteMapNode.Description = String.IsNullOrEmpty(node.Description) ? siteMapNode.Title : node.Description;
            if (this.reflectAttributes)
            {
                AcquireAttributesFrom(node, siteMapNode.Attributes, helper);
            }
            AcquireRolesFrom(node, siteMapNode.Roles);
            siteMapNode.Clickable           = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true"));
            siteMapNode.VisibilityProvider  = node.GetAttributeValue("visibilityProvider");
            siteMapNode.DynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider");
            siteMapNode.ImageUrl            = node.GetAttributeValue("imageUrl");
            siteMapNode.TargetFrame         = node.GetAttributeValue("targetFrame");
            siteMapNode.HttpMethod          = node.GetAttributeValueOrFallback("httpMethod", "*").ToUpperInvariant();
            siteMapNode.Url = node.Url;
            siteMapNode.CacheResolvedUrl = bool.Parse(node.GetAttributeValueOrFallback("cacheResolvedUrl", "true"));
            siteMapNode.CanonicalUrl     = node.GetAttributeValue("canonicalUrl");
            siteMapNode.CanonicalKey     = node.GetAttributeValue("canonicalKey");
            this.AcquireMetaRobotsValuesFrom(node, siteMapNode.MetaRobotsValues);
            siteMapNode.ChangeFrequency  = (ChangeFrequency)Enum.Parse(typeof(ChangeFrequency), node.GetAttributeValueOrFallback("changeFrequency", "Undefined"));
            siteMapNode.UpdatePriority   = (UpdatePriority)Enum.Parse(typeof(UpdatePriority), node.GetAttributeValueOrFallback("updatePriority", "Undefined"));
            siteMapNode.LastModifiedDate = DateTime.Parse(node.GetAttributeValueOrFallback("lastModifiedDate", DateTime.MinValue.ToString()));
            siteMapNode.Order            = int.Parse(node.GetAttributeValueOrFallback("order", "0"));

            // Handle route details

            // Assign to node
            siteMapNode.Route = node.GetAttributeValue("route");
            if (this.reflectRouteValues)
            {
                AcquireRouteValuesFrom(node, siteMapNode.RouteValues, helper);
            }
            AcquirePreservedRouteParametersFrom(node, siteMapNode.PreservedRouteParameters);
            siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver");

            // Add inherited route values to sitemap node
            foreach (var inheritedRouteParameter in node.GetAttributeValue("inheritedRouteParameters").Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var item = inheritedRouteParameter.Trim();
                if (parentNode.RouteValues.ContainsKey(item))
                {
                    siteMapNode.RouteValues.Add(item, parentNode.RouteValues[item]);
                }
            }

            // Handle MVC details

            // Get area, controller and action from node declaration
            string area       = node.GetAttributeValue("area");
            string controller = node.GetAttributeValue("controller");

            siteMapNode.Area       = area;
            siteMapNode.Controller = controller;

            // Inherit area and controller from parent
            if (parentNode != null)
            {
                if (string.IsNullOrEmpty(area))
                {
                    siteMapNode.Area = parentNode.Area;
                }
                if (string.IsNullOrEmpty(controller))
                {
                    siteMapNode.Controller = parentNode.Controller;
                }
            }

            // Add defaults for area
            if (!siteMapNode.RouteValues.ContainsKey("area"))
            {
                siteMapNode.RouteValues.Add("area", "");
            }

            return(nodeParentMap);
        }
        protected virtual IEnumerable <ISiteMapNodeToParentRelation> LoadSiteMapNodesFromXml(XDocument xml, ISiteMapNodeHelper helper)
        {
            var result = new List <ISiteMapNodeToParentRelation>();

            xmlNameProvider.FixXmlNamespaces(xml);

            // Get the root mvcSiteMapNode element, and map this to an MvcSiteMapNode
            var rootElement = GetRootElement(xml);

            if (rootElement == null)
            {
                // No root element - inform the user this isn't allowed.
                throw new MvcSiteMapException(string.Format(Resources.Messages.XmlSiteMapNodeProviderRootNodeNotDefined, helper.SiteMapCacheKey));
            }
            // Add the root node
            var rootNode = GetRootNode(xml, rootElement, helper);

            if (includeRootNode)
            {
                result.Add(rootNode);
            }

            // Process our XML, passing in the main root sitemap node and xml element.
            result.AddRange(ProcessXmlNodes(rootNode.Node, rootElement, NodesToProcess.All, helper));

            // Done!
            return(result);
        }
Exemple #45
0
        /// <summary>
        /// Acquires the route values from a given <see cref="T:System.Web.SiteMapNode"/>.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <returns></returns>
        protected virtual void AcquireRouteValuesFrom(System.Web.SiteMapNode node, IRouteValueDictionary routeValues, ISiteMapNodeHelper helper)
        {
            // Unfortunately, the ASP.NET implementation uses a protected member variable to store
            // the attributes, so there is no way to loop through them without reflection or some
            // fancy dynamic subclass implementation.
            var attributeDictionary = node.GetPrivateFieldValue <NameValueCollection>("_attributes");

            foreach (string key in attributeDictionary.Keys)
            {
                var attributeName  = key;
                var attributeValue = node[key];

                if (helper.ReservedAttributeNames.IsRouteAttribute(attributeName))
                {
                    routeValues.Add(attributeName, attributeValue);
                }
            }
        }