Error "Index was outside the bounds of the array." while loading purchase order

Vote:
 

We added new custom properties to the PurchaseOrder. The new properties of type of "DictionaryMultiValue" and "DictionarySingleValue". Now in our code when we convert cart to order it works perfectly but when we try to load the purchase order it throw exception as below:

Index was outside the bounds of the array.

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.IndexOutOfRangeException: Index was outside the bounds of the array.

Source Error: 

Line 138:
Line 139:            var orderReference = orderRepository.SaveAsPurchaseOrder(cart);
Line 140:            var purchaseOrder = orderRepository.Load<IPurchaseOrder>(orderReference.OrderGroupId);
Line 141:
Line 142:            purchaseOrder.Properties[MetaDataPlus.MetaFields.UTSOrderStatus] = new[] { new MetaDictionaryItem("Awaiting Voucher Confirmation") };


Source File: C:\projects\S60\UTS\Episerver.UTS.Web\UTS\Features\CheckoutPage\Services\CheckoutService.cs    Line: 140 

Stack Trace: 

[IndexOutOfRangeException: Index was outside the bounds of the array.]
   Mediachase.MetaDataPlus.MetaObject.CloneMetaFieldReferenceTypes(Hashtable original, Hashtable clone) +412
   Mediachase.MetaDataPlus.MetaObject.DeepCloneImplementation() +101
   Mediachase.Commerce.Storage.MetaStorageBase.DeepCloneImplementation() +14
   Mediachase.Commerce.Orders.OrderGroup.DeepCloneImplementation() +35
   Mediachase.Commerce.Orders.PurchaseOrder.DeepCloneImplementation() +33
   Mediachase.Commerce.Orders.PurchaseOrder.Mediachase.Commerce.Orders.Internal.IDeepCloneable.DeepClone() +10
   EPiServer.Commerce.Order.Internal.DefaultOrderRepository.ReadThrough(Int32 orderGroupId, Func`1 load) +404
   EPiServer.Commerce.Order.Internal.DefaultOrderRepository.Load(Int32 orderGroupId, Type orderType) +179
   EPiServer.Commerce.Order.Internal.DefaultOrderRepository.Load(Int32 orderGroupId) +83
   EPiServer.Reference.Commerce.Site.Features.Checkout.Services.CheckoutService.CreateOrder(Int32 cartid, Dictionary`2 keys) in C:\projects\S60\UTS\Episerver.UTS.Web\UTS\Features\CheckoutPage\Services\CheckoutService.cs:140
   EPiServer.UTS.Web.UTS.Features.Checkout.CheckoutPageController.Callback(CheckoutPage currentPage) in C:\projects\S60\UTS\Episerver.UTS.Web\UTS\Features\CheckoutPage\CheckoutPageController.cs:137
   lambda_method(Closure , ControllerBase , Object[] ) +104
   System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +157
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
   System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +22
   System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +50
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +228
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +228
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +228
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +228
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +228
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +228
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +228
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +26
   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() +576
   System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +132
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +163

After digging down I found the code of Mediachase.MetaDataPlus.MetaObject.CloneMetaFieldReferenceTypes as below:

 /// <param name="clone">The clone.</param>
    protected void CloneMetaFieldReferenceTypes(Hashtable original, Hashtable clone)
    {
      foreach (object key in (IEnumerable) original.Keys)
      {
        object obj = original[key];
        if (obj is MetaDictionaryItem)
        {
          clone[key] = (object) ((MetaDictionaryItem) obj).DeepClone();
        }
        else
        {
          MetaDictionaryItem[] metaDictionaryItemArray1 = obj as MetaDictionaryItem[];
          if (metaDictionaryItemArray1 != null)
          {
            MetaDictionaryItem[] metaDictionaryItemArray2 = new MetaDictionaryItem[metaDictionaryItemArray1.Length];
            int index = metaDictionaryItemArray1.Length - 1;
            do
            {
              metaDictionaryItemArray2[index] = metaDictionaryItemArray1[index].DeepClone();
            }
            while (index-- > 0);
            clone[key] = (object) metaDictionaryItemArray2;
          }
          else if (obj is MetaFile)
            clone[key] = (object) ((MetaFile) obj).DeepClone();
          else if (obj is MetaStringDictionary)
            clone[key] = (object) ((MetaStringDictionary) obj).DeepClone();
          else if (obj is MetaObject)
            clone[key] = ((MetaObject) obj).DeepCloneImplementation();
        }
      }
    }

Seems like below like causing the error:

int index = metaDictionaryItemArray1.Length - 1;
            do
            {
              metaDictionaryItemArray2[index] = metaDictionaryItemArray1[index].DeepClone();
            }
            while (index-- > 0);

as if the metaDictionaryItemArray1.Length is "0" then it throws an exception. Can anyone help with this? Appreciate help!

Aria

#205541
Jul 16, 2019 9:58
Vote:
 

When your metaDictionaryItemArray1.Length is "0" then the

metaDictionaryItemArray2[-1]

and therefore it will throw the exception as you are getting now. Also, your loop is do..while() that will execute the statements inside it at least once even while condition fails.

Read about the array behavour for more info.

Thanks

#205602
Jul 17, 2019 13:38
Vote:
 

You r 100% right .. the point is that is Commerce code bit mine ;) I found the issue and reported here 

#205603
Jul 17, 2019 13:42
Praful Jangid - Jul 17, 2019 15:43
I see, my bad, I just focused on last line you mentioned that error causing lines :D
Vote:
 

Thanks for your investigation - much appreciated. I have filed a bug for Commerce team. 

#205615
Jul 17, 2019 14:35
Vote:
 

Tnx buddy .. 

#205619
Jul 17, 2019 15:06