Enable Disable Sitemap Menu Item Based on Role in ASP.Net

Let me tell you a little bit of the background of this article. Today I was tasked to develop a sitemap for one application of our organization. A Sitemap is an easy task but the criteria was for a menu of the sitemap that will be visible and invisible depending on role.

So, the concept is that, the menu will be enabling and disable depending on role. The truth to be told, I spent a couple of hours solving it, then in meantime, I was misguided by a fellow developer, hahah.. Oh, he too doesn't know, not intentionally.

Fine, so I thought that, let's show my POC to the community and someday one can save her a couple of hours. Fine, so I am planning to make the article as simple as possible and focus only on our necessary parts.

First of all, since we will work with a sitemap, we need to create one sitemap XML file and here is mine.

  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >  
  3.     <siteMapNode url="default.aspx" title="Home"  page" roles="P,S">  
  4.       <siteMapNode url="products.aspx" title="Products" roles="P">  
  5.         <siteMapNode url="products/product1.aspx" title="Product 1" roles="P" />  
  6.         <siteMapNode url="products/product2.aspx" title="Product 2" roles="P"/>  
  7.         <siteMapNode url="products/product3.aspx" title="Product 3" roles="P" />  
  8.       </siteMapNode>  
  9.       <siteMapNode url="services.aspx" title="Services"  roles="S" >  
  10.         <siteMapNode url="services/service1.aspx" title="Services 1" roles="S" />  
  11.         <siteMapNode url="services/service2.aspx" title="Services 2" roles="S" />  
  12.         <siteMapNode url="services/service3.aspx" title="Services 3" roles="S" />  
  13.       </siteMapNode>  
  14.     </siteMapNode>  
  15. </siteMap>

Add one Web form in the application and paste the following code into it. 

  1. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebForm.WebForm1" %>  
  2. <!DOCTYPE html>  
  3. <html xmlns="http://www.w3.org/1999/xhtml">  
  4. <head runat="server">  
  5.     <title></title>  
  6. </head>  
  7. <body>  
  8.     <form id="form1" runat="server">  
  9.     <div>  
  10.         <asp:Menu ID="Menu1" runat="server" Orientation="Horizontal" DataSourceID="SiteMapDataSource1">  
  11.         </asp:Menu>  
  12.         <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />  
  13.     </div>  
  14.     </form>  
  15. </body>  
  16. </html>

The code is very simple, we have just added one sitemap data source and one menu element. The menu item will be displayed depending on role.

The view of the page is something like this.

sitemap data source and one menu element

Here is the C# code of the same file:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Security.Principal;  
  5. using System.Web;  
  6. using System.Web.Security;  
  7. using System.Web.UI;  
  8. using System.Web.UI.WebControls;  
  9. namespace WebForm  
  10. {  
  11.     public partial class WebForm1 : System.Web.UI.Page  
  12.     {  
  13.         protected void Page_Load(object sender, EventArgs e)  
  14.         {  
  15.             string[] r = { "P" };  
  16.             HttpContext.Current.User = new GenericPrincipal(HttpContext.Current.User.Identity, r);  
  17.         }  
  18.     }  
  19. }

As we said, we will make the application very simple, so that I have discarded all the authentication part. I am just populating the user context in the page load. Currently the role is "P" for current user.

Now, if you look at the sitemap file, you will find that the product part is enabled for the user holding role “P”. The user without the “P” role cannot access the product part and it will be invisible. Fine, we are almost done, we only need to tune something in the web.config. Here is my web.config code.

  1. <?xml version="1.0"?>  
  2. <!--  
  3.   For more information on how to configure your ASP.NET application, please visit  
  4.   http://go.microsoft.com/fwlink/?LinkId=169433  
  5.   -->  
  6. <configuration>  
  7.     <system.web>  
  8.       <compilation debug="true" targetFramework="4.5" />  
  9.       <httpRuntime targetFramework="4.5" />  
  10.       <siteMap enabled="true">  
  11.         <providers>  
  12.           <clear/>  
  13.           <add siteMapFile="Web.sitemap"  
  14.                name="AspNetXmlSiteMapProvider"  
  15.                type="System.Web.XmlSiteMapProvider"  
  16.                securityTrimmingEnabled="true"/>  
  17.         </providers>  
  18.       </siteMap>  
  19.    </system.web>  
  20.     <location path="Products">  
  21.       <system.web>  
  22.         <authorization>  
  23.           <allow roles="P"/>  
  24.           <deny users="*" />  
  25.         </authorization>  
  26.       </system.web>  
  27.     </location>  
  28.     <location path="Services">  
  29.       <system.web>  
  30.         <authorization>  
  31.           <allow roles="S"/>  
  32.           <deny users="*" />  
  33.         </authorization>  
  34.       </system.web>  
  35.     </location>  
  36. </configuration>

At first we are configuring the sitemap and then we are just allowing and disallowing roles in the specific directory. Here is our application structure.

disallowing roles in particular directory

We are just implementing the role over the Product and Services directory.

Now, if we run the application then we will see that all menus under Services has been hidden automatically because we have set the role as "P".
 

But the user can see the product information. Here is the output screen.
 
output

Conclusion

If you think that only setting the role in a sitemap will automatically hide and show the role then you too will make the same mistake that I did, it will not. We need to specify the location path in the web.config file.


Similar Articles