public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { // here we deal with people linking to non-n2 controllers but we have merged route values containing n2 stuff // scenarios: // controller: other -> not our business // controller: self -> link to same acton and page // acton: other -> link to action on same page // item: other -> link to other page // nuthin' -> link to same acton and page // x: y -> add parameter x // page: other -> not our business // item: other & action: other -> link to action other page // item: other & action: other & x:y-> link to action other page with param // app in virtual dir values = new RouteValueDictionary(values); logger.DebugFormat("GetVirtualPath for values: {0}", new RouteExtensions.QueryStringOutput(values)); var contextPath = requestContext.RouteData.CurrentPath(); var requestedItem = values.CurrentItem <ContentItem>(ContentItemKey, engine.Persister); var item = requestedItem; if (item == null) { // fallback to context item item = contextPath.CurrentItem; } else { // remove specified item from collection so it doesn't appear in the url values.Remove(ContentItemKey); } if (item == null) { // no item requested or in context .> not our bisiness return(null); } var contextController = (string)requestContext.RouteData.Values["controller"]; var requestedController = (string)values["controller"]; if (requestedItem == null && requestedController != null) { if (!string.Equals(requestedController, contextController, StringComparison.InvariantCultureIgnoreCase)) { // no item was specificlly requested, and the controller differs from context's -> we let some other route handle this return(null); } if (!controllerMapper.IsContentController(requestedController)) { // same controller not content controller -> let it be return(null); } } var itemController = controllerMapper.GetControllerName(item.GetContentType()); values["controller"] = itemController; if (item.IsPage) { return(ResolveContentActionUrl(requestContext, values, item)); } // try to find an appropriate page to use as path (part data goes into the query strings) var page = values.CurrentItem <ContentItem>(ContentPageKey, engine.Persister) ?? contextPath.CurrentPage ?? item.ClosestPage(); if (page != null) { return(ResolvePartActionUrl(requestContext, values, page, item)); } // can't find a page, don't link return(null); }