EpiServer - Get the absolute friendly URL for a given culture for a page

I have the following setting in the Site Management panel

Shared Url is set to alloy.com

alloy .no set for culture no

alloy.se is customized for sv culture

alloy.com is customized for ru culture

In my code, I want to get a friendly external url for a given language for a given page. So for the Search page, I want to get a completely friendly URL in all languages.

I am using the following code to get the friendly url for a page (found on Anders G. Nordby blog ):

var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>();
var pageAddress = urlResolver.GetUrl(reference, language);

var builder = new UrlBuilder(pageAddress);

Global.UrlRewriteProvider.ConvertToExternal(builder, null, Encoding.UTF8);

var friendlyUrl = builder.Uri.IsAbsoluteUri
    ? builder.ToString()
    : UriSupport.AbsoluteUrlBySettings(builder.ToString());

return friendlyUrl;

      

It's easy if I use the alloy.com webpage and generate a friendly URL in my custom code.

  • no - alloy.no/søk
  • se - alloy.se/sök
  • ru - alloy.com/search

But when I use the .no alloy to enter edit mode and I try to create an address for no , I get the com / søk alloy when it should be an alloy. no / søk.

I found that if I use the .no alloy to go into edit mode the code is:

urlResolver.GetUrl(reference, language)

      

only returns / søk and code

UriSupport.AbsoluteUrlBySettings(builder.ToString())

      

add a generic url (alloy.com) instead of alloy .no.

How can I improve this code to choose the correct hostname for a page in a different culture?

+3


source to share


4 answers


The GetUrl method for UrlResolver returns the URL to a relative or absolute page, depending on the current request context. The URL will be relative if the page is on the current site and absolute if on another site or if the call is made outside of the request.

If you are using EPiServer.CMS.Core version 8.0 or newer, there is also support for identifying one site as the primary site. This update also made it possible to explicitly request the URL to be on the main site by setting the ForceCanonical flag to the VirtualPathArguments parameter. If the flag is not set, it will prefer the current site url over the main one (if the requested content is on the current site).

So with that in mind, you can assume that the returned url, if not absolute, will be relative to the requested site and safely combine it with the currently requested url, e.g .:



private static string ExternalUrl(this ContentReference contentLink, CultureInfo language)
{
    var urlString = UrlResolver.Current.GetUrl(contentLink, language.Name, new VirtualPathArguments { ForceCanonical = true });
    if (string.IsNullOrEmpty(urlString) || HttpContext.Current == null) return urlString;

    var uri = new Uri(urlString, UriKind.RelativeOrAbsolute);
    if (uri.IsAbsoluteUri) return urlString;

    return new Uri(HttpContext.Current.Request.Url, uri).ToString();
}

      

In most cases, I would prefer not to use HttpContext.Current directly and instead pass the current request url. But in this case, I decided to use it directly to keep the example more meaningful.

+4


source


We have an argument of support on this. We want the url resolver to always return an absolute url when requesting a canonical url. This is our current solution:



public static string ExternalUrl(this PageData p, bool absoluteUrl, string languageBranch)
{
    var result = ServiceLocator.Current.GetInstance<UrlResolver>().GetUrl(
        p.ContentLink,
        languageBranch,
        new VirtualPathArguments
        {
            ContextMode = ContextMode.Default,
            ForceCanonical = absoluteUrl
        });

    // HACK: Temprorary fix until GetUrl and ForceCanonical works as expected,
    // i.e returning an absolute URL even if there is a HTTP context that matches the page 
    // site definition and host.
    if (absoluteUrl)
    {
        Uri relativeUri;

        if (Uri.TryCreate(result, UriKind.RelativeOrAbsolute, out relativeUri))
        {
            if (!relativeUri.IsAbsoluteUri)
            {
                var siteDefinitionResolver = ServiceLocator.Current.GetInstance<SiteDefinitionResolver>();
                var siteDefinition = siteDefinitionResolver.GetDefinitionForContent(p.ContentLink, true, true);
                var hosts = siteDefinition.GetHosts(p.Language, true);
                var host = hosts.FirstOrDefault(h => h.Type == HostDefinitionType.Primary) ?? hosts.FirstOrDefault(h => h.Type == HostDefinitionType.Undefined);

                var basetUri = siteDefinition.SiteUrl;

                if (host != null)
                {
                    // Try to create a new base URI from the host with the site URI scheme. Name should be a valid
                    // authority, i.e. have a port number if it differs from the URI scheme default port number.
                    Uri.TryCreate(siteDefinition.SiteUrl.Scheme + "://" + host.Name, UriKind.Absolute, out basetUri);
                }

                var absoluteUri = new Uri(basetUri, relativeUri);

                return absoluteUri.AbsoluteUri;
            }
        }
    }

    return result;
}

      

+2


source


I managed to write something in Johan and Henry :

public static string GetExternalAbsoluteFriendlyUrl(
    this ContentReference reference,
    string language)
{
    var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>();
    var friendlyUrl = urlResolver.GetUrl(reference, language);

    if (string.IsNullOrEmpty(friendlyUrl))
        return friendlyUrl;

    var uri = new Uri(friendlyUrl, UriKind.RelativeOrAbsolute);
    if (uri.IsAbsoluteUri)
        return friendlyUrl;

    if (HttpContext.Current != null)
        return new Uri(HttpContext.Current.Request.Url, uri).ToString();

    var siteDefinitionResolver =
        ServiceLocator.Current.GetInstance<SiteDefinitionResolver>();
    var siteDefinition =
        siteDefinitionResolver.GetDefinitionForContent(reference, true, true);

    return new Uri(siteDefinition.SiteUrl, friendlyUrl).ToString();
}

      

0


source


I also ran into this issue while writing a scheduled job on the multi-lingual site multihostname. To get the absolute url with the correct hostname in a non-HttpContext situation I had to combine Henrik code with Dejan code from here: https://www.dcaric.com/blog/episerver-how-to-get-external-page -url .

This is what I came up with:

public static string ExternalUrl(this ContentReference contentLink, CultureInfo language)
{
    var urlString = UrlResolver.Current.GetUrl(contentLink, language.Name, new VirtualPathArguments { ForceCanonical = true });

    var uri = new Uri(urlString, UriKind.RelativeOrAbsolute);
    if (uri.IsAbsoluteUri) return urlString;

    string externalUrl = HttpContext.Current == null
        ? UriSupport.AbsoluteUrlBySettings(urlString)
        : HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + urlString;

    return externalUrl;
}

      

0


source







All Articles