Sitecore MVC in a multisite environment: area’s

If you are creating a multisite environment using Sitecore & MVC (or any MVC site for that matter), chance is you have to do some weird naming in your controllers to avoid naming conflicts.

This is why Microsoft introduced area’s in their implementation of MVC (as did others before them)

Using them in Sitecore is actually pretty easy, thanks to (again) sitecore’s flexible pipilines.

First, we extend the Initialize pipeline with our own step:


  
    
      
      
        
      
    
  

Then add our class to the project:

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Sitecore.Configuration;
using Sitecore.Mvc.Configuration;
using Sitecore.Pipelines;

namespace BoC.Sitecore.Pipelines
{
    public class InitializeRoutes
    {
        public virtual void Process(PipelineArgs args)
        {
            var scRoute = RouteTable.Routes[MvcSettings.SitecoreRouteName] as Route;
            var indx = RouteTable.Routes.IndexOf(scRoute);
            AreaRegistration.RegisterAllAreas();
            foreach (var info in Factory.GetSiteInfoList())
            {
                if (info.Properties["mvcArea"] != null)
                {
                    var newRoute = new Route(scRoute.Url, 
                        new RouteValueDictionary(scRoute.Defaults), 
                        new RouteValueDictionary(scRoute.Constraints), 
                        new RouteValueDictionary(scRoute.Constraints), 
                        scRoute.RouteHandler);
                    newRoute.DataTokens.Add("area", info.Properties["mvcArea"]);
                    newRoute.Constraints.Add("sc-issite", new IsCorrectSiteContraint(info.Name));

                    if (info.Properties["mvcNamespaces"] != null)
                    {
                        newRoute.DataTokens["Namespaces"] = info.Properties["mvcNamespaces"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                        newRoute.DataTokens["UseNamespaceFallback"] = false;
                    }

                    RouteTable.Routes.Insert(indx, newRoute);
                }

            }
        }

        public class IsCorrectSiteContraint : IRouteConstraint
        {
            private readonly string _siteId;

            public IsCorrectSiteContraint(string siteId)
            {
                _siteId = siteId;
            }

            public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values,
                RouteDirection routeDirection)
            {
                return global::Sitecore.Sites.SiteContext.Current.Name == _siteId;
            }
        }
    }
}

Now what this code does, is to add a route to the routecollection for every Sitecore-site configured. It uses a routeconstraint to validate if the route is applyable for the current request. If it is applyable the property ‘mvcArea’ of the configured website is set as the MVC area for that request. So, we will have to extend the tag of the sitecore configuration with an mvcArea attribute, like so:


  
    
      
    
  

As you can see, we also specify “mvcnamespaces”, although these are optional, it allows you to tell MVC where to look for your controllers.

It’s this easy. So now you’re ready to go and create your controllers & views in the correct manner. Don’t forget to place your views in the correct folder (in this case: areascorporateviews)

3 Replies to “Sitecore MVC in a multisite environment: area’s”

  1. I tried your solution and
    var scRoute = RouteTable.Routes[MvcSettings.SitecoreRouteName] as Route; is null for me. Do you have idea why?

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.