I have a custom pipeline processor inserted after ItemResolver in which I overwrite the current context item with a new item selected by the content editor from a droplink.
If I go to that dynamic item via a normal request through my website and through my processor and i change my context item, it will stil render the same item:
public override void Process(HttpRequestArgs args)
{
// some code
Context.Item = dropLink.TargetItem;
}
Strangely, if I issue a request via the item API, sitecore changes the item successfully
//api call
Context.Item = Context.Database.SelectSingleItem("fast:/sitecore/content/mysite/dynamicitem");
Here is my config file:
<pipelines>
<httpRequestBegin>
<processor patch:after="* @type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" type="MyDll.Web.Pipelines.LandingPageResolver,MyDll.Web" />
</httpRequestBegin>
</pipelines>
Since you are using MVC the item is resolved (again) using a different set of pipelines, so you need to patch into there instead.
The GetFromRouteUrl
processor in the mvc.getPageItem
pipeline sets args.Result
to the item matching the requested URL which is then eventually set to Context.Item
, so it essentially resets the item back to the "correct" item based on the URL and that overwrites the changes you made earlier.
You need to add a need processor to the mvc.getPageItem
with some logic to check if the context item has already been resolved.
Update your code in the ItemResolver and store a boolean to indicate that you have already resolved using custom logic, this saves having to run the resolving logic twice:
public override void Process(HttpRequestArgs args)
{
// some code
Context.Item = dropLink.TargetItem;
Context.Items["custom::ItemResolved"] = true;
}
Create a new Class that checks if your custom logic has already resolved the item:
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;
}
}
And then patch this in:
<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>
The pipeline immediately after is GetFromFromUrl()
which would normally set args.Result
by re-resolving the Item. By setting it back to Context.Item that processor will break out early and leave your previous logic alone.
You can find more details about MVC and Pipelines in the documentation.