无需重定向即可更改 sitecore 项目
Change sitecore item without redirect
我在 ItemResolver 之后插入了一个自定义管道处理器,我在其中用内容编辑器从下拉链接中选择的新项目覆盖当前上下文项目。
如果我通过我的网站和我的处理器通过正常请求转到该动态项目,并且我更改了我的上下文项目,它仍然会呈现相同的项目:
public override void Process(HttpRequestArgs args)
{
// some code
Context.Item = dropLink.TargetItem;
}
奇怪的是,如果我通过项目 API 发出请求,sitecore 会成功更改项目
//api call
Context.Item = Context.Database.SelectSingleItem("fast:/sitecore/content/mysite/dynamicitem");
这是我的配置文件:
<pipelines>
<httpRequestBegin>
<processor patch:after="* @type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" type="MyDll.Web.Pipelines.LandingPageResolver,MyDll.Web" />
</httpRequestBegin>
</pipelines>
由于您使用的是 MVC,因此使用一组不同的管道(再次)解决了该项目,因此您需要修补到那里。
mvc.getPageItem
管道中的 GetFromRouteUrl
处理器将 args.Result
设置为与请求的 URL 匹配的项,然后最终设置为 Context.Item
,因此它实质上将项目重置回基于 URL 的 "correct" 项目,并覆盖您之前所做的更改。
您需要向 mvc.getPageItem
添加一个需求处理器,并使用一些逻辑来检查上下文项是否已被解析。
在 ItemResolver 中更新您的代码并存储一个布尔值以指示您已经使用自定义逻辑解析,这样就不必 运行 解析逻辑两次:
public override void Process(HttpRequestArgs args)
{
// some code
Context.Item = dropLink.TargetItem;
Context.Items["custom::ItemResolved"] = true;
}
创建一个新的 Class 来检查您的自定义逻辑是否已经解决了该项目:
public class CheckItemResolved: GetPageItemProcessor
{
public override void Process(GetPageItemArgs args)
{
if (args.Result == null)
{
var resolved = Sitecore.Context.Items["custom::ItemResolved"];
if (MainUtil.GetBool(resolved, false))
{
// item has previously been resolved
args.Result = Sitecore.Context.Item;
}
}
return;
}
}
然后将其修补到:
<pipelines>
<mvc.getPageItem>
<processor type="MyProject.Custom.Pipelines.CheckItemResolved, MyProject.Custom"
patch:before="*[@type='Sitecore.Mvc.Pipelines.Response.GetPageItem.GetFromRouteUrl, Sitecore.Mvc']" />
</mvc.getPageItem>
</pipelines>
紧随其后的管道是 GetFromFromUrl()
,通常会通过重新解析项目来设置 args.Result
。通过将其设置回 Context.Item,该处理器将提前中断并保留您之前的逻辑。
您可以找到有关 MVC and Pipelines in the documentation 的更多详细信息。
我在 ItemResolver 之后插入了一个自定义管道处理器,我在其中用内容编辑器从下拉链接中选择的新项目覆盖当前上下文项目。
如果我通过我的网站和我的处理器通过正常请求转到该动态项目,并且我更改了我的上下文项目,它仍然会呈现相同的项目:
public override void Process(HttpRequestArgs args)
{
// some code
Context.Item = dropLink.TargetItem;
}
奇怪的是,如果我通过项目 API 发出请求,sitecore 会成功更改项目
//api call
Context.Item = Context.Database.SelectSingleItem("fast:/sitecore/content/mysite/dynamicitem");
这是我的配置文件:
<pipelines>
<httpRequestBegin>
<processor patch:after="* @type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" type="MyDll.Web.Pipelines.LandingPageResolver,MyDll.Web" />
</httpRequestBegin>
</pipelines>
由于您使用的是 MVC,因此使用一组不同的管道(再次)解决了该项目,因此您需要修补到那里。
mvc.getPageItem
管道中的 GetFromRouteUrl
处理器将 args.Result
设置为与请求的 URL 匹配的项,然后最终设置为 Context.Item
,因此它实质上将项目重置回基于 URL 的 "correct" 项目,并覆盖您之前所做的更改。
您需要向 mvc.getPageItem
添加一个需求处理器,并使用一些逻辑来检查上下文项是否已被解析。
在 ItemResolver 中更新您的代码并存储一个布尔值以指示您已经使用自定义逻辑解析,这样就不必 运行 解析逻辑两次:
public override void Process(HttpRequestArgs args)
{
// some code
Context.Item = dropLink.TargetItem;
Context.Items["custom::ItemResolved"] = true;
}
创建一个新的 Class 来检查您的自定义逻辑是否已经解决了该项目:
public class CheckItemResolved: GetPageItemProcessor
{
public override void Process(GetPageItemArgs args)
{
if (args.Result == null)
{
var resolved = Sitecore.Context.Items["custom::ItemResolved"];
if (MainUtil.GetBool(resolved, false))
{
// item has previously been resolved
args.Result = Sitecore.Context.Item;
}
}
return;
}
}
然后将其修补到:
<pipelines>
<mvc.getPageItem>
<processor type="MyProject.Custom.Pipelines.CheckItemResolved, MyProject.Custom"
patch:before="*[@type='Sitecore.Mvc.Pipelines.Response.GetPageItem.GetFromRouteUrl, Sitecore.Mvc']" />
</mvc.getPageItem>
</pipelines>
紧随其后的管道是 GetFromFromUrl()
,通常会通过重新解析项目来设置 args.Result
。通过将其设置回 Context.Item,该处理器将提前中断并保留您之前的逻辑。
您可以找到有关 MVC and Pipelines in the documentation 的更多详细信息。