Click here to Skip to main content
Click here to Skip to main content

User Controlled XML Menu For Site Navigation

, 9 Jul 2009
Rate this:
Please Sign up or sign in to vote.
A fully customizable ASP.NET website menu that can be set by site admin to control user access.

DBDrivenMenu

Introduction

First of all, a huge thanks for giving a good response to my first article on CodeProject. In this article, I would illustrate the use of bit operations on integers to help us make a cool customizable menu. As always, my motto is minimum programming effort.

Background

You need to have a good understanding of the .NET CLR to better understand this article, as the concept relies heavily on it.

Let me first of all brief you on the use of the bitwise '&' operator. This operator is used to check the status of bits in integer values. Note the following about '&':

  1. 0 & 1 = 0
  2. 1 & 0 = 0
  3. 0 & 0 = 0
  4. 1 & 1 = 1

I would not go into the details of converting an integer to bits. But just note the following property:

10111011 &  00100000 = 00100000

I.e., 187 & 32 = 32

Using the Code

We would need to add SQL CLR to our code, as applying '&' to an integer is illegal in C#. We do this by using the Microsoft.SqlServer.Server namespace. For building up this menu, we assign a score in the form of 2^n to each item as:

<?xml version="1.0"?>
<SiteMenu>
    <MenuItem Title="A" URL="Page1.aspx" Value="1">
        <MenuItem Title="A.1" URL="Page1-1.aspx" Value="2" />
        <MenuItem Title="A.2" URL="Page1-2.aspx" Value="4" />
    </MenuItem>

    <MenuItem Title="B" URL="Page2.aspx" Value="8">
        <MenuItem Title="B.1" URL="Page2-1.aspx" Value="16"/>
        <MenuItem Title="B.2" URL="Page2-2.aspx" Value="32"/>
    </MenuItem>

    <MenuItem Title="C" URL="Page3.aspx" Value="64">
        <MenuItem Title="C.1" URL="Page3-1.aspx" Value="128"/>
        <MenuItem Title="C.2" URL="Page3-2.aspx" Value="256">
            <MenuItem Title="C.2.1" URL="Page3-2-1.aspx" Value="512"/>
            <MenuItem Title="C.2.2" URL="Page3-2-2.aspx" Value="1024">
                <MenuItem Title="C.2.2.1" URL="Page3-2-2.aspx" Value="2048"/>
            </MenuItem>
        </MenuItem>
    </MenuItem>
</SiteMenu>

We also assign a score to each user that is calculated as the sum of all the values of menu items that we want the user to see. Say, we want a user to only see the Main menu A with all the subitems, then the score will be 1+2+4 = 7. Note that you need to add up the main menu score, i.e., the score of A, B, or C if you want to use any of its child menus.

Now, let's jump to the last critical part, that is the CLR code that performs the '&' operation with the menu's values to see whether a user is eligible to see the navigation link or not.

[Microsoft.SqlServer.Server.SqlFunction()]
private bool Addable(int score, int valueToCheck)
{
    return ((score & valueToCheck) == valueToCheck);
}

Now, all we need is a record of score of each user and get the required XML data source to bind to a menu or tree. Each menu item's value is checked for its '&' ability with the total score, to see if it fits the user's menu criteria.

if (score != 0)
{
    datasetReadXML = new DataSet();
    datasetMenuItems = new DataSet();
    xdsMenuData = new XmlDataSource();

    ///Necessary for Displaying Updated Values.
    xdsMenuData.EnableCaching = false;
    xdsMenuData.EnableViewState = false;

    ///Read XML and prepare a menu data holder.
    datasetReadXML.ReadXml(pathToXML);
    datasetMenuItems = datasetReadXML.Clone();

    ///Get required menu items in the holder.
    foreach (DataRow drWorker in datasetReadXML.Tables[0].Rows)
        if (Addable(score, Convert.ToInt32(drWorker["Value"])))
            datasetMenuItems.Tables[0].ImportRow(drWorker);

    ///Make a StringWriter to read XML.
    stringWriter = new System.IO.StringWriter();
    datasetMenuItems.WriteXml(stringWriter, XmlWriteMode.IgnoreSchema);

    ///Populate XMLDataSource with XML.
    xdsMenuData.Data = stringWriter.ToString();

    ///Bind menu or tree.
    TreeMenu.DataSource = xdsMenuData;
    Menu.DataSource = xdsMenuData;

    this.DataBind();
}

I have used XML to keep track of user scores. However, you may use your own choice of database to do the same. All you need is a score. The attached code is self explanatory.

Points of Interest

Please remember to set the EnableCaching and EnableViewState properties of the XML data source to false for getting the updated values. I have seen a lot of people on various forums going nuts over it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

MeraMBA.com
Software Developer HCL Technologies Limited
India India
Rahul has worked on several technologies in Microsoft's technology stack. He has been in field of software developemnt for two years. He started with ASP.net and graduated to Windows application develeopment. His technology experience includes C#, LINQ, T-SQL,T-SQL, XML, PL\SQL, C, C++, VB, WebServices..
 
Apart from all these he is working on some of the most recent technology offerings such as Windows Azure, SQL Azure, SQL Azure Sync framework, MS Dallas, Powershell etc.
 
His goal of knowledge is to possess knowledge that is sky high and earth deep.

Comments and Discussions

 
GeneralATTENTION PLEASE PinmemberMeraMBA.com9-Jul-09 19:49 
GeneralRe: ATTENTION PLEASE PinmemberMeraMBA.com11-Jul-09 5:07 
Generalvery nice... one thing PinmemberChowDawg9-Jul-09 10:48 
GeneralRe: very nice... one thing PinmemberMeraMBA.com9-Jul-09 19:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 9 Jul 2009
Article Copyright 2009 by MeraMBA.com
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid