Hi Øyvind,
I am seeing the same exceptions in my logs after installing the Marketing plugin, i would like to hear if you found a solution?
My versions:
Episerver CMS 9.12.3
Episerver Commerce 9.24.0
EPiServer.Marketing.Testing 1.0.6
My stacktrace:
EPiServer.Marketing.Testing.Web.TestHandlerInitializer: EvaluateKpis : pagehelper error - evaluating all kpis System.InvalidOperationException: ValueFactory attempted to access the Value property of this instance. at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at EPiServer.Web.Routing.PageRouteHelper.get_PageLink() at EPiServer.Marketing.Testing.Web.TestHandler.EvaluateKpis(Object sender, EventArgs e) System.InvalidOperationException: ValueFactory attempted to access the Value property of this instance. at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at EPiServer.Web.Routing.PageRouteHelper.get_PageLink() at EPiServer.Marketing.Testing.Web.TestHandler.EvaluateKpis(Object sender, EventArgs e)
/Mathias
Hi Mathias,
No I haven't found any solution for this. We are experiencing a number of issues with the Marketing.Testing package, and you can also have a look at https://world.episerver.com/Modules/Forum/Pages/Thread.aspx?id=180232 for another issue. However I'm not sure if it's related or not.
About a year later, I have this too so it doesn't seem to be fixed.
<package id="EPiServer.Marketing.KPI" version="2.5.0" targetFramework="net461" />
<package id="EPiServer.Marketing.Messaging" version="1.3.0" targetFramework="net461" />
<package id="EPiServer.Marketing.Testing" version="2.5.1" targetFramework="net461" />
Reverse engineering of EPiServer.Marketing.Testing.Web.dll indicates that the crash happens here in the Testhandler.EvaluateKpis() method:
try
{
THIS LINE ==> if (this._serviceLocator.GetInstance<IPageRouteHelper>().get_PageLink().get_ID()
== contentEventArg.get_ContentLink().get_ID())
{
this._httpContextHelper.SetItemValue("ABTestHandlerSkipKpiEval", true);
}
}
catch (Exception exception)
{
LoggerExtensions.Warning(this._logger, "EvaluateKpis : pagehelper error - evaluating all kpis", exception);
}
IPageRouteHelper is in the EPiServer.Cms.AspNet 11.3.0.0 assembly which is referenced by the EPiServer.Marketing.Testing.* assemblies. We're at 11.7.1.0 so that might be related to the problem.
We do however have assembly version redirects in our Web.config to cover cases like this:
<dependentAssembly>
<assemblyIdentity name="EPiServer.Cms.AspNet" publicKeyToken="8fe83dea738b45b7" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.7.1.0" newVersion="11.7.1.0" />
</dependentAssembly>
According to FUSLOGVW.exe logs the redirects are active and working.
Any tricks to get rid of this warning is greatly appreciated.
Without knowing the cause in this case I know I have seen that exception before and that time it was caused by a reentrance. That is the code run in the Lazy factory caused the Lazy to be evaluated again. If reentrance is the case here as well then when looking in the code for the factory method for the Lazy I can see that it is loading a content item. So then a potential cause of reentrance would be if there is a an eventhandler for IContentEvents.LoadingContent/LoadedContent that in the eventhandler used IPageRouteHelper (or IContentRouteHelper). I am not familiar with EPiServer.Marketing but it seems realistic that such ocde could exist.
Thanks for looking in to this.
Your reflections is making me a bit worried, I get this warning several times per page view so my logs are filling up. From a performance perspective I don't like getting all these exceptions either and supposedly the A/B testing is not fully functional, or it wouldn't throw like this.
So what should we do? Obviously we're not letting the A/B testing tool into the main branch of our site until we're confident it works correctly. I suppose I'll have to open a support ticket.
As earlier pointed I am not sure of the cause of this but if the cause is using IPageRouteHelper from an eventhandler to LoadingContent then a switch to IContentRouteHelper would help. IContentRouteHelper.ContentLink does not load the actual content as IPageRouteHelper.PageLink does (IPageRouteHelper is a predecessor from the time when there where only pages)
Yes, but the usage is in EPiServer.Marketing.Testing.Web.dll so I can't do much about it. Or did you have something in mind?
Yes I know that want help you. What you could test (that would verify my theory) is to intercept IPageRouteHelper and in implementation of Pagelink delegate to IContentRouteHelper.ContentLink
Hi again,
I'm not sure of how to intercept the interface, and a few attempts I did failed. However, this is the call stack when the exception occurs and it does indeed look like there is some kind of recursion going on.
mscorlib.dll!System.Lazy<EPiServer.Core.PageReference>.CreateValue() Unknown
mscorlib.dll!System.Lazy<EPiServer.Core.PageReference>.LazyInitValue() Unknown
> EPiServer.Marketing.Testing.Web.dll!EPiServer.Marketing.Testing.Web.TestHandler.EvaluateKpis(object sender = {EPiServer.Core.Internal.DefaultContentEvents}, System.EventArgs e = {EPiServer.ContentEventArgs}) Line 241 C#
EPiServer.Marketing.Testing.Web.dll!EPiServer.Marketing.Testing.Web.TestHandler.ProxyEventHandler(object sender, System.EventArgs e) Line 369 C#
EPiServer.dll!EPiServer.Core.Internal.DefaultContentEvents.RaiseContentEvent(string key, EPiServer.ContentEventArgs eventArgs = {EPiServer.ContentEventArgs}) Unknown
EPiServer.dll!EPiServer.Core.Internal.DefaultContentLoader.TryGet<EPiServer.Core.IContent>(EPiServer.Core.ContentReference contentLink, EPiServer.Core.LoaderOptions loaderOptions, out EPiServer.Core.IContent content = null) Unknown
EPiServer.dll!EPiServer.Core.Internal.DefaultContentLoader.Get<EPiServer.Core.IContent>(EPiServer.Core.ContentReference contentLink = ID = 9, WorkID = 0, ProviderName = null, EPiServer.Core.LoaderOptions loaderOptions = {EPiServer.Core.LoaderOptions}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Segments.Internal.NodeSegment.RouteDataMatch(EPiServer.Web.Routing.Segments.SegmentContext context = {EPiServer.Web.Routing.Segments.Internal.RequestSegmentContext}) Unknown
System.Core.dll!System.Linq.Enumerable.All<EPiServer.Web.Routing.Segments.ISegment>(System.Collections.Generic.IEnumerable<EPiServer.Web.Routing.Segments.ISegment> source, System.Func<EPiServer.Web.Routing.Segments.ISegment, bool> predicate = {Method = Inspecting the state of an object in the debuggee of type System.Delegate is not supported in this context.}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Internal.DefaultContentRoute.RouteSegmentContext(EPiServer.Web.Routing.Segments.SegmentContext segmentContext = {EPiServer.Web.Routing.Segments.Internal.RequestSegmentContext}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Internal.DefaultContentRoute.GetRouteData(System.Web.HttpContextBase httpContext = {System.Web.HttpContextWrapper}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Internal.DefaultContentRouteHelper.SetRouteDataFromRoute(int routeIndex = 27) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Internal.DefaultContentRouteHelper.SetRouteDataIfPageNotRouted() Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Internal.DefaultPageRouteHelper..ctor.AnonymousMethod__0() Unknown
mscorlib.dll!System.Lazy<EPiServer.Core.PageReference>.CreateValue() Unknown
mscorlib.dll!System.Lazy<EPiServer.Core.PageReference>.LazyInitValue() Unknown
EPiServer.Marketing.Testing.Web.dll!EPiServer.Marketing.Testing.Web.TestHandler.EvaluateKpis(object sender = {EPiServer.Core.Internal.DefaultContentEvents}, System.EventArgs e = {EPiServer.ContentEventArgs}) Line 241 C#
EPiServer.Marketing.Testing.Web.dll!EPiServer.Marketing.Testing.Web.TestHandler.ProxyEventHandler(object sender, System.EventArgs e) Line 369 C#
EPiServer.dll!EPiServer.Core.Internal.DefaultContentEvents.RaiseContentEvent(string key, EPiServer.ContentEventArgs eventArgs = {EPiServer.ContentEventArgs}) Unknown
EPiServer.dll!EPiServer.Core.Internal.DefaultContentLoader.TryGet<EPiServer.Core.IContent>(EPiServer.Core.ContentReference contentLink, EPiServer.Core.LoaderOptions loaderOptions, out EPiServer.Core.IContent content = null) Unknown
EPiServer.dll!EPiServer.Core.Internal.DefaultContentLoader.Get<EPiServer.Core.IContent>(EPiServer.Core.ContentReference contentLink = ID = 9, WorkID = 0, ProviderName = null, EPiServer.Core.LoaderOptions loaderOptions = {EPiServer.Core.LoaderOptions}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Segments.Internal.NodeSegment.RouteDataMatch(EPiServer.Web.Routing.Segments.SegmentContext context = {EPiServer.Web.Routing.Segments.Internal.RequestSegmentContext}) Unknown
System.Core.dll!System.Linq.Enumerable.All<EPiServer.Web.Routing.Segments.ISegment>(System.Collections.Generic.IEnumerable<EPiServer.Web.Routing.Segments.ISegment> source, System.Func<EPiServer.Web.Routing.Segments.ISegment, bool> predicate = {Method = Inspecting the state of an object in the debuggee of type System.Delegate is not supported in this context.}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Internal.DefaultContentRoute.RouteSegmentContext(EPiServer.Web.Routing.Segments.SegmentContext segmentContext = {EPiServer.Web.Routing.Segments.Internal.RequestSegmentContext}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.Internal.DefaultContentRoute.GetRouteData(System.Web.HttpContextBase httpContext = {System.Web.HttpContextWrapper}) Unknown
System.Web.dll!System.Web.Routing.RouteCollection.GetRouteData(System.Web.HttpContextBase httpContext = {System.Web.HttpContextWrapper}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Web.Routing.RouteCollectionExtensions.HandleRouteData(System.Web.Routing.RouteCollection routes, System.Web.HttpContextBase context = {System.Web.HttpContextWrapper}) Unknown
EPiServer.Cms.AspNet.dll!EPiServer.Global.DefaultDocumentHandling(object sender, System.EventArgs e) Unknown
System.Web.dll!System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() Unknown
System.Web.dll!System.Web.HttpApplication.ExecuteStepImpl(System.Web.HttpApplication.IExecutionStep step) Unknown
System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.SyncEventExecutionStep}, ref bool completedSynchronously = false) Unknown
System.Web.dll!System.Web.HttpApplication.PipelineStepManager.ResumeSteps(System.Exception error) Unknown
System.Web.dll!System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext context, System.AsyncCallback cb) Unknown
System.Web.dll!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest wr = {System.Web.Hosting.IIS7WorkerRequest}, System.Web.HttpContext context = {System.Web.HttpContxt}) Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext = 0x000000000201e3d8, System.IntPtr moduleData, int flags) Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
[Native to Managed Transition]
[Managed to Native Transition]
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
[AppDomain Transition]
Here is an article describing how to register an interceptor https://world.episerver.com/documentation/developer-guides/CMS/initialization/dependency-injection/
Hi again,
I succeeded in creating the interceptor so I created the following mapping from IPageRoutehelper to IContentRouteHelper:
public class CustomPageRouteHelper : IPageRouteHelper
{
private readonly IContentRouteHelper _contentRouteHelper
= ServiceLocator.Current.GetInstance<IContentRouteHelper>();
public string LanguageID => _contentRouteHelper.LanguageID;
public ContentReference ContentLink => _contentRouteHelper.ContentLink;
public IContent Content => _contentRouteHelper.Content;
public PageReference PageLink => new PageReference(_contentRouteHelper.ContentLink);
public PageData Page => ServiceLocator.Current.GetInstance<IContentLoader>()
.Get<PageData>(_contentRouteHelper.ContentLink);
}
Unfortunately it behaves exactly the same. The PageLink property is called recursively but this time it throws an exception in a lazy property in DefaultContentRouteHelper rather than DefaultPageRouteHelper.
The exception goes away if I add protection in my PageLink property so that it aborts if it's already in the callstack but that's obviously just for testing.
Do you have any more suggestions? I'm starting to feel that the A/B testing module is not compatible with the latest Episerver release.
When I reverse engineer EPiServer.Cms.AspNet it looks like it has differences in DefaultPageRouteHelper and DefaultContentRouteHelper when comparing 11.3.0.0 (which is referenced by the A/B testing modules) and 11.7.1.0. The introduction of Lazy<PageReference> is maybe what's causing the problems?
UPDATE: When I look again, the lazy property was already there in version 11.3.0.0, but there are minor changes in the lambda for it.
I just tested with the Alloy demo on EPiServer 11.3 and got the same error. Opened a support ticket, #150119.
Any news about this issue - it's still reproducing and creates a mess in logs!
No news as far as I know. I ended up filtering out these events from the log files...
According to the support people it "shouldn't be a problem" (or something along those lines) and I could not see a performance or stability problem for our site when using the A/B testing module so we went alog anyway.
Still does not feel very stalbe though. IMHO this either indicates a problem that should be fixed in their code, or it doesn't and then the event should not be logged.
This has been fixed in the A/B testing module (I am not sure if the fix has gone out in any version yet though). Support has is correct though that there is really now problem with the current code. What happend is that the A/B testing module was trying to access the routed content while it was actually routing (hence the re-entrance).
After installing the Marketing and ServiceAPI packages I'm suddenly getting logged a lot of the following exceptions:
Are anyone else seeing this, or know how to solve it?
All nuget packages are update to the latest version by the way. :)
- Øyvind