After I created a customer using the /account/ registration page, I got the newly created customer to be the current logged-in customer.
I then use the backoffice interface and - logged-in as an admin - I delete both the member and the Merchello Customer.
When I try to get back from the backoffice to the webstore interface on the first refresh of the page i get the ysod:
Server Error in '/' Application.
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 117: var member = _memberService.GetById(memberId); Line 118: Line 119: if (MerchelloConfiguration.Current.CustomerMemberTypes.Any(x => x == member.ContentTypeAlias)) Line 120: { Line 121: base.EnsureCustomerCreationAndConvertBasket(customer);
Source File: C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\CustomerContext.cs Line: 119
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.] Merchello.Web.<>c__DisplayClass9_0.<EnsureCustomerCreationAndConvertBasket>b__0(String x) in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\CustomerContext.cs:119 System.Linq.Enumerable.Any(IEnumerable`1 source, Func`2 predicate)
+146 Merchello.Web.CustomerContext.EnsureCustomerCreationAndConvertBasket(ICustomerBase customer) in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\CustomerContext.cs:119 Merchello.Web.Pluggable.CustomerContextBase.TryGetCustomer(Guid key) in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\Pluggable\CustomerContextBase.cs:277 Merchello.Web.Pluggable.CustomerContextBase.Initialize() in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\Pluggable\CustomerContextBase.cs:554 Merchello.Web.Pluggable.CustomerContextBase..ctor(IMerchelloContext merchelloContext, UmbracoContext umbracoContext) in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\Pluggable\CustomerContextBase.cs:99 Merchello.Web.CustomerContext..ctor(UmbracoContext umbracoContext) in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\CustomerContext.cs:54
[TargetInvocationException: Exception has been thrown by the target of an invocation.] Merchello.Web.Pluggable.PluggableObjectHelper.GetInstance(String configurationAlias, Object[] ctrArgValues) in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\Pluggable\PluggableObjectHelper.cs:110 Merchello.Web.Pluggable.PluggableObjectHelper.GetInstance(String configurationAlias, Object param1) in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\Pluggable\PluggableObjectHelper.cs:50 Merchello.Web.Mvc.MerchelloTemplatePage.get_CurrentCustomer() in C:\Clax\VSOW\Ajour.no\AjourCms1\Merchello.Web\Mvc\MerchelloTemplatePage.cs:32 ASP._Page_Views_Shared__Header_cshtml.Execute() in c:\Clax\VSOW\Ajour.no\AjourCms1\AjourCms1\Views\Shared\_Header.cshtml:57 System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +198 System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +105 System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +90 System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +235 System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +107 Umbraco.Core.Profiling.ProfilingView.Render(ViewContext viewContext, TextWriter writer) +113 System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection) +277 System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData) +91 System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName) +31 ASP._Page_Views_FastTrack_cshtml.Execute() in c:\Clax\VSOW\Ajour.no\AjourCms1\AjourCms1\Views\FastTrack.cshtml:15 System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +198 System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +105 System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +90 System.Web.WebPages.<>c__DisplayClass3.<RenderPageCore>b__2(TextWriter writer) +232 System.Web.WebPages.HelperResult.WriteTo(TextWriter writer) +10 System.Web.WebPages.WebPageBase.Write(HelperResult result) +80 System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body) +63 System.Web.WebPages.WebPageBase.PopContext() +237 System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +98 System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +235 System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +107 Umbraco.Core.Profiling.ProfilingView.Render(ViewContext viewContext, TextWriter writer) +113 System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
+290 System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +56 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +52 System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c()
+173 System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100 System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10 System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27 System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13 System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29 System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36 System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12 System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22 System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49 System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26 System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10 System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21 System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29 System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
+28 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+9765045 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1637.0
The exception occurs because in Merchello.Web/CustomerContext.cs, the memberId gets -1 and then the member object gets null:
protected override void EnsureCustomerCreationAndConvertBasket(ICustomerBase customer)
{
if (!customer.IsAnonymous) return;
var memberId = Convert.ToInt32(this.MembershipProviderKey(customer.Key));
var member = _memberService.GetById(memberId);
if (MerchelloConfiguration.Current.CustomerMemberTypes.Any(x => x == member.ContentTypeAlias))
{
base.EnsureCustomerCreationAndConvertBasket(customer);
}
}
I would say even further that in this case the logic that allows this to happen is in the TryGetCustomer(Guid guid) method of Merchello.Web/Pluggable/CustomerContextBase.cs:
// Check the cache for a previously retrieved customer.
// There can be many requests for the current customer during a single request.
if (customer != null)
{
CurrentCustomer = customer;
// No we need to assert whether or not the authentication status has changed
// during this request - the user either logged in or has logged out.
if (customer.IsAnonymous)
{
// We have an anonymous customer but the user is now authenticated so we may want to create an
// customer and convert the basket
if (isLoggedIn)
{
this.EnsureCustomerCreationAndConvertBasket(customer);
}
}
While this logic here makes sense for detecting an AnonymousCustomer converting into a Customer, it is also triggerred when a Customer "would convert into an AnonymousCustomer" - because deleting the MerchelloCustomer object and the related Member of a Customer should in theory be the reverse operation - but in this case is failing.
I could not find a good resolution for this yet, all i could do so far is to add the member check, instead of:
if (MerchelloConfiguration.Current.CustomerMemberTypes.Any(x => x == member.ContentTypeAlias))
now I have:
if (member!=null && MerchelloConfiguration.Current.CustomerMemberTypes.Any(x => x == member.ContentTypeAlias))
But that change is directly inside of your code in Merchello.Web/CustomerContext.cs, whereas I would very much like to have something in my project code, something like a removal or an initialization of the cached customer on member deletion in UmbracoEventHandler.cs, something like:
public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
ShipmentService.StatusChanged += ShipmentServiceStatusChanged;
SmtpNotificationGatewayMethod.Sending += SmtpNotificationOnSending;
SendGridEmailNotificationGatewayMethod.Sending += SendGridEmailNotificationOnSending;
MemberService.Created += MemberService_Created;
MemberService.Deleting += MemberService_Deleting;
}
private void MemberService_Deleting(IMemberService sender, Umbraco.Core.Events.DeleteEventArgs<IMember> e)
{
var memberService = sender;
var members = e.DeletedEntities;
var customerContext = new CustomerContext(UmbracoContext.Current);
if (MerchelloContext.HasCurrent)
{
var customerService = MerchelloContext.Current.Services.CustomerService;
foreach (var member in members)
{
var customer = customerService.GetByLoginName(member.Email);
if (customer != null && !customer.IsAnonymous && customerContext.CurrentCustomer.Key == customer.Key)
{
customerContext.Reinitialize(customer);
var customerNew = customerService.CreateAnonymousCustomerWithKey();
customerContext.Reinitialize(customerNew);
//curre
//customerContext.CurrentCustomer. = customer;
//var customerContextData = new CustomerContextData()
//{
// Key = customer.Key
//};
//MerchelloContext.Current.Cache.RequestCache.
//CacheCustomer(customer);
}
}
}
}
which doesn't look to work.
Any ideas please Rusty ? How can i fix this from outside Merchello's code ?
If you delete the member and the customer from the back office you probably don't need to start to reinitialize the CustomerContext - that should take care of itself.
However, it may have something to do with the CustomerContext caching (this will be refactored in v3.0 http://issues.merchello.com/youtrack/issue/M-1132) and/or potentially a cookie not being updated - which would depend on how you are testing. Example if you are running through as a customer and then logging in with the same browser, deleting the customer and member and going back in the same browser and looking again from a customer perspective.
Chrome for customer registration and webstore interface and IE for backoffice
IE for customer registration and webstore interface and Edge for backoffice
In both scenarios i did not logout the user from the webstore interface after registration, instead I just deleted the member and the merchello customer from the backoffice and right after that, back to the webstore i refreshed the root / page.
The issue is there in both scenarios. The exception is thrown the same as explained before.
ysod after deleting logged-in customer
Hi Rusty,
After I created a customer using the /account/ registration page, I got the newly created customer to be the current logged-in customer.
I then use the backoffice interface and - logged-in as an admin - I delete both the member and the Merchello Customer.
When I try to get back from the backoffice to the webstore interface on the first refresh of the page i get the ysod:
The exception occurs because in Merchello.Web/CustomerContext.cs, the memberId gets -1 and then the member object gets null:
I would say even further that in this case the logic that allows this to happen is in the TryGetCustomer(Guid guid) method of Merchello.Web/Pluggable/CustomerContextBase.cs:
While this logic here makes sense for detecting an AnonymousCustomer converting into a Customer, it is also triggerred when a Customer "would convert into an AnonymousCustomer" - because deleting the MerchelloCustomer object and the related Member of a Customer should in theory be the reverse operation - but in this case is failing.
I could not find a good resolution for this yet, all i could do so far is to add the member check, instead of:
now I have:
But that change is directly inside of your code in Merchello.Web/CustomerContext.cs, whereas I would very much like to have something in my project code, something like a removal or an initialization of the cached customer on member deletion in UmbracoEventHandler.cs, something like:
which doesn't look to work.
Any ideas please Rusty ? How can i fix this from outside Merchello's code ?
Hey Claudiu,
If you delete the member and the customer from the back office you probably don't need to start to reinitialize the CustomerContext - that should take care of itself.
However, it may have something to do with the CustomerContext caching (this will be refactored in v3.0 http://issues.merchello.com/youtrack/issue/M-1132) and/or potentially a cookie not being updated - which would depend on how you are testing. Example if you are running through as a customer and then logging in with the same browser, deleting the customer and member and going back in the same browser and looking again from a customer perspective.
This issue was likely introduced https://github.com/rustyswayne/Merchello/blob/merchello-dev/src/Merchello.FastTrack.Ui/App_Plugins/Merchello/config/merchello.config#L31 to make basket retention for anonymous customers configurable.
Can you verify that this issue only happens if you don't log out with the customer before you delete them and you are using the same browser?
Hi Rusty,
Thank you for your quick response.
I just checked on 2 different scenarios:
In both scenarios i did not logout the user from the webstore interface after registration, instead I just deleted the member and the merchello customer from the backoffice and right after that, back to the webstore i refreshed the root / page.
The issue is there in both scenarios. The exception is thrown the same as explained before.
Ok - that makes sense. Would you might logging this as a minor issue on https://issues.merchello.com
I don't think it's a critical issue as most customers won't be back office administrators ;-)
is working on a reply...