public static IEnumerable<SiteMapNode> BuildDynamicNodes(string assemblyQualifiedTypeString, SiteMapNode parentNode) { var type = Type.GetType(assemblyQualifiedTypeString); if (type == null) throw new Exception($"Type {assemblyQualifiedTypeString} was not found."); IDynamicNodeProvider dynamicNodeProvider; if (!cachedNodeProviders.TryGetValue(type, out dynamicNodeProvider)) { lock (syncLock) { if (!cachedNodeProviders.TryGetValue(type, out dynamicNodeProvider)) { dynamicNodeProvider = Activator.CreateInstance(type) as IDynamicNodeProvider; cachedNodeProviders.Add(type, dynamicNodeProvider); } } } foreach(var dynamicNode in dynamicNodeProvider.GetSiteMapNodes()) { yield return ProcessNode(dynamicNode, parentNode); } }
private static SiteMapNode ProcessNode(SiteMapNode nodeToProcess, SiteMapNode parentNode) { var area = string.IsNullOrEmpty(nodeToProcess.Area) ? parentNode.Area : nodeToProcess.Area; var controller = string.IsNullOrEmpty(nodeToProcess.Controller) ? parentNode.Controller : nodeToProcess.Controller; var action = nodeToProcess.Action; var url = nodeToProcess.Url; var explicitKey = nodeToProcess.Key; var parentKey = parentNode == null ? "" : parentNode.Key; var httpMethod = HttpVerbs.Get.ToString().ToUpperInvariant(); var clickable = true; var title = nodeToProcess.Title; string key = nodeKeyGenerator.GenerateKey( parentKey, explicitKey, url, title, area, controller, action, httpMethod, clickable ); nodeToProcess.Area = area; nodeToProcess.Controller = controller; nodeToProcess.Action = action; nodeToProcess.Url = url; nodeToProcess.UnresolvedUrl = url; nodeToProcess.Key = key; nodeToProcess.Clickable = clickable; nodeToProcess.Title = title; return nodeToProcess; }
protected virtual string InheritAreaIfNotProvided(SiteMapNode node, SiteMapNode parentNode) { var result = node.Area; if (string.IsNullOrEmpty(result) && parentNode != null) { result = parentNode.Area; } return result; }
protected virtual SiteMapNode GetSiteMapNodeFromXmlElement(XElement node, SiteMapNode parentNode) { // get data required to generate the node instance // get area and controller from node declaration var area = InheritAreaIfNotProvided(node, parentNode); var controller = InheritControllerIfNotProvided(node, parentNode); var action = node.GetAttributeValue("action"); var url = node.GetAttributeValue("url"); var explicitKey = node.GetAttributeValue("key"); var parentKey = parentNode == null ? string.Empty : parentNode.Key; var httpMethod = node.GetAttributeValueOrFallback("httpMethod", HttpVerbs.Get.ToString()).ToUpperInvariant(); var clickable = bool.Parse(node.GetAttributeValueOrFallback("clickable", "true")); var title = node.GetAttributeValue("title"); var description = node.GetAttributeValue("description"); var targetFrame = node.GetAttributeValue("targetFrame"); var imageUrl = node.GetAttributeValue("imageUrl"); var order = int.Parse(node.GetAttributeValueOrFallback("order", "0")); var dynamicNodeProvider = node.GetAttributeValue("dynamicNodeProvider"); //var implicitResourceKey = node.GetAttributeValue("resourceKey"); var siteMapNode = new SiteMapNode { Key = nodeKeyGenerator.GenerateKey(parentKey, explicitKey, url, title, area, controller, action, httpMethod, clickable), Title = title, Clickable = clickable, Area = area, Controller = controller, Action = action, DynamicNodeProvider = dynamicNodeProvider, Attributes = new Dictionary<string, object>(), ChildNodes = new List<SiteMapNode>(), Description = description, TargetFrame = targetFrame, ImageUrl = imageUrl, Url = url, UnresolvedUrl = url, Order = order }; return siteMapNode; }
protected virtual SiteMapNode GetSiteMapNodeFromJSONNode(SiteMapNode jsonNode, SiteMapNode parentNode) { // get data required to generate the node instance // get area and controller var area = InheritAreaIfNotProvided(jsonNode, parentNode); var controller = InheritControllerIfNotProvided(jsonNode, parentNode); var action = jsonNode.Action; var url = jsonNode.Url; var explicitKey = jsonNode.Key; var parentKey = parentNode == null ? string.Empty : parentNode.Key; var httpMethod = (string.IsNullOrEmpty(jsonNode.HttpMethod) ? HttpVerbs.Get.ToString() : jsonNode.HttpMethod).ToUpperInvariant(); var clickable = jsonNode.Clickable; var title = jsonNode.Title; var description = jsonNode.Description; var targetFrame = jsonNode.TargetFrame; var imageUrl = jsonNode.ImageUrl; var order = jsonNode.Order; var dynamicNodeProvider = jsonNode.DynamicNodeProvider; var siteMapNode = new SiteMapNode { Key = nodeKeyGenerator.GenerateKey(parentKey, explicitKey, url, title, area, controller, action, httpMethod, clickable), Title = title, Clickable = clickable, Area = area, Controller = controller, Action = action, DynamicNodeProvider = dynamicNodeProvider, Attributes = new Dictionary<string, object>(), ChildNodes = new List<SiteMapNode>(), Description = description, TargetFrame = targetFrame, ImageUrl = imageUrl, Url = url, UnresolvedUrl = url, Order = order }; return siteMapNode; }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth) { return Menu(helper, startingNode, startingNodeInChildLevel, showStartingNode, maxDepth, false); }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <param name="drillDownToCurrent">Should the model exceed the maxDepth to reach the current node?</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool drillDownToCurrent, object sourceMetadata) { return Menu(helper, null, startingNode, startingNodeInChildLevel, showStartingNode, maxDepth, drillDownToCurrent, sourceMetadata); }
/// <summary> /// Builds the model. /// </summary> /// <param name="helper">The helper.</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Renders startingNode in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <returns>The model.</returns> private static MenuHelperModel BuildModel(MvcSiteMapHtmlHelper helper, SourceMetadataDictionary sourceMetadata, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth) { return BuildModel(helper, sourceMetadata, startingNode, startingNodeInChildLevel, showStartingNode, maxDepth, false, helper.SiteMap.VisibilityAffectsDescendants); }
/// <summary> /// Gets SiteMap path for the current request /// </summary> /// <param name="helper">MvcSiteMapHtmlHelper instance</param> /// <param name="startingNode">The starting node (the last node in the site map path).</param> /// <returns>SiteMap path for the current request</returns> public static MvcHtmlString SiteMapPath(this MvcSiteMapHtmlHelper helper, SiteMapNode startingNode) { return SiteMapPath(helper, null, startingNode); }
/// <summary> /// Gets SiteMap path for the current request /// </summary> /// <param name="helper">MvcSiteMapHtmlHelper instance</param> /// <param name="templateName">Name of the template.</param> /// <param name="startingNode">The starting node (the last node in the site map path).</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>SiteMap path for the current request</returns> public static MvcHtmlString SiteMapPath(this MvcSiteMapHtmlHelper helper, string templateName, SiteMapNode startingNode, SourceMetadataDictionary sourceMetadata) { var model = BuildModel(helper, GetSourceMetadata(sourceMetadata), startingNode); return helper .CreateHtmlHelperForModel(model) .DisplayFor(m => model, templateName); }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode) { return Menu(helper, startingNode, startingNodeInChildLevel, showStartingNode, Int32.MaxValue, false); }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="templateName">Name of the template.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, object sourceMetadata) { return Menu(helper, templateName, startingNode, startingNodeInChildLevel, showStartingNode, maxDepth, false, sourceMetadata); }
protected virtual void ProcessNodes(IEnumerable<SiteMapNode> nodes, SiteMapNode rootNode) { foreach (var node in nodes) { var siteMapNode = GetSiteMapNodeFromJSONNode(node, rootNode); if (!string.IsNullOrEmpty(siteMapNode.DynamicNodeProvider)) { // has dynamic node provider var dynamicNodes = DynamicNodeBuilder.BuildDynamicNodes(siteMapNode.DynamicNodeProvider, rootNode); // add to root node rootNode.ChildNodes.AddRange(dynamicNodes); // add non-dynamic children for every dynamic node ProcessNodes(dynamicNodes, rootNode); } else { rootNode.ChildNodes.Add(siteMapNode); ProcessNodes(node.ChildNodes, siteMapNode); } } }
/// <summary> /// Recursively process our XML document, parsing our siteMapNodes and dynamicNode(s). /// </summary> /// <param name="rootNode">The main root siteMap node.</param> /// <param name="rootElement">the main root XML element.</param> protected virtual void ProcessXmlNodes(SiteMapNode rootNode, XElement rootElement) { // loop through each element below the current root element foreach (XElement node in rootElement.Elements()) { SiteMapNode childNode; if (!node.Name.LocalName.Equals(nodeName, StringComparison.OrdinalIgnoreCase)) throw new Exception($"Element of type {node.Name.LocalName} is an invalid node."); // if this is a normal mvcSieMapNode then map the xml element // to an mvcSiteMapNode, and add the node to the current root. childNode = GetSiteMapNodeFromXmlElement(node, rootNode); if (!string.IsNullOrEmpty(childNode.DynamicNodeProvider)) { // has dynamic node provider var dynamicNodes = DynamicNodeBuilder.BuildDynamicNodes(childNode.DynamicNodeProvider, rootNode); // add to root node rootNode.ChildNodes.AddRange(dynamicNodes); // add non-dynamic children for every dynamic node foreach (var dynamicNode in dynamicNodes) { ProcessXmlNodes(dynamicNode, node); } } else { rootNode.ChildNodes.Add(childNode); ProcessXmlNodes(childNode, node); } } }
/// <summary> /// Inherits the controller from the parent node if it is not provided in the current siteMapNode XML element and the parent node is not null. /// </summary> /// <param name="node">The siteMapNode element.</param> /// <param name="parentNode">The parent node.</param> /// <returns>The value provided by either the siteMapNode or parentNode.Controller.</returns> protected virtual string InheritControllerIfNotProvided(XElement node, SiteMapNode parentNode) { var result = node.GetAttributeValue("controller"); if (node.Attribute("controller") == null && parentNode != null) { result = parentNode.Controller; } return result; }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, SourceMetadataDictionary sourceMetadata) { return Menu(helper, startingNode, startingNodeInChildLevel, showStartingNode, maxDepth, false, sourceMetadata); }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="templateName">Name of the template.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, SourceMetadataDictionary sourceMetadata) { return Menu(helper, templateName, startingNode, startingNodeInChildLevel, showStartingNode, Int32.MaxValue, false, sourceMetadata); }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="templateName">Name of the template.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <param name="drillDownToCurrent">Should the model exceed the maxDepth to reach the current node</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool drillDownToCurrent) { return Menu(helper, templateName, startingNode, startingNodeInChildLevel, showStartingNode, maxDepth, drillDownToCurrent, new SourceMetadataDictionary()); }
/// <summary> /// Gets SiteMap path for the current request /// </summary> /// <param name="helper">MvcSiteMapHtmlHelper instance</param> /// <param name="templateName">Name of the template.</param> /// <param name="startingNode">The starting node (the last node in the site map path).</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>SiteMap path for the current request</returns> public static MvcHtmlString SiteMapPath(this MvcSiteMapHtmlHelper helper, string templateName, SiteMapNode startingNode, object sourceMetadata) { return SiteMapPath(helper, templateName, startingNode, new SourceMetadataDictionary(sourceMetadata)); }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="templateName">Name of the template.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <param name="drillDownToCurrent">Should the model exceed the maxDepth to reach the current node</param> /// <param name="visibilityAffectsDescendants"><c>true</c> if the visibility provider should affect the visibility of descendant nodes, otherwise <c>false</c>.</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool drillDownToCurrent, bool visibilityAffectsDescendants, object sourceMetadata) { return Menu(helper, templateName, startingNode, startingNodeInChildLevel, showStartingNode, maxDepth, drillDownToCurrent, visibilityAffectsDescendants, new SourceMetadataDictionary(sourceMetadata)); }
/// <summary> /// Builds the model. /// </summary> /// <param name="helper">The helper.</param> /// <param name="startingNode">The starting node.</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>The model.</returns> private static SiteMapPathHelperModel BuildModel(MvcSiteMapHtmlHelper helper, SourceMetadataDictionary sourceMetadata, SiteMapNode startingNode) { // Build model var model = new SiteMapPathHelperModel(); var node = startingNode; while (node != null) { bool nodeVisible = node.IsVisible(sourceMetadata); if (nodeVisible && node.IsAccessibleToUser()) { var nodeToAdd = new SiteMapNodeModel(helper.SiteMap, node, sourceMetadata); model.Nodes.Add(nodeToAdd); } node = node.GetParentNode(helper.SiteMap); } model.Nodes.Reverse(); return model; }
/// <summary> /// Build a menu, based on the MvcSiteMap /// </summary> /// <param name="helper">The helper.</param> /// <param name="templateName">Name of the template.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Show starting node in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <param name="drillDownToCurrent">Should the model exceed the maxDepth to reach the current node</param> /// <param name="visibilityAffectsDescendants"><c>true</c> if the visibility provider should affect the visibility of descendant nodes, otherwise <c>false</c>.</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <returns>Html markup</returns> public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool drillDownToCurrent, bool visibilityAffectsDescendants, SourceMetadataDictionary sourceMetadata) { var model = BuildModel(helper, GetSourceMetadata(sourceMetadata), startingNode, startingNodeInChildLevel, showStartingNode, maxDepth, drillDownToCurrent, visibilityAffectsDescendants); return helper .CreateHtmlHelperForModel(model) .DisplayFor(m => model, templateName); }
private TreeNode<MenuItem> ConvertSitemapNodeToMenuItemNode(SiteMapNode node) { var item = new MenuItem(); var treeNode = new TreeNode<MenuItem>(item); if (node.RouteName.HasValue()) { item.RouteName = node.RouteName; } else if (node.ActionName.HasValue() && node.ControllerName.HasValue()) { item.ActionName = node.ActionName; item.ControllerName = node.ControllerName; } else if (node.Url.HasValue()) { item.Url = node.Url; } item.RouteValues = node.RouteValues; item.Visible = node.Visible; item.Text = node.Title; item.Attributes.Merge(node.Attributes); if (node.Attributes.ContainsKey("permissionNames")) item.PermissionNames = node.Attributes["permissionNames"] as string; if (node.Attributes.ContainsKey("id")) item.Id = node.Attributes["id"] as string; if (node.Attributes.ContainsKey("resKey")) item.ResKey = node.Attributes["resKey"] as string; if (node.Attributes.ContainsKey("iconClass")) item.Icon = node.Attributes["iconClass"] as string; if (node.Attributes.ContainsKey("imageUrl")) item.ImageUrl = node.Attributes["imageUrl"] as string; if (node.Attributes.ContainsKey("isGroupHeader")) item.IsGroupHeader = Boolean.Parse(node.Attributes["isGroupHeader"] as string); // iterate children recursively foreach (var childNode in node.ChildNodes) { var childTreeNode = ConvertSitemapNodeToMenuItemNode(childNode); treeNode.Append(childTreeNode); } return treeNode; }
/// <summary> /// Builds the model. /// </summary> /// <param name="helper">The helper.</param> /// <param name="sourceMetadata">User-defined meta data.</param> /// <param name="startingNode">The starting node.</param> /// <param name="startingNodeInChildLevel">Renders startingNode in child level if set to <c>true</c>.</param> /// <param name="showStartingNode">Show starting node if set to <c>true</c>.</param> /// <param name="maxDepth">The max depth.</param> /// <param name="drillDownToCurrent">Should the model exceed the maxDepth to reach the current node?</param> /// <param name="visibilityAffectsDescendants"><b>true</b> if the visibility provider should affect the current node as well as all descendant nodes; otherwise <b>false</b>.</param> /// <returns>The model.</returns> internal static MenuHelperModel BuildModel(MvcSiteMapHtmlHelper helper, SourceMetadataDictionary sourceMetadata, SiteMapNode startingNode, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool drillDownToCurrent, bool visibilityAffectsDescendants) { // Build model var model = new MenuHelperModel(); var node = startingNode; // Check if a starting node has been given if (node == null) { return model; } // Check ACL if (node.IsAccessibleToUser()) { // Add node? var nodeToAdd = new SiteMapNodeModel(helper.SiteMap, node, sourceMetadata, maxDepth, drillDownToCurrent, startingNodeInChildLevel, visibilityAffectsDescendants); // Check visibility if (node.IsVisible(sourceMetadata)) { if (showStartingNode || !startingNodeInChildLevel) { model.Nodes.Add(nodeToAdd); } // Add child nodes if (visibilityAffectsDescendants && startingNodeInChildLevel) { model.Nodes.AddRange(nodeToAdd.Children); } } // Add child nodes if (!visibilityAffectsDescendants && startingNodeInChildLevel) { model.Nodes.AddRange(nodeToAdd.Children); } } return model; }