This project is read-only.

Issue: StackOverflowException thrown by an infinite loop with ObjectContainerDataSource and controls derived from ListControl (DropDownList, ListBox, CheckBoxList, etc).

When a control derived from the ListControl class (DropDownList, ListBox, CheckBoxList, ...) is bound to an ObjectContainerDataSource that uses custom paging and sorting, an infinite loop is produced and a StackOverflowException is thrown.

Fix

1- Open the file: Microsoft.Practices\Web Controls\ObjectContainerDataSourceView.cs
2- Declare a boolean private field:
#region Private Fields

private List<object> _data = new List<object>();
private bool _usingServerSorting;
private string _dataObjectTypeName;
private Type _dataObjectType;
private int _totalRowCount = -1;
private bool _usingServerPaging;
private bool _selecting; // <- (on selecting event flag)

#endregion


3- In the OnSelecting method set the flag to true before handling the event and then set it to false.
protected virtual bool OnSelecting(ObjectContainerDataSourceSelectingEventArgs e)
{
    EventHandler<ObjectContainerDataSourceSelectingEventArgs> handler =
        base.Events[SelectingEventKey] as EventHandler<ObjectContainerDataSourceSelectingEventArgs>;

    if (handler != null)
    {
         _selecting = true; // <-
         handler(this, e);
         _selecting = false; // <-

        return true;
    }
        else
    {
        return false;
    }
} 


4- In the DataSource property check that the flag is false before calling OnDataSourceViewChanged.
public virtual object DataSource
{
    set
    {
        Data.Clear();
        
        if (value == null)
            return;

        IEnumerable values = value as IEnumerable;

        if (values != null)
        {
            SafeAddRange(values);
        }
        else
        {
            SafeAdd(value);
        }

        if (!_selecting) // <-
            OnDataSourceViewChanged(EventArgs.Empty);
    }
}

Workaround

For a quick workaround that does not require you to modify the WCSF source code, you can use a flag in the Selecting event handler implemented in the view, as shown below:
bool _selecting = false;

protected void CustomersDataSource_Selecting(object sender, ObjectContainerDataSourceSelectingEventArgs e)
{
    if (!_selecting)
    {
        _selecting = true;

        _presenter.OnSelecting(e.Arguments.StartRowIndex, e.Arguments.MaximumRows, e.Arguments.SortExpression);

        _selecting = false;
    }
}

Last edited Mar 14, 2008 at 4:06 PM by MarianoSzklanny, version 2

Comments

No comments yet.