Virtual Items in Sitecore

6

July 1, 2011 by Alistair Deneys

One of the many benefits of using a good CMS like Sitecore is the ability to reuse a single piece of content in multiple locations around your site. This ability is provided through virtual items.

So what is a virtual item? A virtual item is an item that doesn’t actually exist. Why wouldn’t you want the item to exist? One reason would be to keep your content tree clean and another would be to reduce the workload on your content authors. Often virtual items are used to provide a single source of content that can be reused throughout multiple points in your site.

In this post I’m going to visit a few options available inside Sitecore for using virtual items and some related options for achieving those goals mentioned above.

Clone Items

Clone items were introduced in Sitecore 6.4. A cloned item uses another item (source item) in the same way template standard values are used. If a cloned item’s field value is null Sitecore will get the value of that field from the clone source. This allows fields of a cloned item to be overridden without affecting the source item.

This option is good when you want a physical item to be shown in the content tree or when you need to allow content authors to create the cloned items themselves. It’s also a good option for when you want to share most of the fields of the source item, but allow overriding of others when the shared item is used, such as whether it would appear in the breadcrumb (if that was controlled through a field value).

Standard values also works with clones, so if a clone source doesn’t have a field value that field value will be read from standard values right through to the clone item itself. If the value is then overridden on the clone source, that overridden values will be read by the cloned item. The clone is an additional layer in the standard values stack.

Cloned items work just like any other item, cause they are actually a real item. So in that respect they’re not actually virtual. But they can help achieve that goal of having a single source for content and reusing that content throughout the website. Because clone items are real items they will have a different ID to the clone source item.

But if I want a single source of content, allowing users to override values on the cloned item itself goes against that. How can I stop content authors from overriding values on cloned items? Simple! The same way you would stop them from editing any piece of content, by using Sitecore security.

Proxy Items

If you’re using Sitecore 6.4 or lower then proxy items are what you would use instead of clone items. Proxy items were deprecated in Sitecore 6.5, so if you’re starting a new project you shouldn’t be using them. Although still present in Sitecore 6.5, being that they are deprecated Sitecore may remove this feature entirely in a future release.

Proxy items proxy an item (or subtree) from one part of the content tree to another. Updates to a proxy item will update the source item. This means you can’t override a source item value. Other than that, proxy items work in much the same way as clones do.

Unlike clone items which require a physical item in the content tree, proxy items don’t require a physical target item, so they are actually virtual.

Wildcard Items

A wildcard item is an item named with an asterisk (*). It will handle any item requests at a single level in the content tree if another item at the same level isn’t found.

So if I have a content tree as follows:

