Creating a tree like left menu in Sitecore using XSLT

This is one of my oldest tricks in my book. The tree-like left menu is used for almost any website I do, and will work like on this site (example site is not developed by me nor by Pentia). This image is from a website using the menu:

Sample Menu

Sample Menu

The XSLT renders a multilevel left menu, usually placed on pages on websites utilizing a sectional top menu. The menu will fold out any subitems below the current page, and will display the entire tree structure from the current page and upwards to the sectional page that the left menu is placed under.

In this simplified example I use pages with the menu title placed in the field Menu_Title, and I use a checkbox called Show_In_Menu to hide items that is not to be shown in the left menu.

The left menu is initialized with the current section page that will act as the root item for the menu. If you use the home page as your section item it will render the complete web site.

<xsl:template match="*" mode="main">
  <!-- Get the root item -->
  <xsl:variable name="section" select="ancestor-or-self::item[@id = $home/item/@id]"/>
  <!-- Render the menu from the root item and downwards -->
  <xsl:call-template name="renderMenu">
    <xsl:with-param name="root" select="$section"/>
    <xsl:with-param name="level" select="0"/>
    <xsl:with-param name="items" select="$section/item[sc:fld('Show_In_Menu',.) = '1']"/>
  </xsl:call-template>
</xsl:template>

Parameter root identifies the root item of the menu. Level is used for styling the menu (if you use different styles for the different levels). Items is a list of all items below the root item the must be rendered in the menu. In this example this includes all items where the field Show_In_Menu is checked.

The menu is rendered recursively by letting the renderMenu template call itself for each level it has to render.

<xsl:template name="renderMenu">
  <xsl:param name="root"/>
  <xsl:param name="level"/>
  <xsl:param name="items"/>

  <xsl:if test="$items">
<ul class="level{$level}">
      <xsl:for-each select="$items">
        <xsl:variable name="subItems" select="item[sc:fld('Show_In_Menu',.) = '1']"/>
	<li>
          <!-- Apply CSS to the link -->
          <xsl:variable name="selectedClass">
            <!-- Item has children -->
            <xsl:if test="$subItems">children</xsl:if>
            <!-- Item is open (one of it's children is the current page -->
            <xsl:if test="$subItems and @id = $selectedItem/ancestor-or-self::item/@id"> open</xsl:if>
            <!-- Item is the current page -->
            <xsl:if test="@id = $selectedItem/@id"> selected</xsl:if>
          </xsl:variable>

          <!-- Write link including generated CSS tag -->
          <a href="{sc:path(.)}" class="{$selectedClass}">
            <sc:text field="Menu_Title"/>           
          </a>

          <!-- Go further down the tree and render children -->
          <xsl:if test="@id = $selectedItem/ancestor-or-self::item/@id">
            <xsl:call-template name="renderMenu">
              <xsl:with-param name="root" select="."/>
              <xsl:with-param name="level" select="$level+1"/>
              <xsl:with-param name="items" select="$subItems"/>
            </xsl:call-template>
          </xsl:if>
       </li>
      </xsl:for-each></ul>
  </xsl:if>
</xsl:template>

The template renders all items of the first level, but second, third and later levesl are only rendered if the current page is found in that branch. This gives the menu its fold-out like behaviour.
Please note how I style the menu link. The variable selectedClass is set with different content depending of the properties of the link to render. The example uses the three most commonly used styles applied: When the link has children, when the link has children, and the current page is one of these children and when the link is the current page.
Yes, it’s that simple to do an advanced left menu in Sitecore. I have also done the same menu for Umbraco, but that’s a different matter.

Using declarative security in Sitecore

Forms data viewer is one example of a webform in Sitecore

The Forms data viewer is one example of a webform in Sitecore

Writing XAML applications for use in the Sitecore shell can be very tricky. And I admit that I often decide to use a webform instead. Especially if I need to write a minor application that does not use Sitecore data as such, but still needs to be a part of the Sitecore desktop.

One of the downsides of using an .aspx page in the shell is (besides the fact that the styling usually ends up being completely different from the Sitecore styling) is that the application can be called from outside of the Shell context. This is especially a problem if the application is used in public websites, as everyone, including my web site visitors, will be able to execute the page, if they know the URL.

One of the solutions is to implement my own Generic Identity and use declarative security in my webform. And it’s quite easy too. This code can be expanded, but I have kept it simple to demonstrate the principals. Implementing yout own security context requires a generic identity (a user) and a generic principal (a list of groups). The generic identity looks like this:

using System.Security.Permissions;
using System.Collections.Generic;
using System.Threading;
using System.Security.Principal;

/// <summary>
/// Class imlementing a generic identity
/// which equals one Sitecore user
/// </summary>
public class SitecoreIdentity : IIdentity
{
  private Sitecore.Security.Accounts.User _user;

  public SitecoreIdentity()
  {
    _user = Sitecore.Context.User; 
  }

  #region IIdentity Members

  public string AuthenticationType
  {
    // I cheat a little bit. Sitecore returns an empty AuthenticationType
    // so I use the domain name as authenticationtype instead
    get { return Sitecore.Context.Domain.Name; }
  }

  public bool IsAuthenticated
  {
    get { return _user.Identity.IsAuthenticated; }
  }

  public string Name
  {
    get { return _user.Name; }
  }

  #endregion
}

An identity is accompanied by a principal, which equals the roles that the identity (user) belongs to:

/// <summary>
/// Class implementing a generic principal
/// which equals the groups one sitecore user
/// belongs to
/// </summary>
public class SitecorePrincipal : IPrincipal
{
  private List<string> _roles = new List<string>();
  private IIdentity _identity;
  private Sitecore.Security.Accounts.User _user;

  public SitecorePrincipal(IIdentity identity)
  {
    _identity = identity;
    _user = Sitecore.Context.User; 
    // I add the administrator as a role to my principal so I can query it
    // when using declarative security
    if (Sitecore.Context.User.IsAdministrator)
      _roles.Add("Administrator");
    // Add all role names from the current user to my principal
    foreach (Sitecore.Security.Accounts.Role userRole in _user.Roles)
    {
      _roles.Add(userRole.Name);
    }
  }

  #region IPrincipal Members
  public IIdentity Identity { get { return _identity; } }
  public bool IsInRole(string role) { return _roles.Contains(role); }
  #endregion
}

I can now assign the current thread’s principal of the current webform to my own principal:

void Page_Load(object sender, System.EventArgs e)
{
  // Create new user
  SitecoreIdentity user = new SitecoreIdentity();
  // Assign the roles to that user
  SitecorePrincipal roles = new SitecorePrincipal(user);
  // Assign the roles to the current thread
  Thread.CurrentPrincipal = roles;
}

My webform is now runing under the security context of my Sitecore user, and I can now use declarative security to allow or disallow execution of code. The following function will only execute if a Sitecore user is authenticated:

[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
private void WriteText()
{
  Response.Write("Authentication: " + Thread.CurrentPrincipal.Identity.AuthenticationType);
  Response.Write("Is authenticated: " + Thread.CurrentPrincipal.Identity.IsAuthenticated);
  Response.Write("Name: " + Thread.CurrentPrincipal.Identity.Name);
}

It is the PrincipalPermission attribute that sets the security on my function. If the current Sitecore user is not logged in, .net will throw an exception.

Here is another example. This will allow access if the user is a Sitecore administrator, and block everyone else:

[PrincipalPermission(SecurityAction.Demand, Role="Administrator")]
private void WriteText()
{
  // ... your code here
}