Contents
Introduction
The MVCSiteMapProvider is powerful and can generate the site map menu from xml, but sometime you may want to dynamic to generate the menu by user access rights, in this time we can use the dynamicNodeProvider for thatUse the code
Using the code
1.Create a custom SiteMapProvider and implement the IDynamicNodeProvider interface
public class CoderBlogSiteMapProvider : IDynamicNodeProvider { public IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode nodes) { var returnValue = new List<DynamicNode>(); return returnValue; } public bool AppliesTo(string providerName) { if (string.IsNullOrEmpty(providerName)) return false; return GetType() == Type.GetType(providerName, false); } }
2. In the GetDynamicNodeCollection method, you can check the access righs and get current menu items and create the dynamic node
//get the pages by access right var pageIds = CoderBlogAccessRight.GetAccessPageIds(db); var accessMmenus = db.Query<ACCESS_RIGHT_Page>("Select * from ACCESS_RIGHT_Page where PageId in @pageIds order by DisplayPriority ", new { pageIds = pageIds }); foreach (var page in accessMmenus) { //create the dynamic node for site map DynamicNode node = new DynamicNode() { // menu title Title = page.Name, // parent page id ParentKey = page.ParentId.HasValue ? page.ParentId.Value.ToString() : "", // Node Key Key = page.PageId.ToString(), // Action Name Action = page.Action, // Controller Name Controller = page.Controller, // Url (if not null will use this url replace to controller and action) Url = page.Url, // If set the url to # then just not can click Clickable = page.Url != "#" }; if (!string.IsNullOrWhiteSpace(page.RouteValues)) { // get the RouteValues // ex. Key1=value1,Key2=value2... node.RouteValues = page.RouteValues.Split(',').Select(value => value.Split('=')) .ToDictionary(pair => pair[0], pair => (object)pair[1]); } node.Attributes.Add("visibility", page.IsActive ? "" : "!MenuHelper"); returnValue.Add(node); }
3. The full source code should be as below
namespace CoderBlog { public class CoderBlogSiteMapProvider : IDynamicNodeProvider { public IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode nodes) { var returnValue = new List<DynamicNode>(); //check whether the user has been login if (CoderBlogSession.Instance.UserInfo != null) { using (var db = DBService.Connection) { //get the page id by access rights var pageIds = CoderBlogAccessRight.GetAccessPageIds(db); var accessMmenus = db.Query<ACCESS_RIGHT_Page>("Select * from ACCESS_RIGHT_Page where PageId in @pageIds order by DisplayPriority ", new { pageIds = pageIds }); foreach (var page in accessMmenus) { DynamicNode node = new DynamicNode() { // menu title Title = page.Name, // parent page id ParentKey = page.ParentId.HasValue ? page.ParentId.Value.ToString() : "", // Node Key Key = page.PageId.ToString(), // Action Name Action = page.Action, // Controller Name Controller = page.Controller, // Url (if not null will use this url replace to controller and action) Url = page.Url, // If set the url to # then just not can click Clickable = page.Url != "#" }; if (!string.IsNullOrWhiteSpace(page.RouteValues)) { // get the RouteValues // ex. Key1=value1,Key2=value2... node.RouteValues = page.RouteValues.Split(',').Select(value => value.Split('=')) .ToDictionary(pair => pair[0], pair => (object)pair[1]); } node.Attributes.Add("visibility", page.IsActive ? "" : "!MenuHelper"); returnValue.Add(node); } } } return returnValue; } public bool AppliesTo(string providerName) { if (string.IsNullOrEmpty(providerName)) return false; return GetType() == Type.GetType(providerName, false); } } }
4. Add the dynamicNodeProvider attribute in Mvc.sitemap file
<mvcSiteMapNode title="Home" controller="Home" action="Index"> <mvcSiteMapNode title="Menu" dynamicNodeProvider="CoderBlog.CoderBlogSiteMapProvider, CoderBlog"/> </mvcSiteMapNode>
After that, you will find the site map menu dynamic generate by difference user rols!