ArgumentNullException in CommonRules.RegExMatch()

ArgumentNullException in CommonRules.RegExMatch()

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


cstaley posted on Monday, January 22, 2007

I've modified the CSLA.Contib templates to generate nullable value types on columns that allow nulls.  As a result, I'm running into problems with the RegExMatch() method in the Csla.Validation.CommonRules class when new CSLA objects are created.  The problem is that a null value is being validated, and the RegEx.IsMatch() method doesn't like null values being passed in (i.e. it throws a ArgumentNullException).

It seems like the RegExMatch() method should handle this situation more gracefully.  A null value should simply cause the rule to break, rather than throw an exception.  Afterall, a null value couldn't possibly match the regular expression, could it?

To handle this, I've modified the RegExMatch() method as follows (changes in bold):

public static bool RegExMatch(object target, RuleArgs e)
{
   Regex rx = ((RegExRuleArgs
)e).RegEx;
   string propertyValue = Utilities.CallByName(target, e.PropertyName, CallType.Get) as string
;
   if (propertyValue == null
|| !rx.IsMatch(propertyValue))
   {
      e.Description =
String.Format(Resources
.RegExMatchRule, e.PropertyName);
      return false
;
   }
   else
      return true
;
}

RockfordLhotka replied on Monday, January 22, 2007

I've added this request to my to-do list for future versions of the framework.

LEEG replied on Thursday, March 01, 2007

I ran into the same situation.  The one difference I would make is that a null or empty string would return true.  If the value shouldn't be null or an empty string then you would use the CommonRules.StringRequired rule as well.

So instead of the following:

if (propertyValue == null || !rx.IsMatch(propertyValue))

you would have:

if (!String.IsNullOrEmpty(propertyValue) && !rx.IsMatch(propertyValue))

 

RockfordLhotka replied on Thursday, March 01, 2007

My goal with RegEx is to allow anything that can be evaluated to be evaluated.

 

Your regex might reject or accept an empty string – I can’t make that judgment in code without restricting what can be expressed in the regex itself.

 

So the only real debate here, and I agree that there is one, is what to do about null values?

 

There are three answers:

 

1.       A null is an automatic True result

2.       A null is an automatic False result

3.       A null is converted to string.Empty and the regex runs

 

I’m not entirely sure which is the right answer overall, but thinking about it right now I lean toward #3.

 

Rocky

 

From: LEEG [mailto:cslanet@lhotka.net]
Sent: Thursday, March 01, 2007 3:56 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] ArgumentNullException in CommonRules.RegExMatch()

 

I ran into the same situation.  The one difference I would make is that a null or empty string would return true.  If the value shouldn't be null or an empty string then you would use the CommonRules.StringRequired rule as well.

So instead of the following:

if (propertyValue == null || !rx.IsMatch(propertyValue))

you would have:

if (!String.IsNullOrEmpty(propertyValue) && !rx.IsMatch(propertyValue))

 



cstaley replied on Thursday, March 08, 2007

Given the three options, I would argue for #2 by the process of elimination.

#1 is out because, as I originally posted at the start of the thread, passing in a null value to RegEx.IsMatch() will throw an exception.  Therefore, if you can't definitively say, "Yes, this value matches the regular expression," then you should never return true.

#3 should be eliminated for the same reason, but with the additional aggravating circumstance wherein a comparison of the actual value is never being made.  Additionally, since null and empty string can have different meanings, the method could effectively be misunderstanding the property's value, especially if the regular expression accepts empty strings.

RockfordLhotka replied on Friday, March 09, 2007

