ValidationRules at Runtime

ValidationRules at Runtime

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


Pavel posted on Thursday, June 07, 2007

Hi everybody,
I have a few User Fileds in my table, such as U_String1 or U_Bool1  and so on.
In my object all properties for those fields created.

Any idea how to define ValidationRules during a runtime?
Users of this Project software may use this field if they required to add some custom attribute. As for me, I never known what would be the requirements, but I know a type of the field, such as String or Boolean.

un7lg replied on Tuesday, July 17, 2007

It's interesting question, isn't it ?

RockfordLhotka replied on Tuesday, July 17, 2007

One reason the validation rules are associated with properties in AddBusinessRules() - as opposed to using attributes or some other technique - is to allow programmatic association of rules with properties.

Remember that AddRule() takes two parameters: a delegate reference and a property name.

Using a bit of reflection, you can easily create a delegate reference to a method based on the full type and method name in string form.

In other words, if you are able to get metadata from some source (like your database) that specifies the full type path to a rule method (so the type name and method name), along with the property the rule applies to, you can dynamically call AddRule() based on that metadata.

CSLA3 includes a new capability to help with this: the DecoratedRuleArgs class. This is a subclass of RuleArgs that accepts a Dictionary of name/value pairs that are passed to the rule method - following the Decorator design pattern. If your rule method uses DecoratedRuleArgs to get its extra parameters, then you have a much simpler time storing the name/value data for a rule method as metadata as well - and that completes the whole picture.

So your metadata is:

Given that metadata, you can write code in AddBusinessRules() to dynamically associate rules with methods.

CodeSmartNotHard replied on Wednesday, July 18, 2007

We are doing this for one of our objects where we have properties that are required, recommended, and visible for specific statuses.  We use table based code generation to create our objects.  To be able to do this in our generated classes, we created sql server extended properties for each of these behaviors.  Our template in turn reads the extended property and creates them as attributes on our objects.  Then our object iterates through the attributes and dynamically adds/removes items in the validationrules collection.   The EVILAttributes project helped us with the attribute rules.  As the user changes statuses, the object notifies the UI of these behaviors and updates the controls.  It seems to work good.   We had to make one CSLA.NET change that I can remember (I didn't do all of the implementation) for this to work.  We had to make the add/remove methods of the validationrules public.  If this sounds like what you are wanting to do, I can post some code.

Mike
www.CodeSmartNotHard.com

 

JoeFallon1 replied on Thursday, July 19, 2007

Mike,

I took a quick look at the EViL attributes project just now.

I would like to see how you make it work with CSLA validation rules.

Please post some code samples. Thanks.

Joe

 

CodeSmartNotHard replied on Saturday, July 21, 2007

Here’s a small example of the different pieces.  I can’t include the full class because my work doesn’t like me to post that much code.  This should show you the main parts.   The only change to CSLA.NET that I can remember is that we had to make the ValidationRules public so we could call the AddRule and DeleteRule from outside the business object. 

 

In the Extended Property of the FullName column:

        Name  = IsRequiredForStatus
   
Value = Codes.Status.Complete

Property is generated like this:

   <IsRequiredForStatus(Codes.Status.Complete)> _

   Public Overridable Property FullName() As String

In the “set” of the nogen Status property (which is of type Codes.Status  enumeration), it calls the function to check the attributes.  This calls the EVIL attributes to process the rules:

   RunValidationAttributes()

In the Validator, it uses reflection to get all of the properties of the object. It loops through each of the properties and checks to see if any of the attributes are of type VBEvilBaseAttribute.  If so then it calls the ProcessRule of that attribute class such as “IsRequiredForStats”.

 

   Public Class IsRequiredForStatus

       Inherits VBEvilBaseAttribute

 

   Public Overrides Function ProcessRule(ByVal pi As PropertyInfo,

       ByVal entity As Object) As Boolean

 

If the property’s attribute enumeration value matches the enumeration of the Status property then it’s required.  The logic below is done for each datatype.

 

 If IsRequired Then

    If pi.PropertyType Is GetType(String) Then

      Dim args As New Csla2.Validation.RuleArgs(pi.Name)

      args.Description = pi.Name & " is required for this status."

      args.Severity = Csla2.Validation.RuleSeverity.FailsCustomRules

busObject.ValidationRules.AddRule(AddressOf

           Csla2.Validation.CommonRules.StringRequired, args)

 Else

    If pi.PropertyType Is GetType(String) Then

       busObject.ValidationRules.DeleteRule(pi.Name, "StringRequired")

If you have any questions, comments, or better ideas, please let me know.  I always like to hear ideas for using CSLA.NET. I would like to thank Dave Cottle.  He is the one that figured out a lot details to make this work.

I also blogged this same info here: http://codesmartnothard.com/PermaLink,guid,ea138e37-fb83-47b3-bbf8-b0ee5c27044f.aspx

Mike

un7lg replied on Thursday, July 19, 2007

CodeSmartNotHard:

We had to make one CSLA.NET change that I can remember (I didn't do all of the implementation) for this to work.  We had to make the add/remove methods of the validationrules public.  If this sounds like what you are wanting to do, I can post some code.



It would be interesting to see.

Thanks,

Copyright (c) Marimer LLC