Sitecore out of the box will not provide MVC areas support but you will need this functionality for good solution organization. However, Sitecore has a good pipeline system and you could plug your code that will resolve areas.
Implementation#
You need to apply area detection only to** controllers renderings**, as Controllers will require areas information in order to resolve views for example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| {
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)
};
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| {
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 });
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| {
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;
}
}
}
}
|
1
2
3
4
5
6
7
8
9
| <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.