Reputation: 6528
I am trying to setup DMS on Sitecore 7.2 using MVC. I am able to set personalization rules via the Page Editor but the rules do not run when I view the page as a normal users. I have checked the following:
We have narrowed the problem down to Controller Renderings, our solution works for View Renderings. Has anyone made personalisation work with Controller Renderings? We have replicated this problem in a vanilla SC instance.
Here is a video of our problem:
http://screencast.com/t/1nGwUINJLZO
This is a screenshot of my controller code:
And the components on the page:
We have tried to setup a test with the minimum amount of interference.
Upvotes: 2
Views: 2318
Reputation: 6528
The problem was caused by the Sitecore.Forms.Mvc.config file. I hadn't mentioned WFFM in my original question because I assumed that it wouldn't affect DMS.
When you enable DMS without WFFM the getRenderer pipeline looks like this:
<mvc.getRenderer patch:source="Glass.Mapper.Sc.Mvc.config">
<processor type="Sitecore.Mvc.Analytics.Pipelines.Response.GetRenderer.CustomizeRendering, Sitecore.Mvc.Analytics" patch:source="Sitecore.MvcAnalytics.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetViewRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetItemRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetXsltRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetControllerRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetMethodRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetUrlRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetDefaultRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
</mvc.getRenderer>
You can see here that the first entry is a processor that analytics inserts to control personalisation. If we now enable the Sitecore.Forms.Mvc.config this pipeline changes to this:
<mvc.getRenderer patch:source="Glass.Mapper.Sc.Mvc.config">
<processor type="Sitecore.Forms.Mvc.Pipelines.GetFormControllerRenderer, Sitecore.Forms.Mvc" patch:source="Sitecore.Forms.Mvc.config"/>
<processor type="Sitecore.Mvc.Analytics.Pipelines.Response.GetRenderer.CustomizeRendering, Sitecore.Mvc.Analytics" patch:source="Sitecore.MvcAnalytics.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetViewRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetItemRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetXsltRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetControllerRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetMethodRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetUrlRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.Response.GetRenderer.GetDefaultRenderer, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
</mvc.getRenderer>
Notice that the WFFM Forms MVC entry inserts itself at the start of the pipeline. This causes problems because it returns a rendering:
protected override Renderer GetRenderer(Rendering rendering, GetRendererArgs args)
{
if (args.Rendering.RenderingItem.ID != IDs.FormMvcInterpreterID)
return base.GetRenderer(rendering, args);
Tuple<string, string> controllerAndAction = this.GetControllerAndAction(rendering, args);
if (controllerAndAction == null)
return (Renderer) null;
string str1 = controllerAndAction.Item1;
string str2 = controllerAndAction.Item2;
FormControllerRenderer controllerRenderer = new FormControllerRenderer();
controllerRenderer.ControllerName = str1;
controllerRenderer.ActionName = str2;
return (Renderer) controllerRenderer;
}
The CustomiseRendering processor then does nothing because there is a returned result, therefore no personalization is performed:
public override void Process(GetRendererArgs args)
{
Assert.ArgumentNotNull((object) args, "args");
if (args.Result != null || args.Rendering == null || string.IsNullOrEmpty(args.Rendering["RenderingXml"]))
return;
CustomizeRenderingArgs args1 = new CustomizeRenderingArgs(args.Rendering);
args.Result = PipelineService.Get().RunPipeline<CustomizeRenderingArgs, Renderer>("mvc.customizeRendering", args1, (Func<CustomizeRenderingArgs, Renderer>) (pipelineArgs => pipelineArgs.Renderer));
}
This is caused by the order that the MVC, Web Forms and Analytics configs are loaded. By default they are loaded in this order:
This is the correct order.
The solution is to rename the Sitecore.Forms.Mvc.Config to y.Sitecore.Forms.Mvc.config to force it to be loaded last.
Upvotes: 2
Reputation: 6105
I don't see how it can be specific to controller renderings to be honest. In Sitecore MVC controller and view renderings alike follow the same pipeline path. More specifically, a variation based on A/B (aka MVT) test or personalization rules is picked as a first step in mvc.getRenderer
pipeline. You should have
Sitecore.Mvc.Analytics.Pipelines.Response.GetRenderer.CustomizeRendering
in there coming from Sitecore.MvcAnalytics.config
. When it runs it will trigger mvc.customizeRendering
. I guess what I am saying is - Personalization happens before a particular renderer is picked based on your rendering's type. You may want to look at Sitecore.Mvc.Analytics.Pipelines.Response.CustomizeRendering.Personalize
in Sitecore.Mvc.Analytics
to see how exactly Sitecore applies your personalization rules.
I know I am not answering your question per se but here's what I would do myself:
Rendering
object on which you set .Renderer
manually, not monkey patching MVC contexts, etc.)__Renderings
field in the published item (personalization doesn't run in Preview
, only runs when PageMode.IsNormal
).renderRendering
pipeline when you return from your controller. If you wrap it with RenderingView
, for example, it would run through its own pipeline and would have its own RenderingContext
and its own Rendering
object. Personalization will change the datasource on your controller rendering object and your @Html.Sitecore().Field()
may be talking to a different Rendering.Item
than you need (log your Rendering.Item
in your controller and do the same in your razor to see what's going on). I blogged about some of it last week (http://jockstothecore.com/sitecore-mvc-item-maze/) and you will probably see the rendering pipelines sequence if you Debug in Page Editor. Upvotes: 1
Reputation: 1
I can not get the @Html.Sitecore().VisitorIdentification() to work. We just put the
<sc:visitoridentification runat="server" />
before the
</head>
Have you looked at your source to see if @Html.Sitecore().VisitorIdentification() includes it?
Upvotes: 0