Sitecore Item Controller - the hidden gem of Sitecore MVC
Posted 27 November 2016 by Marek Musielak
Not many people know about Sitecore Item Controller and what its role in Sitecore MVC is. SitecoreController is responsible for executing PageContext.Current.PageView
property, which runs mvc.getPageRendering
pipeline and returns html defined by the Sitecore MVC item layout. OK, so why is it important and how can I use it? One thing you can do is changing the way how Sitecore executes MVC page requests. Interesting but a little bit scary. I wouldn't trust that after upgrading to the next Sitecore version, my code still works. But there is another thing you can do. You can execute any code you want before or after Sitecore renders any MVC page. You can say that with httpRequestBegin
and httpRequestEnd
pipelines you can do the same. That's true, but with Sitecore Page Controller you can define different code for every template or even item. How? Read the post to see how I used Sitecore Item Controller and Sitecore Rules Engine to allow Sitecore Editors to use Rules Engine to specify different settings based on whatever condition they want.
When few years ago I switched from Sitecore WebForms project and started to work on my first Sitecore MVC project, I was missing the code behind which was executed for the layout of the page. I wanted to executed some code before any component was rendered or after they all were ready. Googling, searching and asking didn't help. No, you can use Controller Rendering components but that's all you can get. It felt a little bit dirty but when I needed to execute some code for every requested page, I was using either static component included in every cshtml layout or I was adding my own processor to the httpRequestBegin
pipeline. Yes, it did the trick, but still I felt it was not the right place to do what I needed.
Some time later I found SitecoreController field which is a part of the Standard template. A little bit of experimenting later I was able to execute my custom code before any other MVC component was called. It's only 4 steps you need to do:
- Create new class inheriting from
Sitecore.Mvc.Controllers.SitecoreController
class. - Override `Index()` method (don't forget to call
base.Index()
method). - Set the SitecoreController field on your base template to
My.Assembly.Namespace.CustomSitecoreController, My.Assembly
or whatever is your class. - Build, publish and try.
Simplest code can look like that:
public class CustomSitecoreController : SitecoreController { public override ActionResult Index() { Log.Info("Url called: " + HttpContext.Request.RawUrl, this); return base.Index(); } }
Nice, but we can do much more. I've create a structure like this:
I'm not going to dive into details what sets current request config to the [specific] item
action does. If you've read all the text above, I'm pretty sure you know how Sitecore Rules Engine works and how to create your own conditions and rules. But as you see, there are 2 rules specified: first one sets config to default for every item which is under the Home
node, and the second overrides the config with News Config for every item under the News
node, except from the items in the SpecialSection
item. And the controller code which does the magic looks like that:
public class CustomSitecoreController : SitecoreController { public override ActionResult Index() { if (!Disabled()) { var rulesRoot = Context.Database.GetItem("/sitecore/MySite/Settings/PageRules"); RuleList<RuleContext> rules = RuleFactory.GetRules<RuleContext>(rulesRoot, "Rules"); rules.Run(new RuleContext{Item = Context.Item}); } return base.Index(); } }
Those 5 lines of code are enough. Every time a Sitecore MVC item is requested, All the rules defined under /sitecore/MySite/Settings/PageRules
are executed. And in my scenario, proper configuration is applied when needed. And what is more, you can switch back to the default SitecoreController or create another custom one for any page you want if needed.
Thank you for reading. I hope you enjoyed. If you liked this post, I would appreciate if you hearing your thoughts on this. And if you think it's crap and there are better ways to do what I described, I would appreciate your feedback even more.