Custom ValidationException: Context set after message in debug mode

Jan 11, 2009 at 5:33 PM
Hi mikesaunders,

I just began using ValidationAspects and I love it so far. Very good work!

I followed your guidelines to write a new validation aspect including a custom exception and now I need to customize the exception message using ValidationSettings.FormatExceptionMessage, as I would like to know what is the name of the property using e.Context.Property.Name. More precisely:

ValidationSettings.FormatExceptionMessage.X( e=> string.Format( "{0}: blah-blah {1}", e.Context.Property.Name, e.Value );

This is when I noticed this strange behavior with Visual Studio: in debug, when my custom exception is thrown, the exception pop-up window displays the following message: '$exception.Message' threw an exception of type 'System.NullReferenceException'. Continuing execution yields the expected error message though, so it's not a major issue, but it's kinda funny for a developer to see this...

So I debugged it: override SetContext, place brakepoint where it begins, debug: SetContext is called after the pop-up is displayed, so it must be null before; hence the NullReferenceException in the pop-up window. Bad news is it happens also when customizing messages of built-in validation exceptions using ValidationSettings. I am really afraid this issue is related to VS or even PostSharp; maybe you have a clue on what is going on here?

To sum up:
1) use ValidationSettings to customize exception messages
2) throw validation exceptions (do not handle by user code, let VS catch and display them)

My setup: Visual Studio 2008 SP1, PostSharp 1.0 RTM
Coordinator
Jan 11, 2009 at 6:16 PM
Hi,
You haven't provided details on what client code was executing when this occured but I'd guess validation failed on a Parameter rather than a Property? Please let me know if I'm wrong. I can reproduce your issue when Parameter validation fails. This is because the Context.Property value is null (a property setter was not invoked) and your exception message function is calling the Name property on a null reference. To defend against this I recommend quering the Context for the values of Property, Parameter, and Method and getting the Name from one of these. I think it would be useful for Context to provide a "TargetName" property which did the query and returned a valid Name so I might put this in the next release.

Please let me know if this does/does not answer your issue.
Jan 11, 2009 at 6:33 PM
Edited Jan 11, 2009 at 6:44 PM
I wish it was that easy :) but he attribute target is an automatic property, and the Context itself is null ( using only e.Context.ToString() will get the NullReferenceException). I was wrong about one thing though: the behavior is only for custom exceptions, nothing wrong with built-in ones because there's no pop-up for these.

Btw: any hint on where should calls to ValidationSettings be made? Ideally when assembly is loaded or smth...
Coordinator
Jan 11, 2009 at 6:49 PM
Could you email me some source that can reproduce this issue? mike at mikesaunders dot com. Off the top of my head I can't think why this occurs. It is ok to see the popups, you can configure these notifications from menu item Debug=>Exceptions, but the null ref exception you report shouldn't occur so I'd like to investigate it.
Jan 11, 2009 at 7:32 PM
Done! Thanks, I'm curios too :)
Coordinator
Jan 12, 2009 at 1:19 PM
ok I have some answers for you.

Firstly, the '$exception.Message' threw an exception of type 'System.NullReferenceException' is thrown only when debugging because the debugger invokes the Message property on the exception immediately after it is constructed. This in turn calls your message format function which expects the exception Context to be non null. As you correctly identified, Context is null at this point. This is by design - the exception is constructed, thrown, and then when caught by VA, the context is assigned. Interestingly, if you build VA yourself so that VS is aware of the pdb, the NullReferenceException is not thrown. Regardless the exception popups are harmless although I agree a little annoying. You'll only see these though when debugging and a ValidationException is thrown.

To prevent VS from notifying you of when the validation exceptions are thrown, you can add the exception type to the VS Exceptions list and uncheck the User-unhandled check box. Navigate to menu item Debug => Exceptions. From your emailed example I added ValidationAspectsSample.ValidateAlwaysWrongException under 'Common Language Runtime Exceptions', unchecked User-unhandled, and no popup was presented when debugging the test.

Hope that helps. It is annoying that these exceptions are reported as unhandled when debugging even though they are not. An unfortunate result of using lambdas I guess.
Jan 12, 2009 at 3:44 PM
Thanks, this seems reasonable, I'll try your suggestion as soon as I have the chance.

What about the best place for updating validation settings? Could you give a hint on what would that be? (a static constructor, or a static method which you must call manually, or...)
Coordinator
Jan 12, 2009 at 4:34 PM
Personally I'm not a fan of placing application configuration/initialization in a static constructor. When configuring the app I want control on the ordering of configuration of different systems/modules and you can't do that with static constructors. By modules I mean a set of (ideally synergistic) components such as an assembly. So you may have a module that contains your domain objects and domain validators, or maybe the domain validators make up a separate module. You may need invoke module configuration in a particular order possibly due to dependency relationships.

When you configure VA is upto you but obviously it should be before any validators are invoked so maybe in the your apps entry point. I typically architect my apps into separate modules using Bloom IoC which provides this module configuration capability.
Jan 13, 2009 at 7:21 AM
Thanks again! I'll have a look at Bloom, sounds very interesting.