Monday, 05 May 2008

Validators in Custom Configuration Sections

Today I was extending/cleaning/rewriting my Exception Handling library to take advantage of the new .NET 3.5 features.. It proved to be quite fun, so I started making it more useful, and easy to use.

At some point I decided to change the way I stored all the settings in the configuration file. Before I had my own configuration section, that used the standard AppSettingsSection class. Simple and fast. But it didn't look clean. All the settings were mixed up together etc etc..

So I created a clean new sectionGroup with several sections, collections and so on. When I reached the notification e-mail field, I thought that having a validator would be... A lot better :)

Strangely enough, when I added the RegexStringValidator, the application crashed, telling me my e-mail was not valid against the regular expression..

I simplified the RegExpression until I had this:

[RegexStringValidator(@".+")]
[ConfigurationProperty("mail", IsRequired = true, IsKey = true)
public String Mail
{
    get { return (String)this["mail"]; }
}

Where can it go simpler?

After some research online, I found more people with the same problem, but no solution. I did understand the problem though. When the value was validated against the regular expression, the value was empty. Now why the value was empty is beyond me, and I can't change it, so I went on.

After more testing, as well as System.Configuration source digging, I realized what the problem was, as well as the solution!

The problem was quite simple, actually. When an instance of my object was created, default values were assigned to all fields. When they were assigned - they were validated. The next time the value would be assigned is when it is read from the configuration file.

All I had to do is assign a valid value to the DefaultValue field, and it worked! Having IsRequired = true ensured that I will get a value from the configuration property, and the regular expression took care of the rest!

The end result:

[RegexStringValidator(@"^[a-zA-Z0-9%\.\-_]+\@[a-zA-Z0-9\.\-_]+\.[a-zA-Z]{2,4}$")]
[ConfigurationProperty("mail", IsRequired = true, IsKey = true, DefaultValue = "[email protected]")]
public String Mail
{
    get { return (String)this["mail"]; }
}