Executing validation rules on UndoChangesComplete with configurable rules.

Executing validation rules on UndoChangesComplete with configurable rules.

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


GWZ posted on Friday, March 27, 2009

Using 3.6.1.

I have a BO that has configurable rules that may change infrequently over time. For example , the  DefectCode BO has the property, RequiresComments. The Defect BO has properties, DefectCode and Comments. When adding a new Defect,  the validation rule looks at the selected DefectCode.RequiresComments to determine if the comment is required.

I have a use case where the users want to edit Defects. When the selected Defects are loaded from the database, the rules are NOT checked because the RequiresComments property may have changed over time.  However if an old Defect item is edited or a new one is added, then the current validation rules are applied.

The problem occurs when a user begins an editng session and then decides to abort the changes. When the undo is executed, the UndoChangesComplete method of the BusinessBase calls OnUnknownPropertyChanged which triggers validation of  the Defect BO. This may invalidate some old objects because the rule was changed since the object was created.

In a second use case, users are allowed to view (but not edit) old item and may add new items. An undo in this use case renders to form useless because the user can never edit the invalid objects.

I cannot easily override the UndoChangesComplete method  in my BO because some of the methods it needs to call are not accessable from my BO.

Does anyone have a solution for this problem?

Wayne

JoeFallon1 replied on Friday, March 27, 2009

I have a similar situation. In my app a user can edit an existing record. But one of the values in that may have been de-activated at a later date. So if I just ran a rule that said the value must be active then the user would be forced to change the de-activated value even though that is not the reason they are editing the record. That would not be acceptable.

So we devised a smarter rule.
The BO stores the Original value when the object is fetched from the DB in a read only field. So if the BO has a property Vendor it also has a readonly property called OrigVendor. As long as the user does not edit the Vendor field the rule will allow the de-activated vendor code to be re-saved with the rest of the record. But if the user does decide to change it, they have to change to a valid active value.
The other trick is to check if the BO IsNew or not. A new BO is one that is not being edited so the Vendor value must be an active record. If it is not new then it is being edited and the rule only runs if the current value has been changed from the original value.

It looks like this:

Public Function ActiveRecordExists(ByVal target As Object, ByVal e As RuleArgs) As Boolean
Dim ruleArg As ActiveRecordExistsRuleArgs = DirectCast(e, ActiveRecordExistsRuleArgs)
Dim propertyName As String = ruleArg.PropertyName
Dim propertyDescription As String = ruleArg.PropertyDescr
Dim tableName As String = ruleArg.TableName

Dim value As String = CallByName(target, propertyName, Microsoft.VisualBasic.CallType.Get).ToString
Dim origvalue As String = CallByName(target, "Orig" & propertyName, Microsoft.VisualBasic.CallType.Get).ToString

Dim bizObject As Csla.Core.BusinessBase = DirectCast(target, Csla.Core.BusinessBase)

If (bizObject.IsNew) OrElse (Not bizObject.IsNew AndAlso value <> origvalue) Then

If CheckValue.ActiveRecordExists(tableName, value) Then
Return True
Else
e.Description = GetDescription(target, propertyName, propertyDescription) & " does not exist or is not active."
Return False
End If

Else
Return True
End If
End Function

Note: CheckValue.ActiveRecordExists is a small BO which does quick lookups.

Joe

rsbaker0 replied on Friday, March 27, 2009

JoeFallon1:
... So we devised a smarter rule. The BO stores the Original value when the object is fetched from the DB in a read only field. So if the BO has a property Vendor it also has a readonly property called OrigVendor. As long as the user does not edit the Vendor field the rule will allow the de-activated vendor code to be re-saved with the rest of the record. But if the user does decide to change it, they have to change to a valid active value....

We built "original value" availability into our entire infrastructure, partly to provide this capability. It's not really that onerous if you just store values for properties that have changed (versus allocating space in advance for every property). I think CSLA 3.5 implemented "OnPropertyChanging" as part of BusinessBase, which made this even easier.

As far as the OP's question for, I wonder what the rationale for firing all the validation rules is when an "unknown" property has changed, and if this could be short-circuited somehow? Of course, if the BrokenRulesCollection isn't on the undo state stack, then this explains why this would be needed...

Copyright (c) Marimer LLC