The Maze
If you have worked with Sitecore MVC you have probably noticed a few (to say the least) .Item properties in various contexts:
Model.Item(whereModelis aRenderingModel)Model.PageItemModel.Rendering.Item(orRenderingContext.Current.Rendering.Item)Model.Rendering.RenderingItemRenderingContext.Current.ContextItemPageContext.Current.Item@Html.Sitecore().CurrentItem
And of course a good old Context.Item is always available. A maze indeed.
Intrigued? Need a map? Ok, pack your lunch and let’s go look around. If you’re patient we will make it out by sunset.
Not the Item you need
Let’s start by marking the dead ends and wrong turns and by pointing out the two Items you most likely don’t need
1. Rendering.RenderingItem
Your rendering is represented by Sitecore.Mvc.Presentation.Rendering object. You can get to it via:
RenderingContext.Current.Renderingor via:
@Model.Renderingwhen in your razor view, provided that your model is an instance of the
RenderingModel. TheRenderingItemproperty points to the definition item of your component, the item under/sitecore/layout/Renderings. It’s probably not the item you need.2. Context.Item
A good old friend… It’s hard, I know, but it’s time to move on. Depending on where you are in the Sitecore MVC land it may or may not be the item you need. It’s probably worth a blog post of its own but I would recommend you just don’t use
Context.Itemin your Sitecore MVC journey.The two items you need
You most likely need one of the two items – the current page item, and the current component’s data source item. Or let’s better call it the current component’s context item as your rendering might not be datasource-driven, for example.
1. Current Page Item
In context of a rendering (view and controller rendering alike), a page item is the item that’s being rendered. The one that carries your rendering in its layout definition.
var page = PageContext.Current.Item;And it is normally determined by running the
mvc.getPageItempipeline. We’re in a maze though, remember? It’s probably that item. It’s most likely that item. It can, however, be explicitly set on the currentPageContext. And the latter could also be changed by pushing a new context object onto a stack usingContextService.Get().Push(). That said, if no code in your solution is trying to outsmart Sitecore you can be pretty sure it’s the current page item.In context of a routed request it’s the request’s context item. You can read more about it here. It’s the same idea actually –
mvc.getPageItempipeline. The processors in it will take turns to try and figure out what should be the page item and the guys there know about route values and{*scItemPath}.[su_note note_color=”#fafafa”]If you’re in context of a view rendering and your model is a (or a descendant of)
RenderingModel(and why wouldn’t it be?) you can just use:@Model.PageItemto explicitly refer to the current page. We’ll see how you can, in some circumstances, get the same item implicitly via
Model.Itembut I am a big proponent of stating your intention as clear as possible when writing your code. I always favorSingleOrDefault()andSingle()overFirstOrDefault()orFirst(), for example, unless, of course, your intent is, in fact, to pick the first out of potentially many.
[/su_note]2. Current Context Item
In context of a routed request there’s only one context item and we just talked about it. This particular one only makes sense in context of a rendering.
Let’s start with an example. In your razor view:
@Html.Sitecore().Field("Title")will render a
Titlefield of what item exactly?Is it the field of:
@Html.Sitecore().CurrentItemor
@Model.Itemor
@Model.Rendering.Itemor
RenderingContext.Current.Rendering.Item?
The answer is “Yes“.
The last three are all the same. The
CurrentItemon the helper will almost always be equal to them as well. There’s one specific case when it won’t be and I will explain in a minute. TheItemproperty of theRenderingobject does the following:public virtual Item Item { get { return this.StaticItem ?? this.GetItemFromContext(); } set { this.StaticItem = value; } }which roughly (please read the code for the exact transcript) translates to the following sequence:
- Try to get the item from the rendering’s
ItemIdproperty. Return it if notnull. I never used and I am not really sure what it is to be honest- Try to get the item from the rendering’s Data Source. Return it if not
null- Try to get the
ContextItemfrom the currentRenderingContextif datasource nesting is allowed. This thing deserves special attention and I will give it its due in the next chapter. Don’t return just yet if notnull.- If the
ContextItemwasnull(or datasource nesting disabled) then grab the current page item from the currentPageContext. Don’t return it just yet if notnull.- If nothing found then return
null. Can’t see why you would have a rendering running outside of a page context (and thus without the current page item) but nothing is impossible with Sitecore- If we have either the
ContextItemor the page item and the rendering’s Data Source property is null or empty then return that item we have- Otherwise try to evaluate the Data Source relative to that item we have
Still with me? Ok then, moving on.
Remember I told you the
CurrentItemon the helper does it a little differently? It actually runs this exact sequence with one extra step at the very end. In case after all these attempts to get something back we got anull(and how could we? do you see why we would get anullafter all the hassle we just went through to get something?), so in case we have nothing at the end it will one more time reach out and grab the page item. I guess the helper hold itself to a slightly higher standard.[su_note note_color=”#fafafa”]It’s that last step in the long sequence that may produce a
null. If, for example, your rendering’s data source was an ID that was no longer in your Sitecore database or maybe it was there but it was not in the right database, it would returnnullon the second step and would later try to get it again relative to theContextItemor the page item. An ID is not a path so Sitecore would basically just do theGetItem()by that ID again. It’s silly, I know, but it’s what it does and that’s how you can end up with anull. I had it happen to me so that’s how I know[/su_note]The Hidden Gem Item
So what was that
ContextItemon theRenderingContext? Is it an implementation detail or can it come in handy?The
mvc.renderRenderingpipeline runsEnterRenderingContextprocessor right before executing the Renderer. This processor is tasked with pushing the newRenderingContextfor the rendering that is about to render onto the stack of theContextService. In case a rendering is nested within another rendering theContextItemwill be set to the outer rendering’sItem– the result of running the sequence we have just looked into in the previous chapter – it’s called datasource nesting. Otherwise it will be set to be the current page item.There’s a setting that controls whether datasource nesting is allowed –
Mvc.AllowDataSourceNesting. It defaults totruebut if you set it tofalsetheContextItemwill not be used to resolve the current context item.This hidden gem item can come in very handy. Next time (or maybe the time after next as I already have another blog post in the making) I will tell you how you can use it to your advantage. Stay tuned!

Thanks for taking the time to go into this in detail – as you point out, the context item situation was getting a bit confusing.
One question. Is there a way to set the context item somehow without using custom item resolvers?
If you want to set it temporarily you can always use the
using (new ContextItemSwitcher(myItem))
{
// Sitecre.Context.Item now points to myItem
}
Thanks for the detail explanation.
Pingback: Resolving Context.Item in Sitecore MVC | jammykam