For fun I implemented 1 and 2 - allowing you to specify the result of a null. You can see the code in svn (C#) if you'd like.

I think I might actually support 3 using a similar technique - that wouldn't be terribly hard to do.

jhoojharsinghyadav replied on Friday, September 21, 2007

Rocky,

i am having an bo say employee. which do have up an required field i.e companyid (to which company he belongs) now i wnat to implement this in my bo .
that is in validation rules there is something called stringrequired , but this is going to be an int filed so doesnt there do exist something like intrequired .

another thing . coming up to the same scenario ,assuming the same business object employee , the companyid (which is to be populated via another namevalue list object) is the foreign key in database , but the datamapper maps it and returns 0 if null so to overcome this , what would be the best approach as if to handle null values and pss the null values back to database . like this should go null rather then 0 to database and come 0 rather then null from database as all the namevalue lsit objects do contain a default item with index 0 so i dont thing that could b a prob .

thanks
govind

RockfordLhotka replied on Friday, September 21, 2007

A “required integer” field probably just means the value must be >0 right? So you can use the MinValue rule, or the RegExMatch rule.

 

To deal with null values that should flow from the UI to/from the database, you should look at Nullable(Of T). In C# the compiler implements some syntactic sugar around Nullable<T> to give you things like int? and bool? which are nullable values.

 

Rocky

 

 

From: jhoojharsinghyadav [mailto:cslanet@lhotka.net]
Sent: Friday, September 21, 2007 7:07 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] ArgumentNullException in CommonRules.RegExMatch()

 

Rocky,

i am having an bo say employee. which do have up an required field i.e companyid (to which company he belongs) now i wnat to implement this in my bo .
that is in validation rules there is something called stringrequired , but this is going to be an int filed so doesnt there do exist something like intrequired .

another thing . coming up to the same scenario ,assuming the same business object employee , the companyid (which is to be populated via another namevalue list object) is the foreign key in database , but the datamapper maps it and returns 0 if null so to overcome this , what would be the best approach as if to handle null values and pss the null values back to database . like this should go null rather then 0 to database and come 0 rather then null from database as all the namevalue lsit objects do contain a default item with index 0 so i dont thing that could b a prob .

thanks
govind


jhoojharsinghyadav replied on Friday, September 21, 2007

Rocky,

I am using csla 3.0
I am working on to integrate validatino application blocks(VAB), DAAB, and caching application blocks with csla .

firstly moving with VAB here are the steps i had followed.
1. got the refrence of VAB,Common , from application blocks
2. created a class VAB with the following definition
 public class VABRules
    {
        public class VABRuleArgs : RuleArgs
        {
            private string _ruleset;

            public string Ruleset
            {
                get { return _ruleset; }
            }


            public VABRuleArgs(string propertyName)
                : this(propertyName, null)
            {
            }

            public VABRuleArgs(string propertyName, string ruleset)
                : base(propertyName)
            {
                _ruleset = ruleset;
            }
        }

        public static bool VABValid<T>(object target, RuleArgs e)
        {
            Validator<T> validator = ValidationFactory.CreateValidator<T>(((VABRuleArgs)e).Ruleset);

            if (validator == null)
                return true;

            ValidationResults results = validator.Validate(target);

            if (results == null)
                return true;

            foreach (ValidationResult result in results)
            {
                if (result.Key == e.PropertyName)
                {
                    e.Description = result.Message;
                    return false;
                }
            }

            return true;
        }
    }

now on csla object say currency

for one of my property .
  [NotNullValidator]
        [StringLengthValidator(1, 50, MessageTemplate = "Currency code can not be empty")]
   
        public string sCode
        {
            get
            {
                CanReadProperty(true);
                return _Code;
            }
            set
            {
                CanWriteProperty(true);
                if (value == null) value = string.Empty;
                if (_Code != value)
                {
                    _Code = value;
                    PropertyHasChanged();
                }
            }
        }

and finally in the

  protected override void AddBusinessRules()
        {
                ValidationRules.AddRule(VABRules.VABValid<Currency>, new VABRules.VABRuleArgs("sCode","RuleSetCurrency"));

        }


but this is not getting called and not firing validation . on contrary done with csla.validation it is working fine .

coould you please shed some light on the issue why i am not able to get the validation check .

thanks
govind

RockfordLhotka replied on Friday, September 21, 2007

I don’t know.

 

One possible issue: you aren’t using the NoInlining attribute in your property declaration, but you are using the CanReadProperty(), CanWriteProperty() and PropertyHasChanged() overloads that only reliable work if you DO use the NoInlining property.

 

Rocky

 

 

From: jhoojharsinghyadav [mailto:cslanet@lhotka.net]
Sent: Friday, September 21, 2007 7:23 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] ArgumentNullException in CommonRules.RegExMatch()

 

