Safest method of obtaining ContentReference from LinkItem

Al Higgs
Member since: 2008
 

Hi all,

I'm interested in your view on the following. In certain circumstances it is useful for us to know whether the LinkItem's within a LinkItemCollection are internal objects i.e. pages/assets etc stored in EPiServer. For sometime we've had this method in our library:

public static ContentReference ToContentReference(this LinkItem linkItem)
        {
            if (linkItem == null)
                return ContentReference.EmptyReference;

            var urlBuilder = new UrlBuilder(linkItem.Href);
            return PermanentLinkMapStore.ToMapped(urlBuilder)
            ? PermanentLinkUtility.GetContentReference(urlBuilder)
            : ContentReference.EmptyReference;
        }

However, when I ran some tests on it today I found that even though PermanentLinkMapStore.ToMapped(urlBuilder) returned true, indicating it could map the Url to an internal object, PermanentLinkUtility.GetContentReference(urlBuilder) still returned an empty ContentReference - which seems incredibly strange to me.

So I've re-written it to the following. I'm not as happy with it as it has a dependency on the ContentLoader however it does seem to work:

private ContentReference ToContentReference(LinkItem linkItem)
        {
            if (linkItem == null)
                return ContentReference.EmptyReference;

            var urlBuilder = new UrlBuilder(linkItem.Href);
            var map = PermanentLinkMapStore.Find(urlBuilder);
            if (map == null)
                return ContentReference.EmptyReference;

            var guid = map.Guid;
            var content = _contentLoader.Get(guid);
            return content == null ? ContentReference.EmptyReference : content.ContentLink;
        }

Interested to hear youir thoughts.

Thanks in advance

Al

#119269 Mar 25, 2015 17:19
  • valdis iljuconoks
    Member since: 2011
     

    This is strange indeed. Can you paste one of internal mapped Urls?

    #119276 Mar 25, 2015 22:08
  • Johan Petersson
    Member since: 2007
     

    If you're on EPiServer 8, you should use the UrlResolver:

    var content = UrlResolver.Current.Route(new UrlBuilder(linkItem.Href))

    You also need to null-check content before returning content.ContentLink.

    #119279 Mar 26, 2015 4:53
  • Henrik Fransas
    Member since: 2007
     

    Thanks Johan, you have made me learn something new, that is a nice way to solve this.

    Do you know if it works in 7.5 also?

    #119280 Mar 26, 2015 7:39
  • Al Higgs
    Member since: 2008
     

    Hi guys,

    Valdis - all of these links fail to return a ContentReference using the original method. They all returned a valid ContentReference in 7.5 so I'm not sure what's happened, but it is a concern!

    • <a href="~/link/d8c9f56acb3d4980a3855b3038e54bc9.aspx">Test 1</a>
    • <a href="~/link/b130c0e0fd734b799521dfb57253dd02.aspx">Test 2</a>
    • <a href="~/link/a1e5326815a04cc6add1718ff3f563f1.aspx">Test 3 </a>

    Johan - that method works a treat. Thankfully we're in a position to upgrade our own nuget libraries to version 8, so I now have two simplified methods to cover LinkItem and Url:

    public static ContentReference ToContentReference(this LinkItem linkItem)
            {
                if (linkItem == null)
                    return ContentReference.EmptyReference;
    
                var content = UrlResolver.Current.Route(new UrlBuilder(linkItem.Href));
                return content != null ? content.ContentLink : ContentReference.EmptyReference;
            }

    And

    public static ContentReference ToContentReference(this Url url)
            {
                if (url == null)
                    return ContentReference.EmptyReference;
    
                var content = UrlResolver.Current.Route(new UrlBuilder(url));
                return content != null ? content.ContentLink : ContentReference.EmptyReference;
            }

    Thanks for your help guys. Still very interested to know why this broke in 8. I can't say I analyse all of the Release notes as much as I might, but it seems a fairly fundamental piece of the core of EPiServer that now works differently.

    Al

    #119288 Mar 26, 2015 11:05
  • Johan Petersson
    Member since: 2007
     

    Mapped links are gone in EPiServer 8. That's why your first method fails on PermanentLinkMapStore.ToMapped(). Your second method finds the permanent link, which stil works.

    This information was in the documentation under breaking changes :)

    #119300 Edited, Mar 26, 2015 14:19
  • Al Higgs
    Member since: 2008
     

    In which case...tut tut to me for not not viewing the release notes properly. However, if that's the case I would have expected the ToMapped and TryToMapped methods to have been marked obsolete, or perhaps even removed entirely if they no longer work - do you think so? Perhaps I should raise this.

    Thanks again

    Al

    #119302 Mar 26, 2015 14:25
  • Johan Petersson
    Member since: 2007
     

    It has been discussed here as well http://world.episerver.com/Modules/Forum/Pages/Thread.aspx?id=117930. But please ping the product guys, because I didn't get an answer when I raised the problem with functions related to mapped links.

    #119308 Mar 26, 2015 15:46