Dynamic Validation Rules - possibly

Dynamic Validation Rules - possibly

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


whelzer posted on Friday, October 23, 2009

I would like to achieve the following: (vb 2008 , windows forms, 2 tier using, csla 3.6.2 but mostly 3.0.4 syntax!)

I've a root object (say Customer) bound to Customer screen,  the data is held in tblCustomer.
I use a versioning/audit technique whereby each row in tblCustomer starts off with version 999 and in decrements each time an amedment (update) is made.  The old version is put out to tblCustomerArc.

Under certain circumstances during DP_Fetch of Customer I would like to get the data from a previous version, compare it against the latest and somehow flag to the user the old value.  I was thinking a slick way of achieving this would be to use a dynamic validation rules and set the severity to "Information" and the Description to the old value.  Thus each changed textbox on the form would have a nice little info icon and hovering would give details of the previous value.  I've no issue in getting the old data and comparing it to the new, its the creating and trigger of rules in this scenario that has me stumped.  Any pointers or help much appreicated.


RockfordLhotka replied on Friday, October 23, 2009

I've often thought that it would be nice to have a direct way to add a permanent Information 'broken rule' for a property. The kind of thing you'd do in DataPortal_Create() or DP_Fetch().

Maybe like this:

ValidationRules.AddInformationMessage(IPropertyInfo property, string text)

Or if we wanted to be able add/remove them:

ValidationRules.SetInformationMessage(IPropertyInfo property, string ruleName, string text)

Such a message would never auto-add or auto-remove as other rules run, but they'd be in the broken rules list and so would appear in the UI, etc.

Probably something that should go on the wish list - it seems like this is the kind of thing that'd make your scenario pretty easy.

whelzer replied on Friday, October 23, 2009

Sounds good.  Any ideas for now?

RockfordLhotka replied on Friday, October 23, 2009

In the meantime, the solution is to write a rule method and attach it to each of your properties. The trick is to provide that rule method with access to the comparison data, which can be accomplished by storing it as a NonSerialized field on your business class itself.

This is far from elegant, but something like this should work:

  [Serializable]
  public class Test : BusinessBase<Test>
  {
    private static PropertyInfo<string> NameProperty = RegisterProperty<string>(c => c.Name);
    public string Name
    {
      get { return GetProperty(NameProperty); }
      set { SetProperty(NameProperty, value); }
    }

    protected override void AddBusinessRules()
    {
      base.AddBusinessRules();
      ValidationRules.AddRule(InfoRule, NameProperty);
    }

    private static bool InfoRule(object target, Csla.Validation.RuleArgs e)
    {
      var obj = target as Test;
      var comp = obj._comparisonData;
     

      if (obj != null && comp != null)
      {
        e.Severity = Csla.Validation.RuleSeverity.Information;
        switch (e.PropertyName)
        {
          case "Name":
            if (obj.Name != comp.Name)
            {
              e.Description = "Name is different";
              return false;
            }
            break;
          default:
            break;
        }
      }
      return true;
    }

    [NonSerialized]
    private Test _comparisonData;

    private void DataPortal_Fetch(SingleCriteria<Test, int> criteria)
    {
      // load object data
      // load comparison data
      ValidationRules.CheckRules();
    }
  }

whelzer replied on Friday, October 23, 2009

Cool.  Thanks for taking the time to post this.

Copyright (c) Marimer LLC