/// <summary> /// Returns an RSS feed URL specific to this author /// </summary> /// <param name="url"></param> /// <param name="model"></param> /// <returns></returns> public static string ArticulateAuthorRssUrl(this UrlHelper url, AuthorModel model) { var articulateRootUriPath = RouteCollectionExtensions.RoutePathFromNodeUrl(model.RootBlogNode.Url); var routeHash = articulateRootUriPath.GetHashCode(); var routeName = "articulate_author_rss_" + routeHash; return(url.RouteUrl(routeName, new { authorId = model.Id.ToInvariantString() })); }
public static void MapRoutes(RouteCollection routes, ContextualPublishedCache umbracoCache, UrlProvider umbracoUrlProvider) { //find all articulate root nodes var articulateNodes = umbracoCache.GetByXPath("//Articulate").ToArray(); LogHelper.Info(typeof(ArticulateRoutes), () => $"Mapping routes for {articulateNodes.Length} Articulate root nodes"); //NOTE: need to write lock because this might need to be remapped while the app is running if // any articulate nodes are updated with new values using (routes.GetWriteLock()) { //clear the existing articulate routes (if any) RemoveExisting(routes); // For each articulate root, we need to create some custom route, BUT routes can overlap // based on multi-tenency so we need to deal with that. // For example a root articulate node might yield a route like: // / // and another articulate root node that has a domain might have this url: // http://mydomain/ // but when that is processed through RoutePathFromNodeUrl, it becomes: // / // which already exists and is already assigned to a specific node ID. // So what we need to do in these cases is use a special route handler that takes // into account the domain assigned to the route. var articulateNodesGroupedByUriPath = articulateNodes .GroupBy(x => RouteCollectionExtensions.RoutePathFromNodeUrl(x.Url)) //This is required to ensure that we create routes that are more specific first // before creating routes that are less specific .OrderByDescending(x => x.Key.Split('/').Length); foreach (var nodeByPathGroup in articulateNodesGroupedByUriPath) { var nodesAsArray = nodeByPathGroup.ToArray(); var uriPath = nodeByPathGroup.Key; MapRssRoute(routes, umbracoUrlProvider, uriPath, nodesAsArray); MapSearchRoute(routes, umbracoUrlProvider, uriPath, nodesAsArray); MapTagsAndCategoriesRoute(routes, umbracoUrlProvider, uriPath, nodesAsArray); MapMarkdownEditorRoute(routes, umbracoUrlProvider, uriPath, nodesAsArray); MapAuthorsRssRoute(routes, umbracoUrlProvider, uriPath, nodesAsArray); foreach (var articulateRootNode in nodeByPathGroup) { MapMetaWeblogRoute(routes, uriPath, articulateRootNode); MapManifestRoute(routes, uriPath, articulateRootNode); MapRsdRoute(routes, uriPath, articulateRootNode); MapOpenSearchRoute(routes, uriPath, articulateRootNode); } } } }