Hi,
Here are the answers, will test these things and let you know
1. Did this performance problem begin recently, or has it always been slow? If recently, what's changed?
It was from the start, that is, with a database with very few members.
2. What happens to the timing if you remove the check for member permission? If the performance is still slow then it isn't the permission check and we can rule that out. If it is fast then it is entirely in the permission checking.
I tested this and it goes down to 3 seconds. For all entries in the trace "umbracoMacro After performing transformation" it takes about 0,5 to 1 second. Which is of course much better then the 60 seconds I had before.
3. If the issue is in the permission checking, what happens if you create a member group with only a few members? If it is still slow then we know it isn't related to the number of members but to some overhead in the permission checking generally. If it is fast for a few members then perhaps you can optimize the loop that checks every one's permission?
When I started I had 10 members, even then it was slow, but nog as it is now, this is unbearable.
I guess it is in the access checking code. I think I need to write my own xslt help or do the navigation from a user control.
Where I can do some caching as well, I guess ...
4. Any other behavior pattern you can see?
No, that is it.
For the code , teh hasaccesss check has been commented
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:Stylesheet [
<!ENTITY nbsp " ">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxml="urn:schemas-microsoft-com:xslt" xmlns:umbraco.library="urn:umbraco.library" version="1.0" exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="html" indent="yes"/>
<xsl:param name="currentPage"/>
<!-- Input the documenttype you want here -->
<xsl:variable name="documentTypeAlias" select="string('WebPage')"/>
<xsl:variable name="source" select="$currentPage//ancestor::node[@nodeName = 'Intranet']/@id"/>
<xsl:template match="/">
<!-- no UL element coming from the template ? -->
<!-- Home Button -->
<!-- Add current when at home-->
<li>
<xsl:if test="$currentPage/@id = number($source)">
<xsl:attribute name="class">
<xsl:value-of select="'current'"/>
</xsl:attribute>
</xsl:if>
<a href="/intranet.aspx">Home</a>
</li>
<!-- Added naviHide option to hide the page from teh navigation -->
<!-- Top Level -->
<xsl:for-each select="umbraco.library:GetXmlNodeById($source)/node [@nodeTypeAlias = $documentTypeAlias and string(data [@alias='umbracoNaviHide']) != '1']">
<!--xsl:if test="umbraco.library:HasAccess(@id, @path)"-->
<li id="z{@id}">
<xsl:if test="contains($currentPage/@path,@id)">
<xsl:attribute name="class">
<xsl:value-of select="'current'"/>
</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl(@id)}">
<xsl:value-of select="@nodeName"/>
</a>
<xsl:if test="./node[@nodeTypeAlias = 'WebPage' and string(data [@alias='umbracoNaviHide']) != '1']">
<ul>
<!-- Divisions -->
<xsl:for-each select="./node[@nodeTypeAlias = 'WebPage']">
<!--xsl:if test="umbraco.library:HasAccess(@id, @path) and string(data [@alias='umbracoNaviHide']) != '1'"-->
<li>
<a href="{umbraco.library:NiceUrl(@id)}">
<xsl:value-of select="@nodeName"/>
</a>
<xsl:if test="./node[@nodeTypeAlias = 'WebPage' and string(data [@alias='umbracoNaviHide']) != '1']">
<ul>
<!-- Countries -->
<xsl:for-each select="./node[@nodeTypeAlias = 'WebPage' and string(data [@alias='umbracoNaviHide']) != '1'] ">
<!--xsl:if test="umbraco.library:HasAccess(@id, @path)"-->
<li>
<a class="cLevel" href="{umbraco.library:NiceUrl(@id)}">
<xsl:value-of select="@nodeName"/>
</a>
<!-- Business Unit Cluser: do not show -->
<xsl:if test="./node[@nodeTypeAlias = 'WebPage' and string(data [@alias='umbracoNaviHide']) != '1']">
<ul>
<xsl:for-each select="./node[@nodeTypeAlias = 'WebPage']/node[@nodeTypeAlias = 'WebPage' and string(data [@alias='umbracoNaviHide']) != '1'] ">
<!--xsl:if test="umbraco.library:HasAccess(@id, @path)"-->
<li>
<a class="buLevel" href="{umbraco.library:NiceUrl(@id)}">
<xsl:value-of select="@nodeName"/>
</a>
</li>
<!--/xsl:if-->
</xsl:for-each>
</ul>
</xsl:if>
</li>
<!--/xsl:if-->
</xsl:for-each>
</ul>
</xsl:if>
</li>
<!--/xsl:if-->
</xsl:for-each>
</ul>
</xsl:if>
</li>
<!--/xsl:if-->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Any ideas on how to do the navigation with a usercontrol / or a better has access method?
It seems that the hasAccess code is looping over all the groups of the member, and I have a lot of members
that have over 30 groups assigned to them.
Maybe that causes a problem?
Code:
public static bool HasAccess(int DocumentId, string Path, cms.businesslogic.member.Member Member)
{
bool hasAccess = false;
if (!IsProtected(DocumentId, Path))
hasAccess = true;
else
{
XmlNode currentNode = getPage(getProtectedPage(Path));
if (Member != null)
{
IDictionaryEnumerator ide = Member.Groups.GetEnumerator();
while(ide.MoveNext())
{
cms.businesslogic.member.MemberGroup mg = (cms.businesslogic.member.MemberGroup) ide.Value;
if (currentNode.SelectSingleNode("./group [@id=" + mg.Id.ToString() + "]") != null)
{
hasAccess = true;
break;
}
}
}
}
return hasAccess;
}