Hi,
Below is an extension method (for UrlHelper) that lets you generate Url's to specific actions on page controllers:
e.g. Url.PageUrl(myPage, "SomeAction", new { someMethodParamater : parameterValue })
public static MvcHtmlString PageUrl(this UrlHelper instance, PageData page, string action, object routeValues) { var rvd = new RouteValueDictionary(routeValues); var urlBuilder = new UrlBuilder(HttpUtility.HtmlDecode(page.LinkURL)); var languageForRequest = GetLanguageForRequest(urlBuilder, instance.RequestContext); var shouldSetIdAsQueryParameter = ShouldSetIdAsQueryParameter(instance.RequestContext); var newRequestContext = new RequestContext {RouteData = new RouteData()}; // Build the new route values up based on the existing request, // the additional route values passed and the new action rvd.Add("action", action); if (instance.RequestContext.GetIgnorePartialRouting()) { rvd.Add("ignorePartialRouting", true); } if (shouldSetIdAsQueryParameter) { rvd.Add("id", page.PageLink.ToString()); } if (PageEditing.PageIsInEditMode) { newRequestContext.RouteData.DataTokens["contextmode"] = ContextMode.Edit; } var epichannel = PageEditing.GetChannel(instance.RequestContext.HttpContext); if (!string.IsNullOrEmpty(epichannel)) { rvd.Add("epichannel", epichannel); } var urlResolver = new UrlResolver(instance.RouteCollection, null, null); return new MvcHtmlString(urlResolver.GetVirtualPath(page.PageLink, languageForRequest, rvd, newRequestContext).GetUrl()); }
Here's the whole class, which you will need to compile the snippet
using System.Web; using System.Web.Mvc; using System.Web.Routing; using EPiServer; using EPiServer.Core; using EPiServer.Editor; using EPiServer.Globalization; using EPiServer.ServiceLocation; using EPiServer.Web; using EPiServer.Web.Mvc.Html; using EPiServer.Web.Routing; namespace <Putyournamespacehere> { public static class UrlExtension { // cheater to fix app_code helpers.cshtml. Cannot call helper extensions from app_code in mvc public static IHtmlString PageLinkUrl(PageReference pageLink) { if (ContentReference.IsNullOrEmpty(pageLink)) { return MvcHtmlString.Empty; } var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>(); var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>(); var page = contentLoader.Get<PageData>(pageLink); return new MvcHtmlString(urlResolver.GetVirtualPath(page.PageLink)); } /// <summary> /// Returns the target URL for a PageReference. Respects the page's shortcut setting /// so if the page is set as a shortcut to another page or an external URL that URL /// will be returned. /// </summary> public static IHtmlString PageLinkUrl(this UrlHelper urlHelper, PageReference pageLink) { if (ContentReference.IsNullOrEmpty(pageLink)) { return MvcHtmlString.Empty; } var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>(); var page = contentLoader.Get<PageData>(pageLink); return PageLinkUrl(urlHelper, page); } /// <summary> /// Returns the target URL for a page. Respects the page's shortcut setting /// so if the page is set as a shortcut to another page or an external URL that URL /// will be returned. /// </summary> public static IHtmlString PageLinkUrl(this UrlHelper urlHelper, PageData page) { var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>(); switch (page.LinkType) { case PageShortcutType.Normal: case PageShortcutType.FetchData: return new MvcHtmlString(urlResolver.GetVirtualPath(page.PageLink)); case PageShortcutType.Shortcut: var shortcutProperty = page.Property["PageShortcutLink"] as PropertyPageReference; if (shortcutProperty != null && !ContentReference.IsNullOrEmpty(shortcutProperty.PageLink)) { return urlHelper.PageLinkUrl(shortcutProperty.PageLink); } break; case PageShortcutType.External: return new MvcHtmlString(page.LinkURL); } return MvcHtmlString.Empty; } public static RouteValueDictionary GetPageRoute(this RequestContext requestContext, PageReference pageLink) { var values = new RouteValueDictionary(); values[RoutingConstants.NodeKey] = pageLink; values[RoutingConstants.LanguageKey] = ContentLanguage.PreferredCulture.Name; var idkeep = requestContext.HttpContext.Request.QueryString["idkeep"]; if (idkeep != null && !PageReference.IsNullOrEmpty(pageLink)) { values["id"] = pageLink.ToString(); } return values; } public static string Content(this UrlHelper instance, Url contentPath) { if (contentPath == null) { return null; } return instance.Content(contentPath.ToString()); } public static MvcHtmlString PageUrl(this UrlHelper instance, PageReference pageReference) { return PageUrl(instance, pageReference.GetPage(), null); } public static MvcHtmlString PageUrl(this UrlHelper instance, PageReference pageReference, object routeValues) { return PageUrl(instance, pageReference.GetPage(), routeValues); } public static MvcHtmlString PageUrl(this UrlHelper instance, PageReference pageReference, string action, object routeValues) { return PageUrl(instance, pageReference.GetPage(), action, routeValues); } public static MvcHtmlString PageUrl(this UrlHelper instance, PageData page) { return PageUrl(instance, page, null); } public static MvcHtmlString PageUrl(this UrlHelper instance, PageData page, object routeValues) { return PageUrl(instance, page, "Index", routeValues); } public static MvcHtmlString PageUrl(this UrlHelper instance, PageData page, string action, object routeValues) { var rvd = new RouteValueDictionary(routeValues); var urlBuilder = new UrlBuilder(HttpUtility.HtmlDecode(page.LinkURL)); var languageForRequest = GetLanguageForRequest(urlBuilder, instance.RequestContext); var shouldSetIdAsQueryParameter = ShouldSetIdAsQueryParameter(instance.RequestContext); var newRequestContext = new RequestContext {RouteData = new RouteData()}; // Build the new route values up based on the existing request, // the additional route values passed and the new action rvd.Add("action", action); if (instance.RequestContext.GetIgnorePartialRouting()) { rvd.Add("ignorePartialRouting", true); } if (shouldSetIdAsQueryParameter) { rvd.Add("id", page.PageLink.ToString()); } if (PageEditing.PageIsInEditMode) { newRequestContext.RouteData.DataTokens["contextmode"] = ContextMode.Edit; } var epichannel = PageEditing.GetChannel(instance.RequestContext.HttpContext); if (!string.IsNullOrEmpty(epichannel)) { rvd.Add("epichannel", epichannel); } var urlResolver = new UrlResolver(instance.RouteCollection, null, null); return new MvcHtmlString(urlResolver.GetVirtualPath(page.PageLink, languageForRequest, rvd, newRequestContext).GetUrl()); } public static MvcHtmlString PageUrl(this UrlHelper urlHelper, Url url) { if (url == null) { return null; } if (url.IsEmpty()) { return MvcHtmlString.Empty; } return urlHelper.PageUrl(classicUrl: url.ToString()); } public static bool IsNullOrEmpty(this Url contentPath) { if (contentPath == null) { return true; } if (contentPath.IsEmpty()) { return true; } return false; } private static string GetLanguageForRequest(UrlBuilder urlBuilder, RequestContext requestContext) { var language = urlBuilder.QueryCollection["epslanguage"]; if (string.IsNullOrWhiteSpace(language)) { language = (requestContext.GetLanguage() ?? ContentLanguage.PreferredCulture.Name); } return language; } private static bool ShouldSetIdAsQueryParameter(RequestContext requestContext) { var setIdAsQueryParameter = false; bool flag; if (!string.IsNullOrEmpty(requestContext.HttpContext.Request.QueryString["idkeep"]) && !bool.TryParse(requestContext.HttpContext.Request.QueryString["idkeep"], out flag)) { setIdAsQueryParameter = flag; } return setIdAsQueryParameter; } /* private static string MapUrlFromRoute(RequestContext requestContext, RouteCollection routeCollection, string url) { UrlBuilder urlBuilder = new UrlBuilder(HttpUtility.HtmlDecode(url)); ContentReference contentReference = PermanentLinkUtility.GetContentReference(urlBuilder); if (!ContentReference.IsNullOrEmpty(contentReference)) { string text = urlBuilder.QueryCollection["epslanguage"]; if (text == null) { text = (requestContext.GetLanguage() ?? ContentLanguage.PreferredCulture.Name); } bool setIdAsQueryParameter = false; bool flag; if (!string.IsNullOrEmpty(requestContext.HttpContext.Request.QueryString["idkeep"]) && !bool.TryParse(requestContext.HttpContext.Request.QueryString["idkeep"], out flag)) { setIdAsQueryParameter = flag; } VirtualPathData virtualPath = GetVirtualPath(routeCollection, contentReference, text, setIdAsQueryParameter, false); return virtualPath.GetUrl(); } return urlBuilder.ToString(); } private static VirtualPathData GetVirtualPath(RouteCollection routes, ContentReference contentLink, string language, bool setIdAsQueryParameter, bool forceIsInEditMode) { RequestContext requestContext = new RequestContext(); requestContext.RouteData = new RouteData(); RouteValueDictionary routeValueDictionary = new RouteValueDictionary(); RequestContext requestContext2 = HttpContext.Current.GetRequestContext(); if (forceIsInEditMode || (requestContext2 != null && requestContext2.GetIgnorePartialRouting())) { routeValueDictionary.Add(RoutingConstants.IgnorePartialRoutingKey, true); } if (setIdAsQueryParameter) { routeValueDictionary.Add(RoutingConstants.IdKey, contentLink.ToString()); } if (forceIsInEditMode || PageEditing.PageIsInEditMode) { requestContext.SetContextMode(ContextMode.Edit); } string value = (requestContext2 != null) ? PageEditing.GetChannel(requestContext2.HttpContext) : null; if (!string.IsNullOrEmpty(value)) { routeValueDictionary.Add("epichannel", value); } UrlResolver urlResolver = new UrlResolver(routes, null, null); return urlResolver.GetVirtualPath(contentLink, language, routeValueDictionary, requestContext); }*/ } }
Hi, I'm wondering if it's possible to connect a specific PageLink from my nav to a specific action in the controller?
I'm trying to recreate my company's intranet as an assignment for my internship here, and I'm trying to keep the code to a minimum, with the same functionality and design - but with editorial properties etc.
I'm using a modified version of Joel Abrahamssons NavigationHelper(RenderMainNavigation) that simply creates tablerows and data inside a table instead of an UL, but I want to associate each PageLink with a specific action without creating a ton of different controllers.
As an example:
I have the startpage in the nav, and when I click it I want it to go to the action Index.
I also have a profilepage in the nav, and when I click that link I would like it to go to a different action in the same controller (even though it's a different pagetype) and return a different view inside a @section.
I currently have no built up code for any of this except the NavigationHelper class, but I'm wondering if this is possible or if there's another, better way or if I should just give up and do it the normal way.
Thanks in advance.