RadzenListBox, bug when using asynchronous call LoadData

Hi team,

when using an HttpClient and set Multiple selection property true and AllowVirtualization [RadzenListBox],
throws an hard exception.

Error: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.Generic.List1.Enumerator.MoveNext()* *at System.Linq.Enumerable.SelectListIterator2.MoveNext()
at System.Linq.Enumerable.CastIterator[TResult](IEnumerable source)+MoveNext()
*at Radzen.DropDownBase`1.SelectItemFromValue(Object value) *
in ...\radzen-blazor\Radzen.Blazor\DropDownBase.cs:line 950

It tries to change the list in the same time as the list is read.
A quick fix would be to copy the list.


//Change from
foreach (object v in values)

//To
foreach (object v in values.ToList())

The method name is "SelectItemFromValue(object value)" in "DropDownBase" class


But this is not a clean solution.
I unfortunately do not have time for a clean solution and pull request
I hope the bug can be fixed quickly.

As an example:

<h4>Virtualization using LoadData event</h4>
<RadzenListBox AllowVirtualization="true" 
    Multiple="true"
    AllowFiltering="true" 
    Count="@count" 
    LoadData=@LoadDataVirtualization 
    Data=@attributesDataVirtualization
    TextProperty="Name"
    ValueProperty="Name"
    @bind-Value=@attributeValues
    Style="height:200px" Class="w-100" />
IEnumerable<string> attributeValues = new string[] {  };

async Task LoadDataVirtualization(LoadDataArgs args)
{
    var pagedResult = await GetAttributesAsync(args.Skip.HasValue ? args.Skip.Value : 0, args.Top.HasValue ? args.Top.Value : 10);

    count = items.Count;

    attributesDataVirtualization = pagedResult.Results;

    //var query = dbContext.Customers.AsQueryable();

    //if (!string.IsNullOrEmpty(args.Filter))
    //{
    //    query = query.Where(c => c.CustomerID.ToLower().Contains(args.Filter.ToLower()) || c.ContactName.ToLower().Contains(args.Filter.ToLower()));
    //}

    //console.Log($"LoadData with virtualization: Skip:{args.Skip}, Top:{args.Top}, Filter:{args.Filter}");

    //count = query.Count();

    //customCustomersDataVirtualization = query.Skip(args.Skip.HasValue ? args.Skip.Value : 0).Take(args.Top.HasValue ? args.Top.Value : 10).ToList();

    //InvokeAsync(StateHasChanged);
}

I have tested this directly in the Radzen demo (repo)

@Parijsy
There is probably a similar problem but I am not sure
RadzenListBox with Multiple and Virtualization

-Tom

I have looked at this now.
The problem with asynchronous processing is the two-way binding value property.

At the same time a value is set multiple and read by forearch.
This triggers the exception.

@bind-Value=@values
DataBoundFormComponent<T> CLASS
[Parameter]
public object Value
{
    get
    {
        return _value;
    }
    set
    {
        if (_value != value)
        {
            _value = object.Equals(value, "null") ? null : value;
        }
    }
}
FIX
DropDownBase<T> CLASS
protected virtual void SelectItemFromValue(object value)
{
    if (value != null && View != null)
    {
        if (!Multiple)
        {
            //......
        }
        else
        {   
             /*NEW*/                  
            var values = value as IEnumerable<object>;
            /*CURRENT*/
            //var values = value as dynamic;
            if (values != null)
            {
                if (!string.IsNullOrEmpty(ValueProperty))
                {
                    /*NEW*/   
                    foreach (object v in values.ToArray())
                    /*CURRENT*/
                    //foreach (object v in values)
                    {
                       //......
                    }
                }
                else
                {
                       //......
                }
            }
        }
    }
    else
    {
        selectedItem = null;
    }
}

It is accessed read only you can make a shallow copy with ToArray().
It solves the problem.

I hope it is helpful.

-Tom

Hi @Tom,

We would need a reproduction of this issue. How can we get this exception by modifying the RadzenListBox online demo?

@korchev
Hi, can you invite me to github and I could create a branch and commit it ?
If that's ok?

You can get my email from my account here I think.

-Tom

I can't invite you to github however you can open a pull request without an invitation. Still we prefer to reproduce the issue first hence my request.

@korchev

No problem.
In the startup of the demo add the client.

services.AddHttpClient();

Then just replace the ListBoxPage and start the demo.

ListBoxPage.zip (1.9 KB)

Select the entries of the ListBox you want and scroll up and down.
Then the exception is thrown.

-Tom

We've fixed this and the fix will be part of our next update before the end of the week.

1 Like

@enchev
Good morning, this is fanatstic news.
I noticed that multipleValues has double entries after scrolling up and down when items are selected.

If there is time it would be great if this could be fixed.

@bind-Value="multipleValues"

-Tom

@enchev

I have seen that it was fixed in the master branch.
Many thanks for the fast and professional work.

I have found another bug as written before.
After scrolling up and down the list of selected items is getting bigger.

For example: Two items selected, after scrolling there are 5

I added that in my example before.

ListBoxPage.zip (2.0 KB)

It is about the list of values that is bound to the listbox.

@bind-Value=@multipleEntryValues
IEnumerable<string> multipleEntryValues = new string[] { };

-Tom

Yes, we reproduced the problem. Hopefully fix for this will be released tomorrow with our next update.

@enchev
Super fast your response really incredible :ok_hand:t3:
If my colleagues were sooo fast :wink:

-Tom

@enchev
I have to bother you again :face_with_diagonal_mouth:

After scrolling up and down, you can no longer deselect the items.

-Tom

We've just released update of Radzen.Blazor with your reports addressed.

I have seen :ok_hand:t3:
Thanks a lot

-tom

Hello Team,

i have found another bug and a performance leak.
Should I open a new topic or can I write it here?

-Tom

It’s ok to continue here!

1 Like

About the bug:

When the second dataset is loaded after scroll down, the select all checkbox is not deselected until I select an item from the list. Sometimes it works but usually it does not work.

Sometimes the behavior is also different.
Is difficult to explain :face_with_spiral_eyes:

Example:
SecondDataSet
SecondDataSet2

-Tom

@enchev
Hi Enchev,

have you had the time to reproduce this?
Or do you need something from me to reproduce it?

-Tom

I didn’t have time to look at this issue, I’ll try to check it this week.

I've tried to reproduce this however select/deselect all worked normally:
dddg-sdall