Developer forum

Forum » Ecommerce - Standard features » Bug: Error when adding a new RMA to an order with a Fixed OrderLine

Bug: Error when adding a new RMA to an order with a Fixed OrderLine

Alexander P.
Reply

I don't know if this has been already reported, but I'm posting this, in case it hasn't been.

The Problem:

When I try to Register a new RMA ( Register new RMA in Ecom) on an Order, which has a Fixed OrderLine, the following error occurs:

Server Error in '/' Application.


The given key was not present in the dictionary.

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.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.

Source Error:

 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.


Stack Trace:
 

[KeyNotFoundException: The given key was not present in the dictionary.]
   System.Collections.Generic.Dictionary`2.get_Item(TKey key) +11007725
   Dynamicweb.Admin.EcomRma_Edit.BuildOrderLineSelector() +720
   Dynamicweb.Admin.EcomRma_Edit.BuildContent() +1630
   Dynamicweb.Admin.EcomRma_Edit.Page_Load(Object sender, EventArgs e) +55
   System.Web.UI.Control.OnLoad(EventArgs e) +92
   System.Web.UI.Control.LoadRecursive() +54
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772

 


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34212

Where:

The error happens here (This is a decompiled version of the method in Dynamicweb.Admin.dll - i have added comments):

// Dynamicweb.Admin.EcomRma_Edit
private void BuildOrderLineSelector()
{
    System.Collections.Generic.Dictionary<string, int> dictionary = new System.Collections.Generic.Dictionary<string, int>();
    if (this._rma.IsNew)
    {
        ListColumn listColumn = new ListColumn();
        listColumn.Name = "";
        listColumn.TranslateName = false;
        listColumn.Width = 20;
        this.OrderlineList.Columns.Add(listColumn);
        dictionary = this._newOrderLineListColumns;
    }
    else
    {
        dictionary = this._orderLineListColumns;
    }
    foreach (string current in dictionary.Keys)
    {
        ListColumn listColumn2 = new ListColumn();
        listColumn2.TranslateName = true;
        listColumn2.Name = current;
        if (dictionary[current] > 0)
        {
            listColumn2.Width = dictionary[current];
        }
        this.OrderlineList.Columns.Add(listColumn2);
    }
    ReturnMerchandiseAuthorizationCollection rmasByOrderId = ReturnMerchandiseAuthorization.GetRmasByOrderId(this._order.ID);
    if (this._rma.IsNew)
    {
        System.Collections.Generic.List<ListRow> list = new System.Collections.Generic.List<ListRow>();
        int num = 0;
       
        // 1. This (availableOrderLines) should be a superset or equal to this._order.ProductOrderLines
        System.Collections.Generic.Dictionary<string, int> availableOrderLines = ReturnMerchandiseAuthorization.GetAvailableOrderLines(this._order);
        
        // 2. This._order.ProductOrderLines should be a subset or equal to availableOrderLines
        foreach (OrderLine current2 in this._order.ProductOrderLines)
        {
            bool flag = availableOrderLines[current2.ID] > 0; // 3. And this is the reason why (The error happens here)
            if (flag)
            {
                num++;
            }
            if (flag)
            {
                System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
                int num2 = availableOrderLines[current2.ID]; // 3. Same as above
                for (int i = 1; i <= num2; i++)
                {
                    stringBuilder.AppendFormat("<option id=\"{0}\" value=\"{0}\">{0}</option>", i);
                }
                ListRow listRow = new ListRow();
                listRow.ItemID = current2.ID;
                listRow.AddColumn(string.Format("<input type=\"checkbox\" name=\"RmaOrderLines_{2}\" id=\"RmaOrderLines_{2}\" value=\"{0}\" style=\"align: center;\"{1} onClick=\"showSerialNumberRows('RmaOrderLines_{2}',document.getElementById('SerialNumber_{0}').value)\" />", current2.ID, (flag ? "" : " disabled=\"disabled\""), current2.ID));
                listRow.AddColumn(current2.ProductNumber);
                listRow.AddColumn(current2.ProductName);
                listRow.AddColumn(availableOrderLines[current2.ID]); // 3. Same as above
                listRow.AddColumn(string.Format("<select name=\"SerialNumber_{0}\" id=\"SerialNumber_{0}\"  class=\"NewUIinput\" style=\"width: 100px;\" onChange=\"showSerialNumberRows('RmaOrderLines_{0}',document.getElementById('SerialNumber_{0}').value)\"{2} >{1}</select>", current2.ID, stringBuilder.ToString(), (flag ? "" : " disabled=\"disabled\"")));
                this.OrderlineList.AddRow(listRow);
                int arg_24A_0 = 1;
                int num3 = availableOrderLines[current2.ID]; // 3. Same as above
                for (int j = arg_24A_0; j <= num3; j++)
                {
                    ListRow listRow2 = new ListRow();
                    listRow2.AddColumn("");
                    listRow2.AddColumn("<img src=\"/Admin/Images/DoubleArrowRight.gif\" style=\"vertical-align: middle;\">" + Translate.Translate("Serial number", 0));
                    listRow2.AddColumn(string.Format("<input type=\"text\" name=\"SerialNumber_{0}-{1}\" id=\"SerialNumber_{0}-{1}\"  class=\"NewUIinput SerialNumberInputBoxWidth\" />", current2.ID, j.ToString()));
                    listRow2.AddColumn("");
                    listRow2.AddColumn("");
                    listRow2.AddClass("ClassHidden");
                    listRow2.AddClass("RmaOrderLines_" + current2.ID + "_" + j.ToString());
                    listRow2.AddClass("RmaOrderLines_" + current2.ID);
                    this.OrderlineList.AddRow(listRow2);
                }
            }
            int num4 = System.Math.Max(availableOrderLines[current2.ID], System.Convert.ToInt32(current2.Quantity)) - System.Math.Min(availableOrderLines[current2.ID], System.Convert.ToInt32(current2.Quantity)); // 3. Same as above
            if (num4 > 0)
            {
                int num5 = num4 - 1;
                for (int k = 0; k <= num5; k++)
                {
                    ListRow listRow3 = new ListRow();
                    listRow3.Active = false;
                    listRow3.AddColumn(current2.ProductNumber);
                    listRow3.AddColumn(current2.ProductName);
                    try
                    {
                        listRow3.AddColumn(this.CreateRmaLink(ReturnMerchandiseAuthorization.GetRmasByOrderLineId(current2.ID)[k].Id.ToString()));
                    }
                    catch (System.Exception)
                    {
                        listRow3.AddColumn(Translate.Translate("Unable to find RMA Id", 0));
                    }
                    list.Add(listRow3);
                }
            }
        }
        if (list.Count > 0)
        {
            ListRow listRow4 = new ListRow();
            listRow4.AddColumn("");
            listRow4.AddColumn(Translate.Translate("Claimed products", 0));
            listRow4.AddColumn("");
            listRow4.AddColumn("");
            listRow4.AddColumn("");
            listRow4.Expandable = true;
            this.OrderlineList.AddRow(listRow4);
            if (this.Session[this._sessionKeyClaimedProduct] != null)
            {
                this.Session.Remove(this._sessionKeyClaimedProduct);
            }
            this.Session.Add(this._sessionKeyClaimedProduct, list);
        }
        if (num == 0)
        {
            this.RmaInfoBar.Message = "There are no available products on this order.";
            this.RmaInfoBar.TranslateMessage = true;
            this.RmaInfoBar.Type = Infobar.MessageType.Warning;
            this.RmaInfoBar.Visible = true;
            this.DisableUI();
        }
    }
    else
    {
        foreach (ReturnMerchandiseAuthorizationOrderLine current3 in this._rma.OrderLines)
        {
            ListRow listRow5 = new ListRow();
            listRow5.AddColumn(current3.OrderLine.ProductNumber);
            listRow5.AddColumn(current3.OrderLine.ProductName);
            listRow5.AddColumn(current3.SerialNumber);
            this.OrderlineList.AddRow(listRow5);
        }
    }
}

Why:

The reason is that the availableOrderLines dictionary does not necessarily contain all entries in this._order.ProductOrderLines. This happens when there is a Fixed OrderLine in the Order, and then during iteration, when a Fixed OrderLine is encountered, the key is not present in the availableOrderLines dictionary, which generates the error above.

Here are two decompiled source code excerpts from Dynamicweb.dll, showing that the ProductOrderLines property of an Order includes Fixed OrderLine instances, while the GetAvailableOrderLines method does not include them.

1.

// Dynamicweb.eCommerce.Orders.Order
public OrderLineCollection ProductOrderLines
{
    get
    {
        OrderLineCollection orderLineCollection = new OrderLineCollection();
        foreach (OrderLine current in this.OrderLines)
        {
            if (current.HasType(new OrderLine.OrderLineType[]
            {
                OrderLine.OrderLineType.Product,
                OrderLine.OrderLineType.Fixed,
                OrderLine.OrderLineType.PointProduct
            }))
            {
                if (current != null && current.Product != null)
                {
                    orderLineCollection.Add(current);
                }
            }
        }
        return orderLineCollection;
    }
}

2.

// Dynamicweb.eCommerce.Orders.ReturnMerchandiseAuthorization.ReturnMerchandiseAuthorization
internal static System.Collections.Generic.Dictionary<string, int> GetAvailableOrderLines(Order order)
{
    System.Collections.Generic.Dictionary<string, int> dictionary = new System.Collections.Generic.Dictionary<string, int>();
    foreach (OrderLine current in order.OrderLines)
    {
        if (current.HasType(new OrderLine.OrderLineType[]
        {
            OrderLine.OrderLineType.Product,
            OrderLine.OrderLineType.PointProduct // MISSING OrderLine.OrderLineType.Fixed
        }))
        {
            dictionary.Add(current.ID, (int)System.Math.Round(current.Quantity));
        }
    }
    ReturnMerchandiseAuthorizationCollection allNotDeletedRmas = ReturnMerchandiseAuthorization.GetAllNotDeletedRmas();
    foreach (ReturnMerchandiseAuthorization current2 in allNotDeletedRmas)
    {
        if (current2.OrderLines.Count > 0 && current2.OrderLines.First<ReturnMerchandiseAuthorizationOrderLine>().OrderLine.OrderID == order.ID)
        {
            foreach (ReturnMerchandiseAuthorizationOrderLine current3 in current2.OrderLines)
            {
                if (current3.OrderLine.HasType(new OrderLine.OrderLineType[]
                {
                    OrderLine.OrderLineType.Product,
                    OrderLine.OrderLineType.PointProduct // MISSING OrderLine.OrderLineType.Fixed
                }))
                {
                    dictionary[current3.OrderLine.ID] = dictionary[current3.OrderLine.ID] - 1;
                }
            }
        }
    }
    return dictionary;
}

 

The solution's Dynamicweb version is 8.5.1.19.

Please let me know if you need more information.


Replies

 
Alexander P.
Reply

Just posting this, in order to keep this thread visible.

 
Nicolai Høeg Pedersen
Reply

Hi Alexander

Sorry!

I've sent it for fixing.

BR Nicolai

 
Vladimir
Reply

Hi Alexander,
thank you for such detailed analysis:)
I want to clarify(just for precise testing): how fixed lines appeared in order - they were added by an extension?

Best regards,

Vladimir

 
Vladimir
Reply

Hi Alexander,
thank you for such detailed analysis:)
I want to clarify(just for precise testing): how fixed lines appeared in order - they were added by an extension?

Best regards,

Vladimir

 
Oleg Rodionov
Reply

New TFS # 17368 has been submitted against the bug

BR, Oleg, QA

 
Alexander P.
Reply

Hi Vladimir,

Yes, the order lines appeared, because they were added by some custom code (a NotificationSubscriber to the eCommerce.Cart.AfterCustomFieldValueIsChanged event). I made the code use the Fixed OrderLine type, when adding new order lines, because I assumed it was a valid OrderLine type.

Best Regards,
Alexander

 

You must be logged in to post in the forum