Server error when combining order with item promotion that sets a total redemption limit

Found in

EPiServer.Commerce 11.0.0

Fixed in

EPiServer.Commerce 11.4.0

Created

Oct 30 2017

Updated

Nov 10 2017

State

Closed, Fixed and tested


Description

Precondition: Disable all existing promotions in a Quicksilver site.

Steps to reproduce:

  1. Create a promotion: buy 2 men's shoes get 1 free (or any item promotion that have total redemption limit) and set Total redemption limit = 1 with highest priority.
  2. Create an order promotion "buy $500 get $50 for whole order".
  3. Try to add/update "Puma Red Leather Loafers Shoes" with quantity = 11 to the cart.

Expected: Add/update cart normally, and both promotions are applied.

Actual: Cannot add/update cart. Instead, you get this server error:
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 335: public IEnumerable ApplyDiscounts(ICart cart)
Line 336:

{ Line 337: return cart.ApplyDiscounts(_promotionEngine, new PromotionEngineSettings()); Line 338: }

Line 339:

Source File: C:\Episerver\QS2732\Sources\EPiServer.Reference.Commerce.Site\Features\Cart\Services\CartService.cs Line: 337

Stack Trace:

[NullReferenceException: Object reference not set to an instance of an object.]
EPiServer.Commerce.Marketing.OrderFormPriceMatrix.CalculateAndCommit(AffectedEntries item, Func`3 apply) +46
EPiServer.Commerce.Marketing.<>c_DisplayClass1_0.b_0(TAffectedObject item) +70
EPiServer.Commerce.Marketing.RewardApplicatorBase`1.ForEach(Func`2 apply, IEnumerable`1 affectedItems) +194
EPiServer.Commerce.Marketing.RewardApplicatorBase`1.Apply(RewardDescription reward, Int32 remainingRedemptions, PromotionProcessorContext processorContext) +165
EPiServer.Commerce.Marketing.PromotionEngine.Run(IOrderGroup orderGroup, PromotionEngineSettings settings) +1829
EPiServer.Commerce.Order.IOrderGroupExtensions.ApplyDiscounts(IOrderGroup orderGroup, IPromotionEngine promotionEngine, PromotionEngineSettings settings) +51
EPiServer.Reference.Commerce.Site.Features.Cart.Services.CartService.ApplyDiscounts(ICart cart) in C:\Episerver\QS2732\Sources\EPiServer.Reference.Commerce.Site\Features\Cart\Services\CartService.cs:337
EPiServer.Reference.Commerce.Site.Features.Cart.Services.CartService.ValidateCart(ICart cart) in C:\Episerver\QS2732\Sources\EPiServer.Reference.Commerce.Site\Features\Cart\Services\CartService.cs:254
EPiServer.Reference.Commerce.Site.Features.Cart.Services.CartService.LoadCart(String name) in C:\Episerver\QS2732\Sources\EPiServer.Reference.Commerce.Site\Features\Cart\Services\CartService.cs:286
EPiServer.Reference.Commerce.Site.Features.Navigation.Controllers.NavigationController.Index(IContent currentContent) in C:\Episerver\QS2732\Sources\EPiServer.Reference.Commerce.Site\Features\Navigation\Controllers\NavigationController.cs:37
lambda_method(Closure , ControllerBase , Object[] ) +118
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +228
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +34
System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +38
System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +66
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +41
System.Web.Mvc.Async.AsyncInvocationWithFilters.b__3d() +71
System.Web.Mvc.Async.<>c_DisplayClass46.b_3f() +385
System.Web.Mvc.Async.<>c_DisplayClass46.b_3f() +385
System.Web.Mvc.Async.<>c_DisplayClass46.b_3f() +385
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c_DisplayClass2b.b_1c() +38
System.Web.Mvc.Async.<>c_DisplayClass21.b_1e(IAsyncResult asyncResult) +185
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +38
System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +65
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +52
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38
System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +43
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +65
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38
System.Web.Mvc.<>c_DisplayClass4.b_3() +15
System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Func`1 func) +26
System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +1704

[HttpException (0x80004005): Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.]
System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +2321
System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) +137
System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +33
System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter) +575
System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper htmlHelper, String actionName, String controllerName) +52
ASP.Page_Views_Shared_Layout_cshtml.Execute() in c:\Episerver\QS2732\Sources\EPiServer.Reference.Commerce.Site\Views\Shared_Layout.cshtml:50
System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +252
System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +148
System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +122
System.Web.WebPages.<>c_DisplayClass3.b_2(TextWriter writer) +309
System.Web.WebPages.WebPageBase.Write(HelperResult result) +108
System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body) +89
System.Web.WebPages.WebPageBase.PopContext() +310
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +375
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +88
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +81
System.Web.Mvc.Async.<>c_DisplayClass21.b_1e(IAsyncResult asyncResult) +185
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +38
System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +65
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +52
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38
System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +43
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +65
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +607
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +134