ValidationRules.CheckRules() throws NullReferenceException if called while undoing changes?

ValidationRules.CheckRules() throws NullReferenceException if called while undoing changes?

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


rsbaker0 posted on Wednesday, March 24, 2010

I was experimenting with wanting to check some validation rules in OnChildChanged(), and I'm finding that this works fine except when I call UndoChanges() on the object. The same call that worked previously throws an exception in ValidationRules.GetTypeRules() because the "_target" member is now null.

I tried using a pseudo-property also and calling PropertyHasChanged(), but that produced the same result.

Shouldn't you be able to fire validation rules when events are bubbling up from child objects?

(This is in CSLA 3.5, so perhaps it has subsequently been fixed)

RockfordLhotka replied on Wednesday, March 24, 2010

I don't know the answer to that for sure. The undo operation can (if you have any BLB objects in the graph) reshape your graph by re-adding and un-adding objects from the list. So I suppose it is possible that the object graph could be in an indeterminate state at some points during the undo operation.

rsbaker0 replied on Wednesday, March 24, 2010

In this case, the ValidationRules.CheckRules() call (or PropertyHasChanged(...)) is actually failing in the root object, so somehow the state of the ValidationRules member of the root itself would seem to be inconsistent.  Would this change your answer or is this still to be expected?

(As an aside, I managed to work around this for now by ignoring the OnChildChanged() call for the BLB child I am monitoring if the list is being "reset" but I was still concerned I might be doing something that isn't supported here)

RockfordLhotka replied on Wednesday, March 24, 2010

Thinking a little more on this, when you do a BeginEdit a snapshot of your object's state gets stored. This snapshot includes the broken rules  - basically the rules subsystem gets copied.

So during an undo that snapshot is restored - effectively setting the object's rules state (including broken rules) back to where it was when BeginEdit was called.

That means deserializing the rule object graph, and the rule object graph has a reference to its business object (what would be a circular reference). This reference isn't maintained through serialization for perf/size reasons, so it is reset after the undo operation is complete.

I think it is safe to say that you are in an unsupported scenario, because during the undo process the various business objects in your object graph are getting their rule subsystem objects all deserialized and eventually "re-targeted" back at each business object.

If there's any bug here at all, it is probably that ChildChanged events maybe shouldn't be firing at all during this process. Though I'm not really sure that's true either, since I can see where you'd want those events so as to do re-binding of UI elements or other actions.

rsbaker0 replied on Thursday, March 25, 2010

I see what is going on. The BusinessBase implementation of UndoChangesComplete() looks like this:

    protected override void UndoChangesComplete()
    {
      BindingEdit = false;
      ValidationRules.SetTarget(this);
      InitializeBusinessRules();
      OnUnknownPropertyChanged();
      base.UndoChangesComplete();
    }

So, evidently you anticipated the _target member of ValidationRules needing to be restored.

Maybe you might provide some protected method so that we can at least test whether we are in the middle of an Undo. It wouldn't be hard at all for me to do this, but maybe it would be better placed in the the framework itself.

 

RockfordLhotka replied on Thursday, March 25, 2010

http://www.lhotka.net/cslabugs/edit_bug.aspx?id=725

Copyright (c) Marimer LLC