Sitecore


I know I should be posting a video of the performance webinar but at over 350mb finding a decent way to host it is taking longer than expected. Instead I thought I’d post a little module I wrote which should help anyone who is having trouble keeping track of what items have overridden the presentation values in the standard template.

This is a common problem and becoming even more so as more people take advantage of the more advanced features in the Design Panel and OMS. The module is pretty straight forward, you install it and then can switch on and off an actionbar warning for overridden values as shown here:

You can then click on the icon to reset back to the standard values, it also shows a different tooltip/icon if the value is overridden but the same as the standard value.

Download

Thanks to everyone who attended Fridays webinar, as promised I’m uploading a recording but converting codecs, hosting etc is taking time. In the meantime here are the slides from the presentation, I’ll follow this with the code samples from the demonstrations.

Slides

Working at Sitecore Australia brings me into contact with a lot of interesting problems and gives me the opportunity to solve them in (hopefully) interesting ways. A customer recently made the fairly common request to find a way have Items appear in more than one place. What I mean by that is they were looking to have an item appear as a child item to multiple parent items, an example being a book item appearing under multiple genre items.

For this I wrote a Data Provider module called ItemMirror, below is a package with the book/genre example I mentioned and I’ve also included the code, both will be up on Shared Source very shortly.

Package

Code

Typically the solution to this problem is to have a multi-select field such as a treelistex on each of the genre items and select the books you want to appear under it, you then can leave it up to the renderings to sort out where each book appears. In the vast bulk of cases this is a sufficient solution but the customer felt that in this case it left 3 unresolved issues:

  1. Increased difficulty editing the book items.
  2. Sub-par URLs, instead of landing on site.com/genre/book.aspx you would either land on site.com/genre.aspx?bookid=xxx or link to site.com/bookrespository/book.aspx
  3. Increased difficulty creating renderings.

What they said was needed was the ability to have book items that are otherwise stored in the book repository (called bookpile in the image above) shown under the genre items as children. This would neatly solve all 3 problems they were having, only problem being that it wasn’t possible out of the box with Sitecore (yet) hence the need for the ItemMirror module.

Configuration of the ItemMirror is done via the ItemMirror.config include file which you should find in App_Config/Include once the package is installed. The only line you’ll want to change is the one which configures the active template and the field which picks the items to replicate:

<template id=”{2BA6F255-67F5-4EDD-B626-11224F707658}” field=”bookSelection” />

The module should support multiple templates so you can have both genre/book and category/product running on the same website.

Quick Disclaimer

  • Documentation is forthcoming, in fact the lack of that is what’s holding it back from going on Shared Source really, think of this as the beta release.
  • Yes the virtual items publish and yes they become “real” once that happens, this is mostly because I didn’t feel that having the ItemMirror system running on the web database was particular wise or necessary.
  • The use of the master database is currently hardcoded in, if anyone can “solve” the XPATH statement needed at Line 75 in MirrorProvider.cs please post in the comments, otherwise I’ll have it solved for the Shared Source version.

Otherwise enjoy and feel free to suggest improvements.

Update:

A few quick replies based on comments via email/msn.

You could have used the Inline Item List Field.

Yes but sadly it wasn’t actually released when we started, it could in fact still be used alongside the ItemMirror.

What about Wildcard items?

Yep, that would have solved the URL issue but the customer wasn’t keen on the * items.

Is writing renderings to pull items from a multilist really that hard?

Well no, not for you and I but the customer was looking to do a lot of development in house, been able to simply render all child items would make their life a lot easier.

Isn’t this just Item Proxying?

No, come on guys, read the post, install the module!

What about stability/performance/daisy-chaining/other?

All good concerns and really this is why I made sure it only runs on the master database and gets turned into real items on publish. Daisy-chaining should only be possible if you explicitly set it up that way in the include file, in that case best of luck to you. Stability and performance were fine during development (isn’t it always?), it’s got two layers of caching, item and entity which should in theory cover you but it’s still needing some stress testing before it goes on Shared Source. Any volunteers?

Last week someone asked me to email them a list of tips for improving code quality and I thought it would make a nice blog post; I picked just three areas and only made a few bullet points for each one:

