Thursday, 6 June 2013

Gotcha in Orchard CMS RoutesDescriptor when using Multi-Tenancy

It's been a while since I posted, and I've been using Orchard CMS a lot among other things. I came across a rather trickysome problem today, hopefully this post will help others find the resolution quicker than I did. In orchard you can Implement IRouteProvider in any module you write. This is basically a wrapper for MVC routes, and works really well. For example, the route defined below is for custom handling in the event of errors.

public class ErrorHandlingRoutesProvider : IRouteProvider
    { 
        public IEnumerable<routedescriptor> GetRoutes() 
        { 
            return new[]{  
                new RouteDescriptor{ 
                    Name = "ErrorRoute",  
                    Priority = 1,                     
                    Route = new Route( 
                        "Error", 
                        new RouteValueDictionary{ 
                            {"action", "ErrorPage"}, 
                            {"controller", "ErrorHandler"}, 
                            {"area", "BG.Shared.ErrorHandling"} 
                        }, 
                        new RouteValueDictionary(),//constraints (none here) 
                        new RouteValueDictionary{ 
                            {"area", "BG.Shared.ErrorHandling"} 
                        }, 
                        new MvcRouteHandler()) 
                }; 
        }

This works as intended in a single site. However, when you have two tenants using the same module, this will fail with an error similar to the following:

System.ArgumentException: A route named 'ErrorRoute' is already in the route collection. Route names must be unique.
Parameter name: name 
   at System.Web.Routing.RouteCollection.Add(String name, RouteBase item) 
   at Orchard.Mvc.Routes.RoutePublisher.Publish(IEnumerable`1 routes) in d:\Workspaces\GitHub\src\Orchard\Mvc\Routes\RoutePublisher.cs:line 100
   at Orchard.Environment.DefaultOrchardShell.Activate() in d:\Workspaces\GitHub\src\Orchard\Environment\DefaultOrchardShell.cs:line 48
   at Orchard.Environment.DefaultOrchardHost.ActivateShell(ShellContext context) in d:\Workspaces\GitHub\src\Orchard\Environment\DefaultOrchardHost.cs:line 156
   at Orchard.Environment.DefaultOrchardHost.CreateAndActivateShells() in d:\Workspaces\GitHub\src\Orchard\Environment\DefaultOrchardHost.cs:line 135

The workaround is to comment out the "Name" attribute of the RouteDescriptor, as follows
public IEnumerable<RouteDescriptor> GetRoutes() 
        { 
            return new[]{  
                new RouteDescriptor{ 
                     
                    //Name = "ErrorRoute", //This doesn't work in Multi-Tenancy 
                    Priority = 1,                     
                    Route = new Route( 
                        "Error", 
                        new RouteValueDictionary{ 
                            {"action", "ErrorPage"}, 
                            {"controller", "ErrorHandler"}, 
                            {"area", "BG.Shared.ErrorHandling"} 
                        }, 
                        new RouteValueDictionary(),//constraints (none here) 
                        new RouteValueDictionary{ 
                            {"area", "BG.Shared.ErrorHandling"} 
                        }, 
                        new MvcRouteHandler()) 
                }      
            }; 
        }
I've started investigating this with the Orchard team, but the workaround doesn't really appear to have any drawbacks.

1 comment:

  1. This is already fixed, see: https://orchard.codeplex.com/workitem/19611

    ReplyDelete