Wednesday, May 22, 2013

Sitecore with MVC 4

Task at hand:

Sitecore works pretty nicely with MVC 4 until you try to use default MVC functionality like bundling. When you attempt to use it and run the solution in release mode, you'll see all your bundles returning 404. The reason for that is Mvc.IllegalRoutes setting in Sitecore.Mvc.config. John West has written as series of post regarding this functionality, but I figured I would post my solution.

Solution:

  • Remove {controller}/{action}/{id} from Mvc.IllegalRoutes:
    <setting name="Mvc.IllegalRoutes" value="" />
  • Create a new class for a route contraint like so: 
public class SitecoreConstraint : IRouteConstraint
    {
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            if (Sitecore.Context.Item != null && Sitecore.Context.Item.Visualization.Layout != null)
            {
                return false;                
            }
            return true;
        }
    }
  • Add newly created constraint to RouteConfig:
public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                constraints: new { sitecoreRoute = new SitecoreConstraint() }
            );
        }
    }

That should solve the routing problem and allow you to use bundles with Sitecore.

UPDATE:

I just upgraded our solution from 7.0 to 7.2 (Update-2) and bundles seem to be working without any issue when I add "/bundles" to "IgnoreUrlPrefixes". No modification of Mvc.IllegalRoutes was required.

One more thing I had to change to make css @import statement work.

Instead of:

bundles.Add(new StyleBundle("~/bundles/css").Include("~/assets/design_new/css/main.css""~/assets/design_new/css/all.css"));


I had to place all css files into the same directory and use CssRewriteUrlTransform object:

bundles.Add(new StyleBundle("~/bundles/css").Include("~/assets/design_new/css/*.css"new CssRewriteUrlTransform()));