Inconvenient body id for anonymous users


A few weeks ago I presented you a solution for creating dynamic layouts with nothing more than some CSS definitions and a dynamic body id. Using exactly the same HTML markup you can create a different layout of your page elements what makes it an extremely efficient and easy to maintain solution. While the concept is pretty straight-forward, applying it in practice to a real-life SharePoint Server Web Content Management solution has one drawback that you should keep in mind.

Anatomy of body id revisited

As described in the previous article the idea of body id is simple: by decorating the body element of your HTML page with a different ID attribute, you can benefit of the power of CSS and layout your page elements in a different way. What I have also showed you is, that because we are working with the SharePoint platform, we cannot use the ID attribute of the body element, but instead we can create a wrapper div and apply to it dynamic class attribute. While it is a little different semantically, it allows you to achieve comparable results.

The concept of body id relies on the ability of dynamically generating the value of the ID based on some information, like section of the website, particular page or any other information that allows you to determine how the page elements should be positioned on the page. The great benefit of working with SharePoint is, that using Page Layouts for this purpose makes a perfect match.

The problem with Page Layouts

In order to dynamically generate the body id based on the Page Layout, you have to determine which Page Layout is being used by the current page. And this is where things get challenging.

The code is straight-forward:

if (SPContext.Current != null &&
    SPContext.Current.ListItem != null &&
    PublishingPage.IsPublishingPage(SPContext.Current.ListItem))
{
    PublishingPage page = PublishingPage.GetPublishingPage(SPContext.Current.ListItem);
    if (page.Layout != null)
    {
        // generate the body id based on the name of the Page Layout here
    }
}

While it works perfectly with authenticated users, try to hit the page without logging in. All that you will see is the authentication prompt asking you to login. If you attach the debugger you will find out, that you get the authentication prompt as soon as the PublishingPage.Layout property is being read.

One way you could solve this issue is to use Privileges Elevation, like:

if (SPContext.Current != null &&
    SPContext.Current.ListItem != null &&
    PublishingPage.IsPublishingPage(SPContext.Current.ListItem))
{
    string siteUrl = SPContext.Current.Web.Url;
    Guid pagesListId = PublishingWeb.GetPagesListId(SPContext.Current.Web);
    Guid itemId = SPContext.Current.ListItem.UniqueId;

    SPSecurity.RunWithElevatedPrivileges(delegate() {
        using (SPSite site = new SPSite(siteUrl))
        {
            using (SPWeb web = site.OpenWeb())
            {
                SPList pages = web.Lists[pagesListId];
                SPListItem listItem = pages.Items[itemId];
                PublishingPage page = PublishingPage.GetPublishingPage(listItem);
                if (page.Layout != null)
                {
                    // generate the body id based on the name of the Page Layout
                }
            }
        }
    });
}

While the above code snippet does the job, it has one serious issue: performance penalty. In order to determine the body id properly, the above code must be run on every request for every page. You could limit the penalty by caching the pages using the Output Cache, but still it is very expensive resource-wise to open a whole new instance of SPSite and SPWeb just to retrieve the current Page Layout on every request.

Body id based on Page Layout – is it really the perfect match?

Using different Page Layouts to layout page elements in different ways fits the idea behind the Page Layouts perfectly. Not only they allow you to alter the positioning of the elements on the page but also to change the content of the page as well! And because all that we are doing while working with body id is changing the position, using different Page Layouts is even a little too heavy: after all the only thing that is different between all the different layouts is the name of the Page Layout. The contents of various Page Layouts are the same.

Using Page Layouts for this purpose has one more big benefit above other approaches. Using Page Layouts for changing layout of elements on the page feels natural to users who have been working with SharePoint Publishing Features for a while now. Alternative approaches like storing the selected layout in a Page Field might be better performing but might not be as intuitive as using Page Layouts.

So what is the verdict?

Whether you can use Page Layouts for generating dynamic body ids or not depends on both your website and the users responsible for content authoring. If the website is very dynamic and you cannot do really much about caching, you might want to consider investing in educating users about different approaches like using Page Fields to change the layout of the page. However if the load on the website isn’t that heavy and you can benefit of the caching capabilities of SharePoint Server 2010 using Page Layouts might just be the way to go. Eventually it’s all about making an educated choice suitable for your scenario.

Technorati Tags: SharePoint,SharePoint 2010,MOSS 2007,SharePoint Server 2010,WCM

Others found also helpful: