public void Publish(IEnumerable<RouteDescriptor> routes) { var routesArray = routes .OrderByDescending(r => r.Priority) .ToArray(); // this is not called often, but is intended to surface problems before // the actual collection is modified var preloading = new RouteCollection(); foreach (var routeDescriptor in routesArray) { // extract the WebApi route implementation var httpRouteDescriptor = routeDescriptor as HttpRouteDescriptor; if (httpRouteDescriptor != null) { var httpRouteCollection = new RouteCollection(); httpRouteCollection.MapHttpRoute(httpRouteDescriptor.Name, httpRouteDescriptor.RouteTemplate, httpRouteDescriptor.Defaults, httpRouteDescriptor.Constraints); routeDescriptor.Route = httpRouteCollection.First(); } preloading.Add(routeDescriptor.Name, routeDescriptor.Route); } using (_routeCollection.GetWriteLock()) { // existing routes are removed while the collection is briefly inaccessable _routeCollection .OfType<HubRoute>() .ForEach(x => x.ReleaseShell(_shellSettings)); // new routes are added foreach (var routeDescriptor in routesArray) { // Loading session state information. var defaultSessionState = SessionStateBehavior.Default; ExtensionDescriptor extensionDescriptor = null; if(routeDescriptor.Route is Route) { object extensionId; var route = routeDescriptor.Route as Route; if(route.DataTokens != null && route.DataTokens.TryGetValue("area", out extensionId) || route.Defaults != null && route.Defaults.TryGetValue("area", out extensionId)) { extensionDescriptor = _extensionManager.GetExtension(extensionId.ToString()); } } else if(routeDescriptor.Route is IRouteWithArea) { var route = routeDescriptor.Route as IRouteWithArea; extensionDescriptor = _extensionManager.GetExtension(route.Area); } if (extensionDescriptor != null) { // if session state is not define explicitly, use the one define for the extension if (routeDescriptor.SessionState == SessionStateBehavior.Default) { Enum.TryParse(extensionDescriptor.SessionState, true /*ignoreCase*/, out defaultSessionState); } } // Route-level setting overrides module-level setting (from manifest). var sessionStateBehavior = routeDescriptor.SessionState == SessionStateBehavior.Default ? defaultSessionState : routeDescriptor.SessionState ; var shellRoute = new ShellRoute(routeDescriptor.Route, _shellSettings, _workContextAccessor, _runningShellTable) { IsHttpRoute = routeDescriptor is HttpRouteDescriptor, SessionState = sessionStateBehavior }; 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) && hubRoute.Name == routeDescriptor.Name; }) as HubRoute; if (matchedHubRoute == null) { matchedHubRoute = new HubRoute(routeDescriptor.Name, 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); } } }