Bug Report B135208
Visible to All Users

ASPxListBox - Updating the items collection on the client side results in an "Object reference not set" exception if the view state is disabled

created 16 years ago

In version 8.3 this worked beautifully.
I have a webcontrol wherein I'm moving items clientside between two listboxes (as per your own example) and then saving the changes (postback).
In 9.1 the very same code generates an error in an undocumented method. (AreItemsEqualWithoutValues(ListEditItem item1, ListEditItem item2)). Since I have changed nothing in code, I'd like to have a workaround or solution for this problem.
Steps to Reproduce:
Create webcontrol with three listboxes (items,selecteditems,selecteditems2), 8 buttons (add,add2, addall,addall2,remove,remove2,removeall,removeall2)
Datasource can be anything (simpllist will do)
Put control in a popupcontrol and add a savebutton to the footer.
create a label or button to open the popupcontrol.
create a savemethod in codebehind. You should get the error.
Actual Results:
{"Object reference not set to an instance of an object."}
    [System.NullReferenceException]: {"Object reference not set to an instance of an object."}
    Data: {System.Collections.ListDictionaryInternal}
    HelpLink: null
    InnerException: null
    Message: "Object reference not set to an instance of an object."
    Source: "DevExpress.Web.ASPxEditors.v9.1"
    StackTrace: " at DevExpress.Web.ASPxEditors.ListBoxProperties.AreItemsEqualWithoutValues(ListEditItem item1, ListEditItem item2)\r\n at DevExpress.Web.ASPxEditors.ListBoxProperties.SynchronizeItems(String serializedItems, Boolean isInsertingSyncType)\r\n at DevExpress.Web.ASPxEditors.ASPxListBox.SynchronizeItems(NameValueCollection postCollection)\r\n at DevExpress.Web.ASPxEditors.ASPxListBox.LoadPostData(NameValueCollection postCollection)\r\n at DevExpress.Web.ASPxClasses.ASPxWebControl.LoadPostDataInternal(NameValueCollection postCollection, Boolean raisePostDataEvent)\r\n at DevExpress.Web.ASPxClasses.ASPxWebControl.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection)\r\n at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad)\r\n at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)"
    TargetSite: {Boolean AreItemsEqualWithoutValues(DevExpress.Web.ASPxEditors.ListEditItem, DevExpress.Web.ASPxEditors.ListEditItem)}

Show previous comments (3)

    Thanks for the response.
    Reproduction wasn't quite as expected.
    Enclosed you'll find the usercontrol in question.
    You'll notice the difference immediately.
    My refences to DevXpress are all done in web.config instead of in the controls and pages.
    You might want to change the datasource, since I cannot give you the datasource . It would involve to many libraries.

    Serge (DevExpress Support) 16 years ago

      May I ask you to provide a working sample? We just want to be sure that we're testing under the same conditions … to prevent possible misunderstandings as in our first reply.
      Thanks in advance!
      Regards,
      Serge

        Please find attacthed the new usercontrol and a web.config.
        Please replace the usercontrol in your example with this control and put and overwrite the web.config

        Answers approved by DevExpress Support

        created 16 years ago (modified 11 years ago)

        Hi,
        Thank you for the updated sample. First, I should highlight some important things. When changing the ASPxListBox.Items collection at the client side, the control sends the difference between the initial and modified collections to the server. To apply this difference to the initial collection at the server side, it's obviously necessary to load the initial collection first. Once the synchronization has been performed, the newly updated collection should be preserved as the initial collection. This is necessary to restore it during further postbacks. By design, we use the view state as a storage. The view state is disabled in your sample and the initial collection isn't restored. As a result, the difference between the collections sent from the client side is applied to an empty collection. This worked OK in v2008 vol 3. If the changes cannot be applied to the initial collection, v2008 vol 3 simply ignores them. v2009 vol 1 raises an exception in this situation. We've made the necessary corrections to restore the same behavior as in v2008 vol 3. The fix will be included in the next upcoming maintenance update v2009 vol 1.3.
        Since you've disabled the view state in your sample, we tend to think that you maintain a separate storage for the Items collection. This way, please note that you must restore the original collection on the Page_Init event handler, not in Page_Load, because the synchronization is performed between these events. Moreover, you should do this on every postback or callback. So, please remove the if(!IsPostBack) verification from your code. Finally, you should save the modified/synchronized collection in your storage. This can be done, for example, in the Page_Load event handler. This approach should work OK both with v2008 vol 3 and v2009 vol 1. Here is some sample code:

        C#
        //protected void Page_Load(object sender, EventArgs e) { protected void Page_Init(object sender, EventArgs e) { Dictionary<string, string> Items = new Dictionary<string, string>(); //if(!IsPostBack) { for(int i = 0; i < 11; i++) { Items.Add("Item " + i, Guid.NewGuid().ToString()); } lbOptions.DataSource = Items; lbOptions.TextField = "Value"; lbOptions.ValueField = "Key"; lbOptions.DataBind(); //} }

        I've also attached some modified files illustrating how to deal with the collections stored in the view state. It works OK in v2009 vol 1. In your sample, the collection isn't stored anywhere. As a result, the project works only until the 2nd postback.
        Does this make sense?
        Thanks,
        Serge

          Comments (3)

            Serge,
            Thanks and yes, it does make sense.
            Your assumptions were correct. I use a customized ViewState storage object to store objects.
            So the nice thing about this is i only have to set EnableViewstate back to true (or delete the whole parameter) and things should work OK.
            The reason I did it like is is because I don't want to store what I don't have to.
            Since I don't have to store anything about the original collection (I'm moving stuff clientside), I didn't bother with storing the original collection.
            So thank you for your reply.
            Kind regards,
            Arjan Crielaard

              Issue Resolved

              Serge (DevExpress Support) 16 years ago

                Thank you for informing us that the problem is resolved, Arjan. I'm glad that our assistance was helpful.
                If you need any further assistance on this subject, please feel free to reactivate this ticket.
                Thanks,
                Serge

                Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

                Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.