Sitecore LinkManager GetItemUrl。为什么这么棘手?
Sitecore LinkManager GetItemUrl. Why its so tricky?
我的任务是在网站上的 smth 发生更改时获取内容的 url。它就像 CRUD 操作日志记录(在我的例子中,我将 urls 记录到其他系统以进行进一步处理)。它应该适用于版本 6 及更高版本。
当我开始时,订阅事件似乎很简单,然后获取项目并为其生成 url。我订阅了两个事件 publish:itemProcessing(因为只有这里的项目还没有从网络数据库中删除),publish:itemProcessed(用于添加和更新).
这个事件给了我时间对象,所以看起来url很简单
var options = LinkManager.GetDefaultUrlOptions();
options.AlwaysIncludeServerUrl = true;
options.SiteResolving = true;
var url = LinkManager.GetItemUrl(item, options);
我的问题从这里开始。首先,我需要正确 url 并且与网站上生成的方式相同,但这里 url returns 我喜欢“http://domain/sitecore/content/Home.aspx”。
所以我添加了新的方法来从网站定义中找到正确的网站
private List<KeyValuePair<string, SiteContext>> GetSites()
{
return SiteManager.GetSites()
.Where(
s =>
!string.IsNullOrEmpty(s.Properties["rootPath"]) &&
!string.IsNullOrEmpty(s.Properties["startItem"]))
.Select(
d => new KeyValuePair<string, SiteContext>($"{d.Properties["rootPath"]}{d.Properties["startItem"]}",
new SiteContext(new SiteInfo(d.Properties))))
.ToList();
}
public virtual SiteContext GetSiteContext(Item item)
{
var site = _sites.LastOrDefault(s => item.Paths.FullPath.ToLower().StartsWith(s.Key.ToLower()));
return site.Value;
}
options.Site = GetSiteContext(Item item);
由于 sitecore returns "http://127.0.0.1/en.aspx"
,问题仍未解决
然后我继续阅读并了解到站点定义应该有 targetHostName(这实际上是有道理的,因为一个站点可以有多个域)但是当我现在添加 targetHostName 时 returns me other link "://targetHostName/en.aspx" 因此缺少 http|https。第二个问题是 returns 我 EN.aspx 这意味着这个页面可以访问 throw http://targetHostName/en.aspx and http://targetHostName
现在我有以下站点定义
<sites>
<site name="shell" virtualFolder="/sitecore/shell" physicalFolder="/sitecore/shell" rootPath="/sitecore/content" startItem="/home" language="en" database="core" domain="sitecore" loginPage="/sitecore/login" content="master" contentStartItem="/Home" enableWorkflow="true" enableAnalytics="false" analyticsDefinitions="content" xmlControlPage="/sitecore/shell/default.aspx" browserTitle="Sitecore" htmlCacheSize="2MB" registryCacheSize="3MB" viewStateCacheSize="200KB" xslCacheSize="5MB" />
<site name="login" virtualFolder="/sitecore/login" physicalFolder="/sitecore/login" enableAnalytics="false" database="core" domain="sitecore" disableXmlControls="true" />
<site name="admin" virtualFolder="/sitecore/admin" physicalFolder="/sitecore/admin" enableAnalytics="false" enableWorkflow="true" domain="sitecore" loginPage="/sitecore/admin/login.aspx" />
<site name="service" virtualFolder="/sitecore/service" physicalFolder="/sitecore/service" />
<site name="modules_shell" virtualFolder="/sitecore modules/shell" physicalFolder="/sitecore modules/shell" rootPath="/sitecore/content" startItem="/home" language="en" database="core" domain="sitecore" content="master" enableAnalytics="false" enableWorkflow="true" />
<site name="modules_website" virtualFolder="/sitecore modules/web" physicalFolder="/sitecore modules/web" rootPath="/sitecore/content" startItem="/home" language="en" database="web" domain="extranet" allowDebug="true" cacheHtml="true" />
<site name="website" hostName="sitecore6.target|sitecore6.local" targetHostName="sitecore6.target" schema="http" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/home" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" />
<site name="scheduler" enableAnalytics="false" domain="sitecore" />
<site name="system" enableAnalytics="false" domain="sitecore" />
<site name="publisher" domain="sitecore" enableAnalytics="false" enableWorkflow="true" />
</sites>
和link管理员设置
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>
问题的发生是因为您在哪里生成 link。当您将 AlwaysIncludeServerUrl
选项设置为 true 时,Sitecore 将使用当前 Sitecore.Context.Site
信息来计算服务器 Url.
要设置 http 或 https 部分,您需要在站点定义中添加一个名为 scheme
的属性 - 我认为您只是打错了字,因为您有一个名为 schema
的属性:
<sites>
<site name="website" hostName="sitecore6.target|sitecore6.local" targetHostName="sitecore6.target" scheme="http" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/home" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" />
</sites>
在发布活动期间,Context.Site
将是 shell
网站。因此它不会为您的 website
定义选择 targetHostName
。
要强制执行此操作,您需要使用 SiteContextSwitcher
var website = Sitecore.Configuration.Factory.GetSite("website");
using (new SiteContextSwitcher(website))
{
var options = LinkManager.GetDefaultUrlOptions();
options.AlwaysIncludeServerUrl = true;
options.SiteResolving = true;
var url = LinkManager.GetItemUrl(item, options);
}
然后 Url 将使用网站的 targetHostName
生成,并且应该生成您期望的方式。
最后一点 - 最佳做法是通过包含文件修补新站点定义,而不是编辑主 Sitecore 配置。检查你的 include 文件夹,里面应该有一个 SiteDefinition.config.example
文件。它向您展示了如何操作。
我的任务是在网站上的 smth 发生更改时获取内容的 url。它就像 CRUD 操作日志记录(在我的例子中,我将 urls 记录到其他系统以进行进一步处理)。它应该适用于版本 6 及更高版本。
当我开始时,订阅事件似乎很简单,然后获取项目并为其生成 url。我订阅了两个事件 publish:itemProcessing(因为只有这里的项目还没有从网络数据库中删除),publish:itemProcessed(用于添加和更新).
这个事件给了我时间对象,所以看起来url很简单
var options = LinkManager.GetDefaultUrlOptions();
options.AlwaysIncludeServerUrl = true;
options.SiteResolving = true;
var url = LinkManager.GetItemUrl(item, options);
我的问题从这里开始。首先,我需要正确 url 并且与网站上生成的方式相同,但这里 url returns 我喜欢“http://domain/sitecore/content/Home.aspx”。
所以我添加了新的方法来从网站定义中找到正确的网站
private List<KeyValuePair<string, SiteContext>> GetSites()
{
return SiteManager.GetSites()
.Where(
s =>
!string.IsNullOrEmpty(s.Properties["rootPath"]) &&
!string.IsNullOrEmpty(s.Properties["startItem"]))
.Select(
d => new KeyValuePair<string, SiteContext>($"{d.Properties["rootPath"]}{d.Properties["startItem"]}",
new SiteContext(new SiteInfo(d.Properties))))
.ToList();
}
public virtual SiteContext GetSiteContext(Item item)
{
var site = _sites.LastOrDefault(s => item.Paths.FullPath.ToLower().StartsWith(s.Key.ToLower()));
return site.Value;
}
options.Site = GetSiteContext(Item item);
由于 sitecore returns "http://127.0.0.1/en.aspx"
,问题仍未解决然后我继续阅读并了解到站点定义应该有 targetHostName(这实际上是有道理的,因为一个站点可以有多个域)但是当我现在添加 targetHostName 时 returns me other link "://targetHostName/en.aspx" 因此缺少 http|https。第二个问题是 returns 我 EN.aspx 这意味着这个页面可以访问 throw http://targetHostName/en.aspx and http://targetHostName
现在我有以下站点定义
<sites>
<site name="shell" virtualFolder="/sitecore/shell" physicalFolder="/sitecore/shell" rootPath="/sitecore/content" startItem="/home" language="en" database="core" domain="sitecore" loginPage="/sitecore/login" content="master" contentStartItem="/Home" enableWorkflow="true" enableAnalytics="false" analyticsDefinitions="content" xmlControlPage="/sitecore/shell/default.aspx" browserTitle="Sitecore" htmlCacheSize="2MB" registryCacheSize="3MB" viewStateCacheSize="200KB" xslCacheSize="5MB" />
<site name="login" virtualFolder="/sitecore/login" physicalFolder="/sitecore/login" enableAnalytics="false" database="core" domain="sitecore" disableXmlControls="true" />
<site name="admin" virtualFolder="/sitecore/admin" physicalFolder="/sitecore/admin" enableAnalytics="false" enableWorkflow="true" domain="sitecore" loginPage="/sitecore/admin/login.aspx" />
<site name="service" virtualFolder="/sitecore/service" physicalFolder="/sitecore/service" />
<site name="modules_shell" virtualFolder="/sitecore modules/shell" physicalFolder="/sitecore modules/shell" rootPath="/sitecore/content" startItem="/home" language="en" database="core" domain="sitecore" content="master" enableAnalytics="false" enableWorkflow="true" />
<site name="modules_website" virtualFolder="/sitecore modules/web" physicalFolder="/sitecore modules/web" rootPath="/sitecore/content" startItem="/home" language="en" database="web" domain="extranet" allowDebug="true" cacheHtml="true" />
<site name="website" hostName="sitecore6.target|sitecore6.local" targetHostName="sitecore6.target" schema="http" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/home" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" />
<site name="scheduler" enableAnalytics="false" domain="sitecore" />
<site name="system" enableAnalytics="false" domain="sitecore" />
<site name="publisher" domain="sitecore" enableAnalytics="false" enableWorkflow="true" />
</sites>
和link管理员设置
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>
问题的发生是因为您在哪里生成 link。当您将 AlwaysIncludeServerUrl
选项设置为 true 时,Sitecore 将使用当前 Sitecore.Context.Site
信息来计算服务器 Url.
要设置 http 或 https 部分,您需要在站点定义中添加一个名为 scheme
的属性 - 我认为您只是打错了字,因为您有一个名为 schema
的属性:
<sites>
<site name="website" hostName="sitecore6.target|sitecore6.local" targetHostName="sitecore6.target" scheme="http" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/home" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" />
</sites>
在发布活动期间,Context.Site
将是 shell
网站。因此它不会为您的 website
定义选择 targetHostName
。
要强制执行此操作,您需要使用 SiteContextSwitcher
var website = Sitecore.Configuration.Factory.GetSite("website");
using (new SiteContextSwitcher(website))
{
var options = LinkManager.GetDefaultUrlOptions();
options.AlwaysIncludeServerUrl = true;
options.SiteResolving = true;
var url = LinkManager.GetItemUrl(item, options);
}
然后 Url 将使用网站的 targetHostName
生成,并且应该生成您期望的方式。
最后一点 - 最佳做法是通过包含文件修补新站点定义,而不是编辑主 Sitecore 配置。检查你的 include 文件夹,里面应该有一个 SiteDefinition.config.example
文件。它向您展示了如何操作。