November Happy Hour will be moved to Thursday December 5th.

MVC: Specific PageLink leads to specific Action

Vote:
 

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.

#112594
Oct 30, 2014 16:20
Vote:
 

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());
        }
#112606
Oct 31, 2014 12:24
Vote:
 

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);
        }*/
    }
}
#112607
Oct 31, 2014 12:26
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.