/sitecore/content/home/a 
/sitecore/content/home/c 
/sitecore/content/home/*

If I make a request for /sitecore/content/home/b the wildcard item will handle that request. But if I make a request for /sitecore/content/home/a, the a item will handle that.

Wildcard items only work for a single level. In the above example, if I make a request for /sitecore/content/home/b/b I’ll get an item not found error. To handle that case I would need a wildcard item under the wildcard item. So I need a wildcard item for every level I want to be able to handle all requests for.

Wildcard items are also real items, but they allow the requesting of virtual items at a single level of the content tree. Being real items they must exist in the content tree. Some people might think this makes the content tree look messy, particularly if you have a lot of wildcard items.

One way to hide the wildcard items from normal content authors is to make the wildcard item hidden. In the content editor navigate to your wildcard item, select it then in the configure tab click the hide item option in the attributes section. Now the item will only display in the content tree if the user has ticked the hidden items option on the view tab in the content editor.

If you need to have a lot of wildcard items in predictable locations or if you really don’t want them shown in the content tree you may need to consider the next option instead.

Request Pipeline Processor

A fairly straight forward way of handling virtual items at any level without messing up your content tree is to create your own httpRequestBegin processor and insert it into the pipeline. I like to do this after the existing ItemResolver, so in my custom processor I can check to see if the context item is null, and only process the request with my processor if it is. Every httpRequestBegin pipeline processor will run on every request, so you need to ensure processors in this pipeline are as efficient as possible. The simple check for a null context item is very efficient.

With a custom pipeline processor much more complex logic for virtual items can be implemented including checking only for specific item names or allowing any level of virtual item to be requested.

A real world example of this kind of option out in the wild is in the Sitecore eCommerce Fundamental Edition module (SEFE). It uses a custom item resolver after the default Sitecore item resolver to service requests for product which don’t live at the requested location, but exist in another part of the content tree.

I recently used this approach myself in a design. The client wanted an item to appear as a child of another item, but didn’t want that child item to actually be an item in the content tree. All the data required to render the virtual child item was pulled from it’s parent. There were several reasons for this design. Firstly, the client had strict rules around the naming of this item; it must always be called by a specific name. Secondly the virtual child item must always sort in a specific manner; at the bottom of the list of real child pages. Both of those could be achieved through other mechanisms. The biggest factor was the fact that the client didn’t want the virtual item to be edited in a different location to the rest of the data on the parent. They wanted the data for the virtual child item defined on the same item as the parent.

Unlike the above options, this option requires some coding. To implement your own processor, create a class which inherits from HttpRequestProcessor and override the Process method. In your method populate the Sitecore context item to whatever it should be based on the incoming request.

This option is good when you have predictable logic or when you don’t want to show the virtual items in the content tree.

Custom Data Provider

If none of the above options satisfy your exact needs you could always implement your own custom data provider to provide the virtual items. The biggest advantage of this approach is that your virtual items will appear in the content tree.

Defining the virtual items will be up to whatever logic you implement in the data provider. You could automatically return the virtual items based on business rules or you could infer the virtual items from data the content authors input on real items.

One such example of this is the Item Mirror Data Provider written by Steve Green. It shows how you can allow selecting items in one part of the content tree to have virtual representations of those items appear in other parts.

This is the most comprehensive approach to virtual items and the most difficult. Implementing a data provider is no mean feat and should not be undertaken lightly.

Conclusion

So there you have a few different options when designing how your virtual items should work. The biggest considerations will be whether you want content authors to define the virtual items (whether directly or indirectly), whether you want them to appear in the content tree and whether you want to use an out-of-the-box solution or write some code to achieve what you want.

Advertisements

6 thoughts on “Virtual Items in Sitecore

  1. Kurt Bilde says:

    DON’T use proxies at all if you are planing to have more than 200 of them….

  2. Christopher Giddings says:

    Hey Ali,

    Thanks for the good write up, now i don’t have to explain it to people over and over again :).
    One thing if you are using wildcards and use caching you have to make sure to not cache the actual wildcard item but the data based on the URL as you may have incorrect data.

    You will have to modify the caching to allow this, you can look at the following post on the SDN and John wests blog (raised by myself for SSL based caching);
    http://sdn.sitecore.net/SDN5/Forum/ShowPost.aspx?PostID=35652
    http://www.sitecore.net/Community/Technical-Blogs/John-West-Sitecore-Blog/Posts/2011/05/Custom-Caching-Criteria-with-the-Sitecore-ASPNET-CMS.aspx

    When you do this you want to make sure to extend the “GetCacheKey” method.
    What you have in the key is something like below;
    “/web/ui/webcontrols/linkctl00_frmLinkHome_#lang:EN_#data:/sitecore/content/COMPANY/Internet/Home/News/Categories/*_#protocol:http_#port:80”
    We want to replace the “*” with the correct item you can do this by using the following “Replace(Sitecore.Context.Item.Paths.Path, Sitecore.Context.Request.ItemPath)” but only if it contains a wildcard.

    As always I should write a blog post, but never seem to have the time 😦

    Hope this helps,
    Chris

  3. James Walford says:

    Worth noting that if you’re cloning across sites then all the links in the clone will still point back to the source site.

    • Alistair Deneys says:

      Good point James.
      Although the format of the item URI used for item clones contains a DB reference, the UI doesn’t support this capability. I’ve seen examples previously using proxy items to bring external data into the content tree, and item clones supersede clones, so it’s good that they also provide this capability.

  4. prathima says:

    Hi ,

    I had a requirement from the client where the search criteria for job search should be part of url as http://mywebsite.com/results/{keyword/{location}/{salary}

    i have created my own httpRequestBegin processor in which i check for the item path contains the item path and if yes assign the actual item to the context

    public class VirtualItemUrlResolver : HttpRequestProcessor
    {
    public override void Process(HttpRequestArgs args)
    {
    if (Context.Item != null) return;
    var url = args.Url.ItemPath.ToLower();

    if (url.Contains(“/sitecore/content/home/results”))
    Context.Item = args.GetItem(“/sitecore/content/Home/results”);
    }
    }

    and adding this pipeline after itemresolver.

    The above method works.It renders the item and still have all the parameters in the url so i can implement my logic to fetch results on the page.

    This gives the client to changes the layout add any widgets through sitecore rather than creating the virtual items

    My question is it the right way to do?

    Any Advice in this regard is much appreciated.

    Thanks & Regards
    Prathima

    • Alistair Deneys says:

      Hi Prathima,
      It sounds like your approach is a good solution to the problem. Your scenario is dealing with dynamic request parameters which are better handled by code rather than creating lots and lots of items. I think you nailed it when you mentioned “search criteria”. It’s functional, not content.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

The views expressed on this blog are solely my own and do not necessarily reflect the views of my employer.
%d bloggers like this: