5

I'm struggling to get the Sitecore item url from indexing, the SearchResultItem.url is always null.

I tried creating a ComputedField but I'm not getting the correct url.

With Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions(); urlOptions.SiteResolving = false;

I get /en/site1/Home/section/subsection/article-name

With urlOptions.SiteResolving = true;

I get ://test.local/en/section/subsection/article-name

How can I just get /en/section/subsection/article-name or how can I use ://test.local/en/section/subsection/article-name in razor view?

I have a multi-site configuration.

1
  • 1
    hey Huzzi, what's missing on the second example is the protocol (http, https). You could add the attribute "scheme" with the value "http" to the definition of your sites so it returns the protocol. This is if you want absolute url
    – josedbaez
    Nov 11, 2016 at 11:27

3 Answers 3

6

I believe the issue is that the indexing runs without a HttpContext and not in the correct site context either.

The missing site context is why you have to use SiteResolving = true as otherwhise it doesn't know the site and have to use the full path (i.e. /en/site1/Home/...).

The missing HttpContext means it cannot determine the protocol/scheme (as there is no request). If you set that on your site definitions (as mentioned by josedbaez) it should show up when using SiteResolving = true.

<site name="site1" scheme="http" ... />

An alternative is to just get the actual item from the database via the SearchResultItem and get the link from that where you need it.

var item = searchResultItem.GetItem();
var url = LinkManager.GetItemUrl(item);

Of course this might not be the best solution if you need to filter on this or are showing a lot of items.

0
6

It's worth bearing in mind that you'll always have the ID of the item in the Index, so you would still be able to generate a URL at runtime once you have your search result. This may also be preferable on cutting down the complexity of your solution.

However, to address your question:

With Lucene, the URL should be populated by default in the index. However I believe this only works for the default "website" site. This is the code that Sitecore uses for the SearchResultItem.Url property which is connected to the urllink field in the index:

public class UrlLink : AbstractComputedIndexField
  {
    public override object ComputeFieldValue(IIndexable indexable)
    {
      Item item = (Item) (indexable as SitecoreIndexableItem);

      if (item == null)
        return (object) null;

      if (item.Paths.IsMediaItem)
        return (object) MediaManager.GetMediaUrl((MediaItem) item);

      UrlOptions defaultUrlOptions = LinkManager.GetDefaultUrlOptions();
      defaultUrlOptions.Site = SiteContextFactory.GetSiteContext("website");

      return (object) LinkManager.GetItemUrl(item, defaultUrlOptions);
    }
  }

As you can see, the site context of "website" is hardcoded in. For items in that website, the URL should be fine. Other sites will be incorrect however and result in URLs such as /en/sitename/Home....

If you are in a multi-site environment (and your question suggests you are), you will need an alternate method that determines what is the correct Site based on the item, and then sets that .Site in the URL options.

You can use an extension method such as this for getting the site based on an item:

public static SiteInfo GetSite(this Item item)
{
    var siteInfoList = Sitecore.Configuration.Factory.GetSiteInfoList();

    SiteInfo currentSiteinfo = null;
    var matchLength = 0;
    foreach (var siteInfo in siteInfoList)
    {
        if (item.Paths.FullPath.StartsWith(siteInfo.RootPath, StringComparison.OrdinalIgnoreCase) && siteInfo.RootPath.Length > matchLength)
        {
            matchLength = siteInfo.RootPath.Length;
            currentSiteinfo = siteInfo;
        }
    }

    return currentSiteinfo;
}

Combined with the above, this would allow you to update your computed index field with:

defaultUrlOptions.Site = new SiteContext(item.GetSite());

Credit for the extension method goes to zhankezk in the answer to this StackOverflow question - https://stackoverflow.com/questions/14200864/how-to-find-out-with-which-sitecore-site-an-item-is-associated

0
2

You could use the LinkManager.GetItemUrl to generate the url on the item you got from the SearchResult:

LinkManager.GetItemUrl(yourSearchResultItem.GetItem());

This will use the DefaultUrlOptions which are defined in the linkManager section in Sitecore.config.

Depending on the number of items you are getting back from those searches, it may be benificial to use a ComputedField like you described.
I don't know which options you set exactly at the moment. But best practice is to use the DefaultUrlOptions and modify the parameter(s) that you want for the specific purpose.

Sitecore.Links.UrlOptions urlOptions = LinkManager.GetDefaultUrlOptions(); 
urlOptions.AlwaysIncludeServerUrl = false; 
LinkManager.GetItemUrl(item, urlOptions);`

Here is a good read about LinkProviders in multi-site environments:https://jammykam.wordpress.com/2015/02/03/site-specific-link-provider-for-multi-site-implementation-in-sitecore/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.