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{

                <span style="color: green;">//Name = "ErrorRoute", //This doesn't work in Multi-Tenancy</span> 
                Priority = <span style="color: maroon;">1</span>,                     
                Route = <span style="color: blue;">new</span> Route( 
                    <span style="color: maroon;">"Error"</span>, 
                    <span style="color: blue;">new</span> RouteValueDictionary{ 
                        {<span style="color: maroon;">"action"</span>, <span style="color: maroon;">"ErrorPage"</span>}, 
                        {<span style="color: maroon;">"controller"</span>, <span style="color: maroon;">"ErrorHandler"</span>}, 
                        {<span style="color: maroon;">"area"</span>, <span style="color: maroon;">"BG.Shared.ErrorHandling"</span>} 
                    }, 
                    <span style="color: blue;">new</span> RouteValueDictionary(),<span style="color: green;">//constraints (none here)</span> 
                    <span style="color: blue;">new</span> RouteValueDictionary{ 
                        {<span style="color: maroon;">"area"</span>, <span style="color: maroon;">"BG.Shared.ErrorHandling"</span>} 
                    }, 
                    <span style="color: blue;">new</span> MvcRouteHandler()) 
            }      
        }; 
    }</pre>I've started investigating this with the Orchard team, but the workaround doesn't really appear to have any drawbacks.