CSLA 3.5.1 BUG in BrokenRules

CSLA 3.5.1 BUG in BrokenRules

Old forum URL: forums.lhotka.net/forums/t/5025.aspx


JonnyBee posted on Friday, June 27, 2008

Hi,

I have found the following a bug in CSLA 3.5.1 that throws:
System.NotSupportedException in BindingList<T>.RemoveItem.

BrokenRulesCollection inherits from ReadOnlyBindingList that has the following constructor:

    protected ReadOnlyBindingList()
    {
      this.RaiseListChangedEvents = false;
      AllowEdit = false;
      AllowRemove = false;
      AllowNew = false;
      this.RaiseListChangedEvents = true;
    }

 and the IsReadOnly mehod is
    public bool IsReadOnly
    {
      get { return _isReadOnly; }
      protected set { _isReadOnly = value; }
    }

The Bug happens  when a BrokenRule is no longer Broken, ie it is to be removed from the broken rules collection. The Add mehod of BrokenRulesCollection only touches the IsReadOnly property and so the AllowNew and AllowRemove are still false. 

<BrokenRulesCollection.cs>
    internal void Add(IRuleMethod rule)
    {
      Remove(rule);
      IsReadOnly = false;
      BrokenRule item = new BrokenRule(rule);
      IncrementCount(item);
      Add(item);
      IsReadOnly = true;
    }

    internal void Remove(IRuleMethod rule)
    {
      // we loop through using a numeric counter because
      // removing items within a foreach isn't reliable
      IsReadOnly = false;
      for (int index = 0; index < Count; index++)
        if (this[index].RuleName == rule.RuleName)
        {
          DecrementCount(this[index]);
          RemoveAt(index);
          break;
        }
      IsReadOnly = true;
    }

At the moment RemoveAt is called the property AllowRemove is false and thus a System.NotSupportedException is thrown. This might also happend on new broken rules.

/jonny

JoeFallon1 replied on Friday, June 27, 2008

I find it hard to believe that you are the first one to run into this problem!

No one else writes rules and has them broken and unbroken??

The code looks similar to the code that has been in effect since 3.0.

I wonder what the real issue is here?

Joe

 

JonnyBee replied on Saturday, June 28, 2008

Hi Joe,

It might have to do with the fact that I stripped down CSLA 3.5.1 to compile for .NET 2.0 and referenced this CSLA component from a project in VS2005.

And from what I can see there is some code in ReadOnlyBindingList.cs that has been removed in the transition from 3.0.4 to 3.5.1. The code that has been removed is as follows:

    protected override void InsertItem(int index, C item)
    {
      if (!IsReadOnly)
        base.InsertItem(index, item);
      else
        throw new NotSupportedException(Resources.InsertInvalidException);
    }

    protected override void RemoveItem(int index)
    {
      if (!IsReadOnly)
      {
        bool oldValue = AllowRemove;
        AllowRemove = true;
        base.RemoveItem(index);
        AllowRemove = oldValue;
      }
      else
        throw new NotSupportedException(Resources.RemoveInvalidException);
    }

    protected override void SetItem(int index, C item)
    {
      if (!IsReadOnly)
        base.SetItem(index, item);
      else
        throw new NotSupportedException(Resources.ChangeInvalidException);
    }
  }

So when these overridden methods no longer exists the code hits RemoveItem in ExtendedBindingList that does not modify the AllowRemove property (and then it throws an Exception).

I assumed that it would also affect the .NET 3.5 code but for some reason it seems to works there.

/jonny


JoeFallon1 replied on Monday, June 30, 2008

In my copy of 3.5 (not the latest) that code is present in the VB version:

Protected Overrides Sub RemoveItem(ByVal index As Integer)
  If (Not IsReadOnly) Then
     
Dim oldValue As Boolean = AllowRemove
    AllowRemove =
True
   
RemoveIndexItem(Me(index))
   
MyBase.RemoveItem(index)
    AllowRemove = oldValue
  Else
   
Throw New NotSupportedException("")
  End If
End Sub

Joe

JonnyBee replied on Tuesday, July 01, 2008

Hi Joe,

Must be me doing some strange things in stripping down to .NET 2.0 - the "missing" code is in the 3.5.1 ReadOnlyListBase.cs.

Ignore this thread - just my own mistake/error.

/jonny .

Copyright (c) Marimer LLC