Automated code quality

  • Resharper + StyleCop Plugin – This is a fantastic product that will both spot common programming mistakes and suggest improvements. With the stylecop plugin it will enforce the Microsoft formatting standard ensuring code consistency and readability.
  • FxCop – Scans your compiled dlls for known issues recorded by Microsoft, it’s a bit noisy but some of the potential problems it spots can be incredibly useful.
  • GhostDoc –Auto-generates and scaffolds out your comments based on the code naming, so a method called GetCustomerRecords will create a comment that simply says “Gets the customer records”. Still requires you to fill in the comments but does the initial legwork.

Training

  • MCPD training – Sadly rife with cheating due to the answers been freely available online the MCPD certification are still a really fantastic certification, not so much for the depth of information but rather the breadth.
  • Transcender – The intention of Transcender is to help people prepare for exams but I would recommend using it for people who have already passed. It will often show up gaps in their training and areas they need to work on.
  • Blogs – I would recommend that every developer has a rss reader which they check every morning, my personal favourite is google reader. Below are some of the blogs I’d recommend:
  • Books – A great idea is to setup a company library and regularly stock it with new books on topics like Linq, MVC and C#/SQL/HTML reference material etc. The one book I would recommend as a “must buy” is Code Complete (2nd edition) by Steve McConnell, I couldn’t recommend it enough.
  • Knowledge sharing – Naturally over time developers tend to become the expert, or go-to person for a particular topic, MVC, SQL or maybe an internal system. It’s great to have someone with a deep understanding of a topic but all too often this results in everyone else having zero understanding of it. Regular knowledge sharing sessions where that expert gives a 15 minute presentation on the topic helps everyone fill in the gaps and prevents disaster occurring if that expert leaves or is unavailable.
  • Code review – Formal code reviews can be quite time consuming and by extension expensive, in situations where this isn’t possible you can still encourage quick peer review of code. Before checking in the final version of their code each developer should ask a co-worker to look over their work and see if they can spot any areas for improvement. Quite often glaring mistakes can be spotted that are otherwise invisible to the person who wrote them.

Testing

  • JMeter – Stress testing during development is a must to ensure that performance issues don’t creep into a project only to be found after launch. It will also help you estimate infrastructure requirements and meet any agreed upon response times.
  • Continuous Integration – CI is a broad topic but I’ll steal the definition from Wikipedia: “CI implements continuous processes of applying quality control – small pieces of effort, applied frequently. Continuous integration aims to improve the quality of software, and to reduce the time taken to deliver it, by replacing the traditional practice of applying quality control after completing all development.”
  • Watin – Automated testing is typically restricted to just integration or unit testing of code. Watin allows you to write tests in C# that check the webpage itself, at the minimum I would recommend a recursive Watin test that checks the entire site for 500 errors and XSLT rendering warnings.
  • Nunit – Since Sitecore is so tightly coupled to the HTTP context it’s difficult to write true unit tests but integration tests can be just as useful. Coupled with Watin running on a dedicated build server you can see real leaps in code quality and a massive reduction in unseen problems been deployed to production servers.

The topic itself is massive and many books have been written on it (as I mentioned my favorite been Code Complete by Steve McConnell), make sure you post your favorites that I missed in the comments ;)

Long time and no post but I’m hoping to get back into the swing of things.

Decided to start off with something straightforward but hopefully useful, it’s a workflow action that will triage items that fail validation into another state. This would help content editors who lack technical skills and would otherwise have to fix XHTML validation errors themselves.

I’ve included both the code below and a prefab package, should be as simple as installing, adding the action to your workflow command and pointing it to the awaiting validation state, give me a shout if you have any trouble with it.

