Results 1 to 9 of 9

Thread: Dynamic Menus WITHOUT sitemap

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Aug 2006
    Posts
    85

    Dynamic Menus WITHOUT sitemap

    hi all,

    I have a menu on my masterpage that i want to control access to based on login roles. i watched a nice video on this at asp.net/learn, but i dont know if this is the right route for me to take. The reason is that it seems that all of the role management and the access rules need to be done via the asp.net security peice. After i finish this up i want to create a page that will allow the end-user to decide which roles have access to what, as well as determine which users are members of which roles.

    So i had assumed that the only way for me to do this was to create another table in my DB for the menu control, and another for the Users/Roles.

    I was just wondering if anyone had done this before, and could give me some advice, or experience-based lessons on the best way to get this done.

    Any advice, or links to documentation on how to get this done would be greatly appreciated !!!

    thanks all !

  2. #2
    Frenzied Member brin351's Avatar
    Join Date
    Mar 2007
    Location
    Land Down Under
    Posts
    1,293

    Re: Dynamic Menus WITHOUT sitemap

    You may or may not need a roleMenu table depending on how difficult it is to map roles to menu items and how frequently that changes, if it's not going to change I'd suggest just hard code that.

    as far as roles generally you have tables such as member - memberRole - role, where memberRole holds only the member and role keys they from a composite primary key so members can be placed in multipul roles and data integrity is enforced by the relationship.

    For show/hide menu control items based on the members role that is fairly easy such as

    Code:
    sub page_load(...)
    
    if not user.isInRole("boss") then
       'hide menu items only available to boss role
       myMenu.items(0).childitems().removeAt(2)
    
       'hide boss menu
       bossMenu.visible = false
    end if
    
    end sub
    if your using the asp.net membership and role providers and tables storedProcs etc created by them there a probably other ways of doing it. I don't like to use them personally.

    I can post the code I use to login/maintian asp.net user roles for a session if you need.
    Last edited by brin351; Jan 19th, 2008 at 06:53 PM. Reason: extra comment

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Aug 2006
    Posts
    85

    Re: Dynamic Menus WITHOUT sitemap

    I think i may have gotten ahead of myself. I think first i need to figure out how to fill a menu control from a DB, so that i can create the DB for the menu. maybe some one has seen a good document somewhere that they could link me to. i have read a couple of articles, but they seems to be a bit more involved than what im trying to do, so i just end up getting confused.

    Lets say, for example, that i have a DB with the following columns:

    MenuID, MenuName, MenuURL, ParentNode.

    MenuID is just a consecutive number 1-X. MenuName is the text that i want to display on the menu for this item. MenuURL would be the link that i want this menu item to navigate to. And ParentNode would be the MenuID of the menu item i want this to be a sub item of.

    how would i go about filling this menu control based off of the DB that i have setup ?

  4. #4
    I'm about to be a PowerPoster! mendhak's Avatar
    Join Date
    Feb 2002
    Location
    Ulaan Baator GooGoo: Frog
    Posts
    38,170

    Re: Dynamic Menus WITHOUT sitemap

    If you want to use this 'menu' data in your database as your 'sitemap', then you can create a custom sitemap provider which takes the existing data and converts it to a format that is acceptable to the menu control.

    Here's an example of a custom sitemap provider

    Code:
    public class MySiteMapProvider : StaticSiteMapProvider  
        {
            static readonly string _errmsg1 = "Missing connectionStringName attribute";
            static readonly string _errmsg2 = "Duplicate node ID";
            SiteMapNode _root = null;
            
    
            public override void Initialize(string name, NameValueCollection attributes)
            {
                base.Initialize(name, attributes);
    
                if (attributes == null)
                    throw new ConfigurationException(_errmsg1);
    
                
            }
    
            [MethodImpl(MethodImplOptions.Synchronized)]
            public override SiteMapNode BuildSiteMap()
            {
                // Return immediately if this method has been called before
                if (_root != null) return _root;
    
                // Create a dictionary for temporary node storage and lookup
                Dictionary<int, SiteMapNode> nodes = new Dictionary<int, SiteMapNode>(16);
    
                // Query the database for site map nodes
                SqlConnection connection = new SqlConnection(RBI.Flight.Framework.Configuration.Settings.ConnectionString());
    
                try
                {
                    connection.Open();
                  //  SqlCommand command = new SqlCommand(
                  //      "SELECT ID, Title, Description, Url, " +
                  //      "Roles, Parent FROM vw_MenuData ORDER BY ID", connection);
                  
                    SqlCommand command = new SqlCommand("GetSiteMap", connection);
                    command.CommandType = CommandType.StoredProcedure;
    
                    SqlDataReader reader = command.ExecuteReader();
                    int id = reader.GetOrdinal("ID");
                    int url = reader.GetOrdinal("Url");
                    int title = reader.GetOrdinal("Title");
                    int desc = reader.GetOrdinal("Description");
                    int roles = reader.GetOrdinal("Roles");
                    int parent = reader.GetOrdinal("Parent");
    
                    if (reader.Read())
                    {
                        // Create the root SiteMapNode
                        _root = new SiteMapNode(this,
                           reader.GetInt32(id).ToString(),
                           reader.IsDBNull(url) ? null : reader.GetString(url),
                           reader.GetString(title),
                           reader.IsDBNull(desc) ? null : reader.GetString(desc));
    
                        if (!reader.IsDBNull(roles))
                        {
                            string rolenames = reader.GetString(roles).Trim();
                            if (!String.IsNullOrEmpty(rolenames))
                            {
                                string[] rolelist = rolenames.Split(
                                    new char[] { ',', ';' }, 512);
                                _root.Roles = rolelist;
                            }
                        }
    
                        //  Add "*" to the roles list if no roles are specified
                        if (_root.Roles == null) _root.Roles = new string[] { "*" };
    
                        // Record the root node in the dictionary
                        if (nodes.ContainsKey(reader.GetInt32(id)))
                            throw new ConfigurationException(_errmsg2);
                        nodes.Add(reader.GetInt32(id), _root);
    
                        // Add the node to the site map
                        AddNode(_root, null);
    
                        // Build a tree of SiteMapNodes underneath the root
                        while (reader.Read())
                        {
                            SiteMapNode node = new SiteMapNode(this,
                              reader.GetInt32(id).ToString(),
                              reader.IsDBNull(url) ? null : reader.GetString(url),
                              reader.GetString(title), reader.IsDBNull(desc) ?
                                  null : reader.GetString(desc));
    
                            if (!reader.IsDBNull(roles))
                            {
                                string rolenames =
                                    reader.GetString(roles).Trim();
                                if (!String.IsNullOrEmpty(rolenames))
                                {
                                    string[] rolelist = rolenames.Split
                                        (new char[] { ',', ';' }, 512);
                                    node.Roles = rolelist;
                                }
                            }
    
                            // If the node lacks roles information,
                            // "inherit" that information from its parent
                            SiteMapNode parentnode = nodes[reader.GetInt32(parent)];
                            if (node.Roles == null)
                                node.Roles = parentnode.Roles;
    
                            // Record the node in the dictionary
                            if (nodes.ContainsKey(reader.GetInt32(id)))
                                throw new ConfigurationException(_errmsg2);
                            nodes.Add(reader.GetInt32(id), node);
    
                            // Add the node to the site map
    
                            //Hold the URL in a tempoary string
                            string temporaryUrl = node.Url;
    
                            if (node.Url.Contains("http"))
                            {
                                node.Url = node.Url.Replace("http://", "/");
                            }
                            AddNode(node, parentnode);
    
                            //Set it back to the original.
                            node.Url = temporaryUrl;
                            
                        }
                    }
                }
                finally
                {
                    connection.Close();
                }
    
                // Return the root SiteMapNode
                return _root;
            }
    
            protected override SiteMapNode GetRootNodeCore()
            {
                BuildSiteMap();
                return _root;
            }
        }

  5. #5
    I'm about to be a PowerPoster! mendhak's Avatar
    Join Date
    Feb 2002
    Location
    Ulaan Baator GooGoo: Frog
    Posts
    38,170

    Re: Dynamic Menus WITHOUT sitemap

    The data received from the database needs to convert your existing data to a format similar to

    ID, Title, Description, URL, Roles, Parent.

    Once you do that, you then have a sitemap provider which you can give to the ASP.NET Menu control.

    To do that, in web.config

    Code:
      <siteMap defaultProvider="MySiteMapProvider" enabled="true">
                <providers>
                    <add name="MySiteMapProvider" type="Blah.Blah.MySiteMapProvider" />
                </providers>
            </siteMap>
    And then in your code,

    Code:
    <asp:SiteMapDataSource ID="smds1" runat="server" SiteMapProvider="MySiteMapProvider" />

  6. #6

    Thread Starter
    Lively Member
    Join Date
    Aug 2006
    Posts
    85

    Re: Dynamic Menus WITHOUT sitemap

    Hmm, i was really hoping to not have to use a sitemap at all. Is this my only option ? Like i HAVE to have the sitemap in order to fill the menu from the DB? there is no other way, using a SQLDataSrouce directly ? The reason i ask is because i will have a column for each role type, with a 1 or 0 to specify if that role can access that menu piece. i had intended on using a datasource to use a select statement to pull only the menu items that a users group can see.

  7. #7
    I'm about to be a PowerPoster! mendhak's Avatar
    Join Date
    Feb 2002
    Location
    Ulaan Baator GooGoo: Frog
    Posts
    38,170

    Re: Dynamic Menus WITHOUT sitemap

    In my opinion, if the menu isn't going to be as straightforward as simply specifying a role and what's visible, you're better off rendering your own menu with the logic inbuilt. That said, with the menu control you have the option of specifying asp:MenuItems

  8. #8

    Thread Starter
    Lively Member
    Join Date
    Aug 2006
    Posts
    85

    Re: Dynamic Menus WITHOUT sitemap

    Yea i have built this menu statically already using:

    Code:
    <asp:MenuItem Text="File" Value="File">
          <asp:MenuItem NavigateUrl="~/Page1.aspx" Text="Add New" Value="Page1"></asp:MenuItem>
          <asp:MenuItem NavigateUrl="~/Page2.aspx" Text="Edit File" Value="Page2"></asp:MenuItem>
    </asp:MenuItem>
    <asp:MenuItem Text="Edit" Value="Edit">
          <asp:MenuItem NavigateUrl="~/Page3.aspx" Text="Edit File" Value="Page3"></asp:MenuItem>
          <asp:MenuItem NavigateUrl="~/Page4.aspx" Text="Assign File" Value="Page4"></asp:MenuItem>
    </asp:MenuItem>
    Now i want to put that exact menu into a DB and add a few columns for Role1, Role2, and Role3. Then i wanted to be able to build this menu using a datasource so that i could just say "SELECT * from Menu WHERE Role1 = 1" to populate this menu with everything Role1 should be able to see.... i had assumed that this proccess would be pretty straightforward, and possibly rather easy, but its not as easy as i had hoped

  9. #9
    I'm about to be a PowerPoster! mendhak's Avatar
    Join Date
    Feb 2002
    Location
    Ulaan Baator GooGoo: Frog
    Posts
    38,170

    Re: Dynamic Menus WITHOUT sitemap

    Look at post #4 and #5 then, it's what you're asking for. The fact that you'll use a sitemapdatasource is a minor inconvenience.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width