4

我的“管理网站”面板中有以下设置

一般网址设置为alloy.com

合金.no设置为没有文化

合金.se设置为sv文化

合金网是为文化而设

在我的代码中,我想为给定页面获取给定语言的友好外部 url。因此,对于搜索页面,我想获得所有语言的绝对友好 url。

我使用以下代码获取页面的友好 url(在Anders G. Nordby 博客上找到):

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;

如果我将使用alloy.com网页并在我的自定义代码中生成友好的 url,这很简单。

  • -合金.no/ søk
  • se-alloy.se/sök _ _
  • zh-alloy.com/search _ _

但是当我使用alloy.no进入编辑模式时,我会尝试生成地址,因为没有我得到合金。com /søk当它应该是合金时。没有/søk

我发现如果我使用alloy.no进入编辑模式,代码:

urlResolver.GetUrl(reference, language)

仅返回/søk和代码

UriSupport.AbsoluteUrlBySettings(builder.ToString())

添加通用 URL (alloy.com) 而不是alloy.no。

如何改进此代码以在不同文化中为页面采用正确的主机名?

4

4 回答 4

4

UrlResolver 的 GetUrl 方法将根据当前请求上下文返回指向相对或绝对页面的 URL。如果页面位于当前站点中,则 URL 将是相对的,如果在另一个站点中或在请求之外进行调用,则 URL 将是绝对的。

如果您使用的是 EPiServer.CMS.Core 8.0 或更高版本,还支持将一个站点标识为主站点。此更新还可以通过在 VirtualPathArguments 参数上设置 ForceCanonical 标志来明确请求 URL 应指向主站点。如果未设置该标志,它将首选当前站点 URL 而不是主站点(假设请求的内容位于当前站点上)。

因此,考虑到这一点,您可以假设返回的 URL(如果不是绝对的)将与当前请求的站点相关,并将其与当前请求的 URL 安全地结合起来,例如:

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();
}

在大多数情况下,我可能不希望直接使用 HttpContext.Current 而是传入当前请求 URL。但在这种情况下,我选择直接使用它来使示例更加包含。

于 2015-04-29T04:48:50.430 回答
3

我们有一个关于此的支持案例。我们希望 url 解析器在请求规范 url 时始终返回绝对 url。这是我们目前的解决方案:

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's 
    // 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's URI scheme. Name should be a valid
                    // authority, i.e. have a port number if it differs from the URI scheme's 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;
}
于 2015-04-27T16:46:30.270 回答
1

在编写在多语言、多主机名站点上运行的计划作业时,我也遇到了这个问题。为了在没有 HttpContext 的情况下获得具有正确主机名的绝对 url,我必须将 Henrik 的代码与 Dejan 的代码从这里结合起来:https ://www.dcaric.com/blog/episerver-how-to-get-external -页面网址

这就是我想出的:

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;
}
于 2017-05-29T13:12:14.960 回答
0

我已经设法根据Johan & 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();
}
于 2015-04-28T10:53:18.387 回答