|
-
Jan 18th, 2008, 06:16 PM
#1
Thread Starter
Lively Member
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 !
-
Jan 19th, 2008, 06:39 PM
#2
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
-
Jan 21st, 2008, 11:22 AM
#3
Thread Starter
Lively Member
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 ?
-
Jan 21st, 2008, 11:37 AM
#4
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;
}
}
-
Jan 21st, 2008, 11:41 AM
#5
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" />
-
Jan 21st, 2008, 12:04 PM
#6
Thread Starter
Lively Member
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.
-
Jan 21st, 2008, 12:15 PM
#7
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
-
Jan 21st, 2008, 12:37 PM
#8
Thread Starter
Lively Member
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
-
Jan 22nd, 2008, 05:07 AM
#9
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|