Validation of objects with properties where CanReadProperty = false

Validation of objects with properties where CanReadProperty = false

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


MonorailMan posted on Thursday, February 22, 2007

I have an object with a string property that is required (CommonRules.StringRequired).  Some users of my app will be able to read this property, while others will not.  I am using CanReadProperty(true) in the property getter, as that seems to be the standard.  If I am logged in as a user with no Get permission on this property, validation will always throw an exception because the property cannot be checked.  How do I validate this object if the user is unable to Get it?

Thanks for your assistance

ajj3085 replied on Thursday, February 22, 2007

First, a user without permission to read this property may be allowed to set it?  That's unusual..

To get around your problem, I think you'll have to make your own StringRequired static method within the class that contains the property.  In your own StringRequired method, you'd then check the value of the field, not the property.. something like this:

private static bool MyPropertyStringRequired( MyClass target, RuleArgs e ) {
     bool result;

      if ( string.IsNullOrEmpty( target.myProperty ) ) {
            result = false;
            e.Description = "Required!";
       }
     else {
           result = true;
     }

     return result;
}

mr_lasseter replied on Thursday, February 22, 2007

The user doesn't have to set it for the validation rules to be called.  Think about the scenario where object is fetched from the database and then the Validation.CheckRules is called. 

Also, wouldn't you want to call the CanReadProperty in the validation routine?

ajj3085 replied on Thursday, February 22, 2007

Yes, that's right... DP_F would check the rule.

You wouldn't want to call CanReadProperty in the validation routine though.  The routine doesn't expose the value in the myProperty field to the user, it just checks if the value is empty or not.


MonorailMan replied on Thursday, February 22, 2007

Exactly, and with the code sample above, it is still calling the public property to check the value, which will call CanReadProperty(true), throwing the exception.  Should I move CanReadProperty to the UI, allowing validation to run, but checking the access in the UI instead?

ajj3085 replied on Thursday, February 22, 2007

Ahh, no, the code isn't clear I guess.

public class MyClass : BusinessBase<MyClass> {

   private string myProperty;

   public string MyProperty {
          get {
               CanReadProperty( "MyProperty", true );
               return myProperty;
          }
     }
}

So in the rule, you're checking the value via the field and not the property.  Notice in my previous code posting the check is:
    string.IsNullOrEmpty( target.myProperty )

MonorailMan replied on Thursday, February 22, 2007

Ahhh...thank you for pointing that out.  I hadn't thought of that.  I just tested it, and it does work.

Thank you all for your help

ajj3085 replied on Thursday, February 22, 2007

No problem, glad you got it working.

MonorailMan replied on Thursday, February 22, 2007

One more thought: Is there a way to make this more generic?  What if I would like to use the same method for checking multiple private fields?  I tried target.GetType().GetFields(), but that only returns public fields.  Is there another way?

Thanks

RockfordLhotka replied on Thursday, February 22, 2007

Sure, but you must use reflection (late binding). It is a very good idea to normalize behavior by creating reusable rule methods!

Reflection does allow you access to private fields, though not by default. Read through the n-level undo implementation in Chapter 3 though, because I do exactly that in my implementation.

xal replied on Thursday, February 22, 2007

You need to pass the correct binding flags in order to get private fields.
If my memory doesn't fail it's the combination of (in vb):
Dim bFlags As BindingFlags = BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public

Now you could do:
target.GetType().GetField("fieldName", bFlags)


Andrés


Copyright (c) Marimer LLC