using System.Threading;
using Sitecore;
using Sitecore.Data.Items;
using Sitecore.Data.Validators;
using Sitecore.Diagnostics;
using Sitecore.Web.UI.Sheer;
using Sitecore.Workflows.Simple;
namespace WorkflowActionLibrary
{
    public class TriageAction
    {
        public void Process(WorkflowPipelineArgs args)
        {
            var workflowItem = args.DataItem;
            var validators = ValidatorManager.BuildValidators(ValidatorsMode.Workflow, workflowItem);
            var options = new ValidatorOptions(true);
            ValidatorManager.Validate(validators, options);
            ValidatorResult validatorResult = Validate(validators, args);
            if (validatorResult != ValidatorResult.Valid)
            {
                Item processorItem = args.ProcessorItem.InnerItem;
                string triageState = processorItem.Fields["TriageState"].Value;
                if(!string.IsNullOrEmpty(triageState))
                {
                    workflowItem.Editing.BeginEdit();
                    workflowItem.Fields[FieldIDs.WorkflowState].Value = triageState;
                    workflowItem.Editing.EndEdit();
                    args.AbortPipeline();
                }
            }
        }
        private static ValidatorResult Validate(ValidatorCollection validators, WorkflowPipelineArgs args)
        {
            Assert.ArgumentNotNull(validators, "validators");
            Assert.ArgumentNotNull(args, "args");
            ProcessorItem processorItem = args.ProcessorItem;
            if (processorItem == null)
            {
                return ValidatorResult.Valid;
            }
            const int @timout = 0x2710;
            const int timoutIncrement = 500;
            int counter = 0;
            while (true)
            {
                ValidatorResult validatorResult = ValidatorResult.Valid;
                foreach (BaseValidator validator in validators)
                {
                    if (validator.IsEvaluating)
                    {
                        validatorResult = ValidatorResult.Unknown;
                        break;
                    }
                    if (validator.Result > validatorResult)
                    {
                        validatorResult = validator.Result;
                    }
                }
                if (validatorResult != ValidatorResult.Unknown)
                {
                    return validatorResult;
                }
                counter++;
                if ((counter * timoutIncrement) > timout)
                {
                    SheerResponse.Alert("Timeout on item validation during Triage Workflow action.");
                    args.AbortPipeline();
                    return ValidatorResult.Unknown;
                }
                Thread.Sleep(timoutIncrement);
                ValidatorManager.UpdateValidators(validators);
            }
        }
    }
}

Fields that inherit the value of their parent items is something I’ve heard asked for before in the past but I’ve always just recommended coding it into the presentation. As an alternative however I’ve created a custom renderField pipeline step that handles it for you.

By including “InheritParent” in the name of your field it will look for values in parent items when none exists in the current item. Installing it is just a matter of including the code in your project and referencing it in the <renderField> just after GetFieldValue:

<renderField>
  <processor type=”Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel” />
  <processor type=”Namespace.FieldValueInherit, Assembly” />

using System;

using Sitecore.Data.Fields;

using Sitecore.Data.Items;

using Sitecore.Pipelines.RenderField;

namespace Namespace

{

/// <summary>

/// Sitecore renderField pipeline for inheriting parent field values recursively.

/// </summary>

public class FieldValueInherit

{

/// <summary>

/// Processes the field value inheritance pipeline.

/// </summary>

/// <param name="args">The pipeline arguments.</param>

public void Process(RenderFieldArgs args)

{

//Dont run while in page edit mode.

if (Sitecore.Context.PageMode.IsPageEditor ||

Sitecore.Context.PageMode.IsPageEditorClassic ||

Sitecore.Context.PageMode.IsPageEditorDesigning ||

Sitecore.Context.PageMode.IsPageEditorEditing ||

Sitecore.Context.PageMode.IsPageEditorNavigating)

{

return;

}

//Check field exists.

Field field = args.GetField();

if (field == null)

{

return;

}

//Check field is tagged to inherit parent values.

if (!field.Name.Contains("InheritParent"))

{

return;

}

//If field contains standard values then check parent items for fields that have been set.

if (field.ContainsStandardValue || !field.HasValue)

{

Item item = args.Item;

if (item == null)

{

return;

}

Item[] ancestors = item.Axes.GetAncestors();

Array.Reverse(ancestors);

foreach (Item ancestor in ancestors)

{

if (ancestor.Fields[field.ID] != null && ancestor.Fields[field.ID].HasValue)

{

args.Result.FirstPart = ancestor.Fields[field.ID].Value;

return;

}

}

}

}

}

}

