Dusty Eves

dusty.eves@techno-babble.net

Sitecore Architect with Paragon Consulting

Avoiding Solution Entropy With Sitecore MVC

Introduction

The introduction of Sitecore MVC has brought a proven successful design pattern into the Sitecore ecosystem.  In a lot of ways this seemed a very natural addition to Sitecore as it was already a Model View Presenter paradigm.  As such lot of MVC developers new to Sitecore end up re-inventing a number of wheels that are already available in the Sitecore stack.  So how do we do Sitecore MVC without re-inventing those particular wheels?  There’s a handful of pitfalls to avoid to make the most of both the Sitecore stack and the added power of MVC.

View Renderings vs. Controller Renderings

One of the most common mistakes I see in Sitecore MVC is wanting to setup the solution as a pure MVC solution and treat Sitecore and ancillary or incidental.  This manifests by setting up a controller and view for each and every presentation component in the solution and defining every Sitecore rendering as a controller rendering.  This creates a lot of unnecessary entropy in the solution because for that vast majority of renderings in a typical Sitecore solution the only thing the controller needs to do is pass either the context item or the data source item off to the view.  A view rendering intrinsically uses the default Sitecore controller which already does exactly that.

So what’s the proper balance between view renderings and controller renderings?  The best rule of thumb that I found is that if you can get view rendering without putting more than a line or two of code block in the view it’s best to go with a view rendering.  If you have a rendering that needs data that comes from a source other than the content tree or has complex logic and processing around the data you’re likely best off with a controller rendering.

Over-Compositing Models

Another common mistake that I see in MVC is redundant code artifacts around the models.  Below is an example of a pattern I’ve seen in MVC solutions:

namespace TechnoBabble.Core.Models
{
	[SitecoreType(TemplateId=ArticleConstants.TemplateIdString )] 
	public partial class Article
	{
		[SitecoreField]
		public string Title { get; set; }

		[SitecoreField]
		public string ArticleText { get; set; }

		[SitecoreField]
		public Author ArticleAuthor { get; set; }
	}
}
namespace TechnoBabble.Core.ViewModels
{
	public partial class ArticleViewModel : TechnoBabble.Core.Models.Article
	{ }
}
@inherits Glass.Mapper.Sc.Web.Mvc.GlassView<TechnoBabble.Core.ViewModels.ArticleViewModel>

<h2>@Editable(m => m.Title)</h2>
<div>@Editable(m => m.ArticleText</div>

In the example above the ArticleViewModel class add nothing to the solution other than the word “model”.  While this is arguably a break from the conventional wisdom of the MVC pattern, the better way to approach this scenario is to have the view inherit from GlassView<Article> and not create the ArticleViewModel at all.

So what are the use cases in which a ViewModel is advisable?  The short answer is if there’s utility to extending the model a View model is the proper place to do so.  Below is an example where the ViewModel adds value.

namespace TechnoBabble.Core.ViewModels
{
	public partial class ArticleViewModel : TechnoBabble.Core.Models.Article
	{ 
		public bool HasProfilePage
		{
			get { return this.ArticleAuthor.ProfilePage != null; }
		}
	}
}
@inherits Glass.Mapper.Sc.Web.Mvc.GlassView<TechnoBabble.Core.ViewModels.ArticleViewModel>

<h2>@Editable(m => m.Title)</h2>
<div>
	@Editable(m => m.ArticleText
	@if(Model.AuthorHasProfilePage)
	{
		@RenderingLink(Model.ArticleAuthor, m => ProfilePage.Url)
	}
</div>

Granular Controllers

Another common issue that I see in Sitecore MVC solutions to create a distinct controller for each rendering in a solution.  While this again clashes with conventional MVC wisdom int Sitecore controllers are best grouped by functionality.  Below is an example of how I see controllers typically broken down.

namespace TechnoBabble.Website.Controllers
{
	private string _view = "/Views/SearchHeader.cshtml";
	public partial class SearchHeaderController
	{
		public ActionResult Index()
		{
			return View(_view);
		}
	}
}
namespace TechnoBabble.Website.Controllers
{
	private string _view = "/Views/SearchResults.cshtml";
	public partial class SearchResultsController
	{
		public ActionResult GetSearchResults(_searchTerm)
		{
			if (string.IsNullOrEmpty(_searchTerm))
				return View(_viewResults);
			var _results = SearchManager.GetResults(_searchTerm);
			return View(_viewResults, results);
		}
	}
}

A better way to organize would be like so:

namespace TechnoBabble.Website.Controllers
{
	public partial class SearchController
	{
		private string _viewHeader = "/Views/SearchHeader.cshtml";
		private string _viewResults = "/Views/SearchResults.cshtml";

		public ActionResult GetHeader()
		{
			return View(_viewHeader);
		}

		public ActionResult GetSearchResults(_searchTerm)
		{
			if (string.IsNullOrEmpty(_searchTerm))
				return View(_viewResults);
			var _results = SearchManager.GetResults(_searchTerm);
			return View(_viewResults, results);
		}
	}
}

Setting up the controller you can create two separate renderings both with the controller defined as “Search” and the methods defined as “GetHeader” and “GetSearchResults” respectively.

Conclusion

So these are my thoughts of Sitecore MVC done right.  Some of these suggestions run contrary to conventional MVC wisdom but purely conventional MVC wisdom in Sitecore can create a lot of unnecessary entropy.  This, on the other hand, strikes the balance between the MVC pattern and what we have by virtue of the Sitecore platform.

Like what you see? Something I missed? Have an even cooler way to do the same thing?!?! Let me know in the comments below.

Leave a Reply

Your email address will not be published. Required fields are marked *