I have an XML file that looks like this:
<SiteMenuItems>
<SiteMenuItem text="Home" navigateurl="/Default.aspx" tooltip="Return Home" />
<SiteMenuItem text="Admin" roles="Admin">
<SiteMenuItem text="User Admin" navigateurl="/Authorized/UserAdmin/Default.aspx" roles="SuperAdmin" />
</SiteMenuItem>
</SiteMenuItems>
Using the example I found at at this StackOverflow question, I was able to come up with the following code:
public string GetMenu()
{
XDocument xmlDoc = XDocument.Load(HttpContext.Current.Server.MapPath(@"~/App_Data/SiteMenu.xml"));
xmlDoc = FilterRoles(xmlDoc); //Working on role problem
return ExecuteXSLTransformation(xmlDoc.ToString());
}
private XDocument FilterRoles(XDocument xmlDoc)
{
XElement element = xmlDoc.Element("SiteMenuItems");
XElement root = new XElement("SiteMenuItems",
(
from sm
in element.Elements("SiteMenuItem")
where UserHelper.IsUserAuthorized(sm.Attribute("roles"))
select new XElement(sm))
);
XDocument menuXml = new XDocument();
menuXml.Add(root);
return menuXml;
}
The problem I have is that the code is only filtering the first level:
<SiteMenuItem text="Admin" roles="Admin">
But I can't figure out how to filter the internal SiteMenuItem as well:
<SiteMenuItem text="User Admin" navigateurl="/Authorized/UserAdmin/Default.aspx" roles="SuperAdmin" />
As it is now, if you have the Admin role, it also returns the "User Admin" item.
[UPDATE] Thanks to woodings, my child nodes are now going through the "IsUserAuthorized" test.
Unfortunately, even though the test is returning "false" for the "User Admin" node, that node is still getting returned as part of the overall XML document.
I was hoping it would return something like this:
<SiteMenuItems>
<SiteMenuItem text="Home" navigateurl="/Default.aspx" tooltip="Return Home" />
<SiteMenuItem text="Admin" roles="Admin">
</SiteMenuItem>
</SiteMenuItems>
Any ideas?
Thanks again!!
I solved my problem and even eliminated the FilterRoles()
method:
public string GetMenu()
{
XDocument xmlDoc = XDocument.Load(HttpContext.Current.Server.MapPath(WebConfigHelper.GetSiteMenu));
xmlDoc.Descendants().Where(element => !UserHelper.IsUserAuthorized(element.Attribute("roles"))).Remove();
return XsltTransformHelper.ExecuteXslTransformation(xmlDoc.ToString(), HttpContext.Current.Server.MapPath(WebConfigHelper.GetSiteMenuTransform));
}
Thanks for everyone's help!!!
XElement.Elements() returns only immediate children of that particular element. Use XElement.Descendants() instead.
private XDocument FilterRoles(XDocument xmlDoc)
{
XElement element = xmlDoc.Element("SiteMenuItems");
XElement root = new XElement("SiteMenuItems",
(
from sm
in element.Descendants("SiteMenuItem")
where UserHelper.IsUserAuthorized(sm.Attribute("roles"))
select new XElement(sm))
);
XDocument menuXml = new XDocument();
menuXml.Add(root);
return menuXml;
}