Had a real head scratcher of a problem with Sitecore running in integrated mode. The site in question is rather odd in that everything including the home node is secured; any anonymous visitor is redirected to the login page. They also need various URL tricks to be done which necessitated integrated mode. Putting all that together was straight forward, just a matter of denying extranet/Anonymous access to the root home node and specifying a login page followed by implementing the integrated mode fix as described here.

Oddly though the moment I viewed the site while logged out it stopped sending me to the login page and instead threw up a “Layout not Found” page. Odder still the item it said it was trying to display wasn’t the home item or even the login item but instead was the root /sitecore item. I knew something strange was happening with the ItemResolver in the httpBeginRequest pipeline so I added a custom processor and debugged it to have a look at the HttpRequestArgs.

Here is what I saw when I switched back to classic mode:

{Sitecore.Pipelines.HttpRequest.HttpRequestArgs}
    base {Sitecore.Pipelines.PipelineArgs}: {Sitecore.Pipelines.HttpRequest.HttpRequestArgs}
    Context: {System.Web.HttpContext}
    LocalPath: “/default”
    PermissionDenied: true
    RequestType: Begin
    StartPath: “/sitecore/content/home”
    Url: {Sitecore.Web.RequestUrl}

As you can see it has attempted to retrieve the home item and been denied permission. It also attempts to retrieve the /default item but this also fails as it doesn’t exist. By the end of the request the context item is still null and permission has been denied so sitecore redirects to the login page.

On the other hand here is what happens when it’s in integrated mode:

{Sitecore.Pipelines.HttpRequest.HttpRequestArgs}
    base {Sitecore.Pipelines.PipelineArgs}: {Sitecore.Pipelines.HttpRequest.HttpRequestArgs}
    Context: {System.Web.HttpContext}
    LocalPath: “/”
    PermissionDenied: true
    RequestType: Begin
    StartPath: “/sitecore/content/home”
    Url: {Sitecore.Web.RequestUrl}

In this case the ItemResolver has been denied access to the home item but then went on to retrieve the / root item and set this as the context (which of course has no layout). The difference is down to the fact that IIS is now no longer telling ASP.Net to look for a /default file in integrated mode. So the context is now set and Sitecore attempts to render it as per normal except the context item in question is the /sitecore item.

Thankfully the solution is simple; if I deny access to /sitecore and /sitecore/content then the problem is resolved. In this case the ItemResolver finishes with permission denied and a null context which means the visitor is redirected to the login page once again.

I could have skipped this whole process however if I’d not fallen for that old trap of confusing what is true for one thing been true for another. On a classic asp.net website only files beneath the site root can be accessed as webpages and although similar in Sitecore it is by no means the same thing. In Sitecore *any* item can become the context item if access is allowed, I guess I can write this off as a reminder :)

Workmate of mine Adam Rambridge sent around an excellent survey on monday asking what best practices we recommend for sitecore projects. Instead of writing up a blog post this week I’ve taken the easy route and just copy/pasted the results ;)

Question Answer
Your name Steve Green

Information architecture

How best to structure templates? Typically I would break the templates down into 3 folders, field sections, page types and meta data.Field sections are reusable collections of fields such as title/text, meta tags, navigation that are inherited by page types.Page type templates are for items that are under the home node, ideally they are the only templates to have presentation values.Meta data templates are for items outside the web context which are typically stored in the global folder. These cover things such as reusable rich text blocks, control labels and configuration, dropdown menu sources and other content that doesn’t ‘belong’ to the content items.
How should the content structure be organised? I’d recommend prefacing your template names with a short signifier, so ABC_ or Comp_, this is so the client can later develop other websites and easily distinguish between the templates meant for one over the other.All content under the home item should represent a page and have valid presentation. All other content should be stored within the global folder which is a sibling item to the root home node.
Is this good practice that we should use on all projects? 90% of the best practices we typically use can be applied as-is without modification. I would prefer to see at least some attempt made to consistency.
Are there disadvantages to this scheme? None, you should only be doing it if it makes sense, if it doesn’t then you’re not doing anyone any favours.
Are there better ways? Indubitably, I hope to find them out ;)
How should you decide when to store items in a global folder rather than under the home node? Only content that “belongs” to the item should be present. The approach to organising sitecore content should be functionally similar to database normalization. It should be in global folders if the content in question isn’t “owned” by the context item, this covers both things like sidemenu RTE blocks, control labels or if there is a many-to-one relationship of some sort.
Text that goes with a control or sublayout We did try name/value pairs for a while but frankly these suck. I’ve now switched to a set of custom configuration templates, one per rendering or sublayout. They have 2 sections, one for labels and one for configuration. The configuration node is set at the top of the renderings as a variable and as a private property on the sublayouts. I’ve been planning on automating this at some point however.Something which I don’t do but it worth considering is using the parameters templates which were introduced in 6.1. I’m not sure how usable this is for the content editors however, letting them go into the presentation interface is dangerous at the best of times.

