Thanks to MikeSmithDev's comment, I've managed to sort out a nice solution. If anyone else comes across the same problem, here's what I did:
In my SiteMap, I added a custom attribute HideFromMenu
:
<siteMapNode title="Add Page" description="Page to Add stuff"
roles="Administrator" url="~/AddPage.aspx" HideFromMenu="true" />
In my Menu control, I added the OnMenuItemDataBound
attribute:
<asp:Menu ID="Menu1" runat="server" DataSourceID="siteMapSource"
OnMenuItemDataBound="Menu1_MenuItemDataBound" >
And in the master's code-behind:
protected void Menu1_MenuItemDataBound(object sender, MenuEventArgs e)
{
SiteMapNode node = (SiteMapNode)e.Item.DataItem;
if (node["HideFromMenu"] == "true")
{
if (e.Item.Parent != null) //if this item has a parent..
e.Item.Parent.ChildItems.Remove(e.Item); //use parent to remove child..
else
Menu1.Items.Remove(e.Item); //else.. remove from menu itself.
}
}
Finally, to ensure the user doesn't access pages off-boundary, I added some validation in my master page..
var authorizedRoles = SiteMap.CurrentNode.Roles; //obtain the list of authorized roles for the current page
if (authorizedRoles == null || authorizedRoles.Count == 0) // no roles defined for this node
isAuthorized = false;
else
{
if (authorizedRoles.Contains("*")) // this page can be accessed by everyone
isAuthorized = true;
if (!isAuthorized)
{
foreach (string authorizedRoleName in authorizedRoles)
{
if (Roles.IsUserInRole(authorizedRoleName) == true)
{
isAuthorized = true;
break;
}
}
}
}
if (!isAuthorized)
Response.End(); // unauthorised user; kill the page.
I hope this helps whoever faces the same problem. Please let me know if there are better ways to achieve the same result.