Grouping shell routes by area and priority

This commit is contained in:
Sebastien Ros
2013-11-18 15:34:50 -08:00
parent 01b6667d6d
commit c4b4967e06
3 changed files with 134 additions and 15 deletions

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Environment;
using Orchard.Environment.Configuration;
namespace Orchard.Mvc.Routes {
public class HubRoute : RouteBase, IRouteWithArea, IComparable<HubRoute> {
private readonly IRunningShellTable _runningShellTable;
private readonly ConcurrentDictionary<string, IList<RouteBase>> _routesByShell = new ConcurrentDictionary<string, IList<RouteBase>>();
public HubRoute(string area, int priority, IRunningShellTable runningShellTable) {
Priority = priority;
Area = area;
_runningShellTable = runningShellTable;
}
public string Area { get; private set; }
public int Priority { get; private set; }
/// <summary>
/// Removes the routes associated with a shell
/// </summary>
public void ReleaseShell(ShellSettings shellSettings) {
IList<RouteBase> routes;
_routesByShell.TryRemove(shellSettings.Name, out routes);
}
public void Add(RouteBase route, ShellSettings shellSettings) {
var routes = _routesByShell.GetOrAdd(shellSettings.Name, key => new List<RouteBase>());
routes.Add(route);
}
public override RouteData GetRouteData(HttpContextBase httpContext) {
var settings = _runningShellTable.Match(httpContext);
if (settings == null)
return null;
IList<RouteBase> routes;
if (!_routesByShell.TryGetValue(settings.Name, out routes)) {
return null;
}
foreach (var route in routes) {
RouteData routeData = route.GetRouteData(httpContext);
if(routeData != null) {
return routeData;
}
}
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
var settings = _runningShellTable.Match(requestContext.HttpContext);
if (settings == null)
return null;
IList<RouteBase> routes;
if (!_routesByShell.TryGetValue(settings.Name, out routes)) {
return null;
}
foreach (var route in routes) {
VirtualPathData virtualPathData = route.GetVirtualPath(requestContext, values);
if (virtualPathData != null) {
return virtualPathData;
}
}
return null;
}
public int CompareTo(HubRoute other) {
if (other == null) {
return -1;
}
if (other == this) {
return 0;
}
if (!String.Equals(other.Area, Area, StringComparison.OrdinalIgnoreCase)) {
return StringComparer.OrdinalIgnoreCase.Compare(other.Area, Area);
}
if (other.Priority == Priority) {
return StringComparer.OrdinalIgnoreCase.Compare(other.Area, Area);
}
return Priority.CompareTo(other.Priority);
}
}
}

View File

@@ -5,6 +5,7 @@ using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
using Castle.Core;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
@@ -55,14 +56,9 @@ namespace Orchard.Mvc.Routes {
using (_routeCollection.GetWriteLock()) {
// existing routes are removed while the collection is briefly inaccessable
var cropArray = _routeCollection
.OfType<ShellRoute>()
.Where(sr => sr.ShellSettingsName == _shellSettings.Name)
.ToArray();
foreach(var crop in cropArray) {
_routeCollection.Remove(crop);
}
_routeCollection
.OfType<HubRoute>()
.ForEach(x => x.ReleaseShell(_shellSettings));
// new routes are added
foreach (var routeDescriptor in routesArray) {
@@ -98,14 +94,35 @@ namespace Orchard.Mvc.Routes {
SessionState = sessionStateBehavior
};
try {
_routeCollection.Add(routeDescriptor.Name, shellRoute);
}
catch(ArgumentException) {
// Named routes can be added multiple times in the case of a module
// loaded in multiple tenants. There is no way to ensure a named route
// is already registered, thus catching the specific exception.
var area = extensionDescriptor == null ? "" : extensionDescriptor.Id;
var matchedHubRoute = _routeCollection.FirstOrDefault(x => {
var hubRoute = x as HubRoute;
if (hubRoute == null) {
return false;
}
return routeDescriptor.Priority == hubRoute.Priority && hubRoute.Area.Equals(area, StringComparison.OrdinalIgnoreCase);
}) as HubRoute;
if (matchedHubRoute == null) {
matchedHubRoute = new HubRoute(area, routeDescriptor.Priority, _runningShellTable);
int index;
for (index = 0; index < _routeCollection.Count; index++) {
var hubRoute = _routeCollection[index] as HubRoute;
if (hubRoute == null) {
continue;
}
if (hubRoute.Priority < matchedHubRoute.Priority) {
break;
}
}
_routeCollection.Insert(index, matchedHubRoute);
}
matchedHubRoute.Add(shellRoute, _shellSettings);
}
}
}

View File

@@ -275,6 +275,7 @@
<Compile Include="Mvc\HttpContextWorkContext.cs" />
<Compile Include="Mvc\Extensions\ControllerExtensions.cs" />
<Compile Include="Mvc\IOrchardViewPage.cs" />
<Compile Include="Mvc\Routes\HubRoute.cs" />
<Compile Include="Mvc\ShapeResult.cs" />
<Compile Include="Mvc\Spooling\HtmlStringWriter.cs" />
<Compile Include="Mvc\ViewEngines\Razor\IRazorCompilationEvents.cs" />