Naming

Naming fields and field sections Field names should be programmatically sound with friendly names added later.
Naming templates, layouts, renderings etc. ProjectAcronym_TemplateName typically. Folders used as much as possible (note, not supported in workflows).
Name prefixes See above.
What other advice would you give on naming items? Clear, concise and SEO friendly. In the case of sublayouts and renderings make sure the item name matches the file name.

Project structure

What is the ideal structure for a Sitecore project? Start with the standard 4, Website, Business, Data and Tests. You’ll almost always end up creating them so why not do it from the start. Otherwise you tend to bloat up the website project with helper classes only to have to refactor later.
What are the worst mistakes that should be avoided? Omnidirectional project references, untilize dependency injection where possible.

Sitecore ORMs

What do you think about Sitecore ORMs? Tears, wailing, gnashing of teeth. Contentious issue but personally I think the issues it’s trying to solve are not as big as the problems it causes.
What problems does it solve? Very very good question. It’s can be cool that’s for sure. Templates as object, intelisense on your fields, that’s lovely. Then you run into the hell of lazy loading, caching and often a gradual and inexplicable delta between the database and the in memory objects.
Does it cause any problems of its own? See above.
Would you use shared source Domain Objects instead? Why? Never tried it to be honest.

Sublayouts and renderings

How do you decide whether to use one over the other? It’s not very scientific but I use the rule of thumb that if it’s not easy it’s time to switch to a sublayout. XSLT should make your life easier, not harder.
Are there dangers of too much reliance on XSLT? There can be issues with refactoring, due to its reliance on referencing items by paths and fields by names. I’ve got some grand ideas to help resolve that however via xslt helpers.
Are there dangers of too much reliance on sublayouts? Sitecore is designed with xslt in mind, if you use sublayouts where a simple xslt rendering could have done you’ve missed a trick.
Is one easier to maintain that the other? Loaded question. Ask someone who needs to rename every reference to an item by path and you’ll get one answer. Ask somone who needs to pull out a faulty ORM and you’ll get another. I think like most things you need a healthy balance really.

Testing

Can Sitecore projects benefit from unit testing? Strictly speaking no, Sitecore itself is impossible to properly unit test. Integration and stress testing however is vital.
WatiN? A recursive Watin test for the whole site to check for standard errors (missing presentation, failed xslt etc) should be standard on all sitecore sites.
What holds us back from doing more testing? Time, and occasional false perception of there not been enough time.

What else?

What factors cause sitecore projects to go well? When the site is been developed as a sitecore site, see next question for more.
What factors cause sitecore projects to go badly? When a site is been developed as something else. Sitecore projects typically fail when someone is trying to code something else into the system. Sitecore can be an application framework, but you’d be better off with MVC. Sitecore can be made to act like any other CMS or legacy system, but you’d be better off not doing it that way. Sitecore always *CAN*, but you probably shouldn’t.
What other questions should this survey have asked? I’m sure we can think up enough for a sequal at some point. This survey though was exhaustive and excellent, cheers ;)

 

 

Love to see what other peoples answers would be, if you do end up posting your answers online make sure you post a link to in the comments :)

layoutnotfound

Layout not found, never a good look. Despite all efforts to not link to items lacking presentation the only sure-fire way to prevent this is to simply not have any; everything under the home node should have *some* kind of presentation applied. In every case where someone has said “don’t worry, there is no way they could reach that item” they always have linked to it or found that users actively change the urls to it (happens more than you’d expect).

