Sitecore: using MVC areas

Sitecore out of the box will not provide MVC ares support but you will really need this functionality for good solution organization. However, Sitecore has good pipelines system and you could plug you code that will resolve areas.
You need to apply area detection only to controllers renderings, as Controllers will require areas information in order to resolve views for example.

namespace Examples.Common.Sc.Pipelines
{
    using System;
    using Sitecore.Data;
    using Sitecore.Mvc.Pipelines.Response.GetRenderer;
    using Sitecore.Mvc.Presentation;
 
    public class AreaController : GetRendererProcessor
    {
        public override void Process(GetRendererArgs args)
        {
            if (args.Result != null)
            {
                return;
            }
 
            var renderingTemplate = args.RenderingTemplate;
            if (renderingTemplate == null)
            {
                return;
            }
 
            if (!renderingTemplate.DescendsFromOrEquals(new ID("{2A3E91A0-7987-44B5-AB34-35C2D9DE83B9}")))
            {
                return;
            }
 
            args.Result = this.GetRenderer(args.Rendering, args);
        }
 
        protected virtual Renderer GetRenderer(Rendering rendering, GetRendererArgs args)
        {
            var action = rendering.RenderingItem.InnerItem.Fields["controller action"].GetValue(true);
            var controller = rendering.RenderingItem.InnerItem.Fields["controller"].GetValue(true);
            var area = rendering.RenderingItem.InnerItem.Fields["area"].GetValue(true);
            var namespaces = rendering.RenderingItem.InnerItem.Fields["namespaces"].GetValue(true);
 
            if (string.IsNullOrEmpty(namespaces))
            {
                namespaces = string.Empty;
            }
 
            return new AreaControllerRenderer
            {
                Action = action, 
                Controller = controller, 
                Area = area, 
                Namespaces = namespaces.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
            };
        }
    }
}
namespace Examples.Common.Sc.Pipelines
{
    using System;
    using System.IO;
    using Sitecore.Mvc.Presentation;
    using Sitecore.StringExtensions;
 
    public class AreaControllerRenderer : Renderer
    {
        public override string CacheKey
        {
            get
            {
                return "areacontroller::" + this.Controller + "#" + this.Action + "#" + this.Area;
            }
        }
 
        public string Action { get; set; }
 
        public string Area { get; set; }
 
        public string Controller { get; set; }
 
        public string[] Namespaces { get; set; }
 
        public override void Render(TextWriter writer)
        {
            var controllerRunner = new AreaControllerRunner(this.Controller, this.Action, this.Area, this.Namespaces);
 
            var value = controllerRunner.Execute();
            if (string.IsNullOrEmpty(value))
            {
                return;
            }
 
            writer.Write(value);
        }
 
        public override string ToString()
        {
            return "Controller: {0}. Action: {1}. Area {2}".FormatWith(new object[] { this.Controller, this.Action, this.Area });
        }
    }
}
namespace Examples.Common.Sc.Pipelines
{
    using System.Web.Mvc;
 
    using Sitecore.Mvc.Controllers;
    using Sitecore.Mvc.Presentation;
 
    public class AreaControllerRunner : ControllerRunner
    {
        public AreaControllerRunner(string controllerName, string actionName, string area, string[] namespaces)
            : base(controllerName, actionName)
        {
            this.Area = area;
            Namespaces = namespaces;
        }
 
        public string Area { get; set; }
 
        public string[] Namespaces { get; set; }
 
        public override string Execute()
        {
            var requestContext = PageContext.Current.RequestContext;
 
            if (this.Namespaces != null && this.Namespaces.Length > 0)
            {
                if (!requestContext.RouteData.DataTokens.ContainsKey("Namespaces"))
                {
                    requestContext.RouteData.DataTokens.Add("Namespaces", this.Namespaces);
                }
                else
                {
                    requestContext.RouteData.DataTokens["Namespaces"] = this.Namespaces;
                }
            }
 
            return base.Execute();
        }
 
        protected override void ExecuteController(Controller controller)
        {
            var requestContext = PageContext.Current.RequestContext;
            var value = requestContext.RouteData.Values["controller"];
            var value2 = requestContext.RouteData.Values["action"];
            var value3 = requestContext.RouteData.DataTokens["area"];
            try
            {
                requestContext.RouteData.Values["controller"] = this.ActualControllerName;
                requestContext.RouteData.Values["action"] = this.ActionName;
                requestContext.RouteData.DataTokens["area"] = this.Area;
                ((IController)controller).Execute(PageContext.Current.RequestContext);
            }
            finally
            {
                requestContext.RouteData.Values["controller"] = value;
                requestContext.RouteData.Values["action"] = value2;
                requestContext.RouteData.DataTokens["area"] = value3;
            }
        }
    }
}
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
 
      <mvc.getRenderer>
        <processor patch:before="processor[@type='Sitecore.Mvc.Pipelines.Response.GetRenderer.GetViewRenderer, Sitecore.Mvc']"
                   type="Examples.Common.Sc.Pipelines.AreaController, Examples.Common.Sc" />
      </mvc.getRenderer>
      
  </sitecore>
</configuration>

Besides the code above you need to make modifications to controller rendering and add fields Area and Namespace. Namespace be required when you add controllers with same names in different areas, as MVC will not be able to choose right one without Namespace.

Sitecore: using MVC areas

One thought on “Sitecore: using MVC areas

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