Exceptions in Validationrules

Exceptions in Validationrules

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


eDjinn posted on Friday, April 27, 2007

I would like to suggest a change in the exception handling of the validation rules.
When an exception occurs, it is quite difficult to find which validation is responsable for this error.

When a try-catch is added to the function
private void Csla.Validation.ValidationRules.CheckRules(List<IRuleMethod> list)

CSLA can provide us with more detailed information, like:

catch ( Exception _ex )     //Got conversion exception Int/String
{                          
        throw new Exception( string.Format( "Exception in {0} {1}", list[index].GetType().Name, list[index].RuleName ), _ex );
}

Depending on the exception Type, the exception might not be thrown, but instead the rule can be broken.

An exception occurred when I binded a StringMaxLenth rule on an int field. I had quite a hard time finding the field in question.

RockfordLhotka replied on Friday, April 27, 2007

Good idea, I've added it to the wish list.

david.wendelken replied on Tuesday, May 01, 2007

What section of code did you put the try block on?

eDjinn replied on Wednesday, May 02, 2007

Though I'm quite new to the CSLA concept (and C# for that matter), there are the changes i placed in the CSLA code:
In this last function (private void CheckRules(List<IRuleMethod> list)), you can place a try-catch in the for-loop:
            for ( int index = 0; index < list.Count; index++ )
                try {...}
                catch ( Exception _ex ){
                    System.Diagnostics.Trace.WriteLine(...);
                    throw new Exception( string.Format( "Exception in {0} {1}",
                        list[index].GetType().Name, list[index].RuleName ), _ex );
                }

I use CodeSmith to generate my CSLA-classes, but next to these default functions, properties and variables, I override the functions
In some cases, the IsValid function does not check all the rules again, resulting a false NotValid state. Using the override, I can check the rules manually.

I hope this helps...

david.wendelken replied on Wednesday, May 02, 2007

Thanks! 

 

 

RockfordLhotka replied on Wednesday, May 02, 2007

It may be worth noting that Clone() is already virtual in that there's a virtual/Overridable method called GetClone() that actually does all the work. If you want to alter the behavior of Clone() all you need to do is override GetClone(). (in version 2.1+)

Providing better exception detail for rule methods that generate exceptions is in the wish list, and may yet make it into 3.0 depending on time.

RockfordLhotka replied on Wednesday, May 02, 2007

OK, I'm looking seriously at this now, and this is an interesting issue - in particular, whether to throw a more detailed exception (that might be hard to find behind data binding), or to convert any exception into a broken rule.

I do wonder if it wouldn't be better to convert any exception into a broken rule - but to alter the rule's description text to reflect the details of the exception. The broken rule description would end up reading (in English) something like:

Validation rule xyz failed in property abc (<original exception message here>)

The advantage to this is that it would work nicely in Windows Forms and WPF, where exceptions are otherwise often silently captured by data binding, and can therefore be hard to find/fix.

The disadvantage to this is that you lose the stack trace and other exception detail.

The thing is, that even in cases where data binding does capture and display the exception, they only display the Message property in the tooltip. So in that case it is a wash as to whether I break the rule or throw an exception, because the tooltip would be better either way.

But in the cases where data binding just eats the exception, breaking the rule would produce a better result.

But then there's the ValidationRules.CheckRules() case, where data binding isn't even involved, and a good argument can be made that throwing an exception makes for the easiest debugging.

So I'm open to suggestions one way or the other here. Throw a more detailed exception? Or break the rule and override the Description with the exception details?

david.wendelken replied on Wednesday, May 02, 2007

RockfordLhotka:

Validation rule xyz failed in property abc (<original exception message here>)

That's a useful message format!

RockfordLhotka:

So I'm open to suggestions one way or the other here. Throw a more detailed exception? Or break the rule and override the Description with the exception details?

Maybe you should do both, and either let context decide, or provide a configuration option for the developer to choose from?

While you're looking at refactoring the rules handling, take a look at this thread. Thanks!

http://forums.lhotka.net/forums/thread/14396.aspx

eDjinn replied on Wednesday, May 02, 2007

I see the problem with Exception or BrokenRules.
What I see in my own code is an Exception on a default rule MaxStringLength there the object is an int type, not a string. The Exception reads something like (translated from dutch): Cannot implicitly convert from int to string.
Because I was filling the BusinessListBase descendent directly, assigning field values directly in the BusinessBase descendent, I got this exception when I tried to BusinessListBase.Save()

For this reason, it doesn't mather to me much if it will be an exception or a broken rule. It would be nice if I could see in the catch or in the brokenrules collection what rule on what field/property of what record (protected override object BusinessBase.GetIdValue()) the problem occurs.

If the sollution is either Exception or Brokenrule, one should handle it.

What I meant with the Exception type, in case of a conversion Exception, it is obviously an error caused by the programmer. Then, it would be best to keep it as an Exception (easier debugging).
It it's a problem caused by a user, it would be better if it would be a broken rule (not loose anything the user typed).

I'm not sure it the latter is even possible (that is, if it's possible to get an exception if the programmer did not make a mistake creating/assigning rules).

Hope this helps...

RockfordLhotka replied on Wednesday, May 02, 2007

You have a good point - an unhandled exception from a rule method should be a developer issue, not a user issue. In other words, a developer really shouldn't allow unhandled exceptions to occur in a rule method, so this issue should occur during development and testing, not really at runtime.

Regardless, it should be easy for the developer to use the resulting detail. There are various scenarios:

  1. PropertyHasChanged is called in a web app, web service, WCF service or workflow
  2. PropertyHasChanged is called in a Windows app with data binding
  3. PropertyHasChanged is called in a Windows app without data binding
  4. PropertyHasChanged is called in a WPF app with data binding
  5. PropertyHasChanged is called in a WPF app without data binding
  6. ValidationRules.CheckRules is called

In 1, 3, 5 and 6 throwing a detailed exception works great. In all these cases the developer (typically the UI developer) would get the exception directly and would see the full details of the issue.

In 2 sometimes the exception would appear, but other times data binding eats the exception. In this case the broken rule solution may be superior.

In 4 either approach is technically workable. The UI developer can write their XAML such that they see a broken rule (using csla:ValidationPanel and appropriate UI styling), or an exception (using the WPF exception control and appropriate UI styling).

Hmm. Putting it like this is useful, because only 2 has an issue with the exception approach, and then only sometimes. So clearly the exception approach offers the best solution to the widest range of scenarios.

Copyright (c) Marimer LLC