The biggest offender for zero presentation is the common garden variety /sitecore/templates/Common/Folder. It’s not uncommon to see deeply nested sets of folders in order to create more content rich urls, it is after all part of the SEO holy trinity of url, title and header. My replacement for this is what I call the bump folder, not the best of names but it has stuck. It’s straightforward to implement and dead easy for content editors to use, the bump folder simply 301 redirects the user to either the parent item or the item selected in a droplink.

First step is to create a new template in your solution and add the following field:

bumpfoldertemplate

This is a single droplink field called Target and I’ve ticked shared as it’s language invariant (or at least likely to be, just untick if it’s going to change based on language). The interesting bit to note here is the source, you can not only supply paths but also sitecore queries. In this case the query used is “query:./*[@@tid!=../@@tid]” which means “Select all child items which are not bump folders”. The reason I avoid linking up to bump folders is to avoid 301 daisy chaining or even worse 301 loops (where the folder linked to has no target set and 301 redirects to the parent item). I’m also using a drop list instead of a general link so as to avoid the folders turning into aliases and creating the website equivalent of spaghetti code.

The only thing to add now is a layout item (and aspx file) and assign it to the presentation for the bump folder. In the codebehind for the layout add the following:


protected void Page_PreInit(object sender, EventArgs e) { 
  LookupField target = Sitecore.Context.Item.Fields["target"]; 
  if(target.TargetItem != null
    Response.Redirect(target.TargetItem.GetFriendlyUrl()); 
  Response.Redirect(Sitecore.Context.Item.Parent.GetFriendlyUrl());
}

Done, I know it’s not exactly ground breaking stuff but it’s little things like this that can really make a big difference to a Sitecore project.

Update: 27th September 2009

Doh, forgot to add that I’m using a set of extension methods alongside my solution, GetFriendlyUrl() in this case is actually an extension method.

public static string GetFriendlyUrl(this Item item)
{
    return LinkManager.GetItemUrl(item);
}

Also as pointed out by Thomas Eldblom these bump folders shouldn’t preclude the development of “fit for purpose” container items. They’re simply for content editors to organise their content into more useful hierarchies. Thomas also has some good pointers on how to manage your errors in general, see the comments for more details.

Adding little “traffic light” labels to the top of your renderings and sub-layouts can really help both the customer and other developers see how the site is progressing. Just a small span at the top of the file containing its name and a css class for its status will do the trick:

<span class="devlabel red">homepage_flashbanner.ascx</span>

The problem you run into is that the style tags often interfere with the layout of the page or just don’t show up correctly at all:

before

It can be worse than this, often you’ll find that simply adding these spans will throw the whole page into a shambles.

The solution is to turn to the as always awesome jQuery. Start by adding the following script to the bottom of your main layout file:

<script type="text/javascript">
jQuery(document).ready(function() {
   jQuery(".devlabel").each(function(n) {
      var label = jQuery(this);
      var target = label.next();
      var pos = target.offset();
      var left = pos.left + "px";
      var top = -12 + pos.top + "px";
      label.css({
         zIndex: 5000,
         left: left,
         top: top
      });
   });
 });
</script>

Make sure the CSS class for the label is set to absolute positioning as so:

.devlabel
{
	font-size:8px;
	position:absolute;
}
.red
{
	color:red;
}
.orange
{
	color:orange;
}
.green
{
	color:green;
}

What that jQuery will do is search for any labels with the ‘devlabel’ class and position them directly above the very next element. It should end up looking more like this:

after

Then of course as your project progresses you can change the color of the traffic lights, red for not started, orange for in progress and green for finished (and tested!). Quite satisfying to watch them slowly turn green one by one :)

progress

I’ve been adding these ‘traffic lights’ to my projects for quite a while now, the only issue really is having to remove them at the end of the project (for SEO purposes they’re a big no no). This has given me inspiration for possibly writing a pipeline handler to automate the process, instead of using the traffic light colors it could instead output the name and Sitecore UI icons of the various renderings and sub-layouts. Once I have the details sorted I’ll be sure to post an update.

Next Page »

Follow

Get every new post delivered to your Inbox.