Rocky,

I am using csla 3.0
I am working on to integrate validatino application blocks(VAB), DAAB, and caching application blocks with csla .

firstly moving with VAB here are the steps i had followed.
1. got the refrence of VAB,Common , from application blocks
2. created a class VAB with the following definition
 public class VABRules
    {
        public class VABRuleArgs : RuleArgs
        {
            private string _ruleset;

            public string Ruleset
            {
                get { return _ruleset; }
            }


&nbs p;           public VABRuleArgs(string propertyName)
                : this(propertyName, null)
            {
            }

            public VABRuleArgs(string propertyName, string ruleset)
                : base(propertyName)
            {
                _ruleset = ruleset;
            }
        }

        public static bool V ABValid<T>(object target, RuleArgs e)
        {
            Validator<T> validator = ValidationFactory.CreateValidator<T>(((VABRuleArgs)e).Ruleset);

            if (validator == null)
                return true;

            ValidationResults results = validator.Validate(target);

            if (results == null)
                return true;

            foreach (ValidationResult result in results)
            {
                if (result.Key == e.PropertyName)
                {
                    e.Description = result.Message;
                    return false;
                }
            }

            return true;
        }
    }

now on csla object say currency

for one of my property .
  [NotNullValidator]
        [StringLe ngthValidator(1, 50, MessageTemplate = "Currency code can not be empty")]
   
        public string sCode
        {
            get
            {
                CanReadProperty(true);
                return _Code;
            }
            set
            {
                CanWriteProperty(true);
           &n bsp;    if (value == null) value = string.Empty;
                if (_Code != value)
                {
                    _Code = value;
                    PropertyHasChanged();
                }
            }
        }

and finally in the

  protected override void AddBusinessRules()
        {
                ValidationRules.AddRule(VABRules.VABValid<Currency>, new VABRules.VABRuleArgs("sCode","RuleSetCurrency"));

        }


but this is not getting called and not firing validation . on contrary done with csla.validation it is working fine .

coould you please shed some light on the issue why i am not able to get the validation check .

thanks
govind


jhoojharsinghyadav replied on Friday, September 21, 2007

hmm ,

seems as if i had to use the csla contrib library instead of validation application block .
but the only mess i m facing with is that i am nto able to throw custom messages if using the commonrules.
thats why i opted for validation blocks .

is there any workaround to get the custom message s.

1 most importatnt thing is that while being up in insert mode , say for example i do get up the validation rule exception the whole of the dataview is cleared mean the object is recreated fresh which i want to avoid mean i want that if error is there then the object does not get clear but instead stops processing if something is wrong there if with the data being retained (which is correct)

how to achieve this .

thanks
govind

RockfordLhotka replied on Friday, September 21, 2007

If you don’t like the messages returned from the rule methods in CommonRules then you can create your own rule methods – create your own common rules library within your application. This is the whole reason the architecture is so open and delegate-based, is to allow you to create your own rule methods to meet your needs.

 

I don’t understand what you are saying about the grid, sorry.

 

Rocky

 

From: jhoojharsinghyadav [mailto:cslanet@lhotka.net]
Sent: Friday, September 21, 2007 8:42 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: ArgumentNullException in CommonRules.RegExMatch()

 

hmm ,

seems as if i had to use the csla contrib library instead of validation application block .
but the only mess i m facing with is that i am nto able to throw custom messages if using the commonrules.
thats why i opted for validation blocks .

is there any workaround to get the custom message s.

1 most importatnt thing is that while being up in insert mode , say for example i do get up the validation rule exception the whole of the dataview is cleared mean the object is recreated fresh which i want to avoid mean i want that if error is there then the object does not get clear but instead stops processing if something is wrong there if with the data being retained (which is correct)

how to achieve this .

thanks
govind



jhoojharsinghyadav replied on Wednesday, September 26, 2007

Rocky,

i am working up with  a scenario .
suppose my users comes up with an insert mode in detail view and then successfully inserts the object .
now he wants to do more insertions like , go on inserting .till he wishes.
not getting over it .

thanks
govind

Copyright (c) Marimer LLC