Showing posts with label Enterprise Library 3. Show all posts
Showing posts with label Enterprise Library 3. Show all posts

Thursday, April 19, 2007

LINQ to Validation

I spent the weekend looking at the Enterprise Library 3.0 validation block. It's fantastic and long overdue. Developing this library was a no-brainer. I wrote something similar (though much less ambitious) as soon as I learned to use attributes in C# 1.0. Although it is a great framework as is I can't help but imagine ways in which LINQ could make it even better.

Validation has annoyed me more than any other problem with perhaps the exception of the object-relational mismatch . Validation logic should be applied at every tier: client, server, and database. However writing and maintaining the same validation rules in Javascript, a server-side language, and then again in SQL is so labour-intensive and thankless that I suspect few people actually do it.

Several attempts have been made to solve this problem in the past with limited success. Some code generators allow you to express business rules in a domain-specific language which is then translated into various target languages. There have also been attribute-based solutions that use XSL as the validation language. The problem with all these solutions is that they force the developer to use yet another language. This is necessary because the language has to be able to be expressed as data so that it can be analysed and converted into other languages. Unfortunately this means that the validation language has to be stored in config files or strings putting it out of reach of the type checking and refactoring tools available in most IDEs. Does this problem sound familiar? It should. It's the same problem we have with data access code today.

Now that LINQ is coming we will have two languages that are powerful enough to express any kind of validation rule, will have full IDE support, and can also be converted into data and thus into other languages: VB.NET and C#.

LINQ is the gift that keeps on giving. As I've written in this blog many times before, the applications for turning code into data extend far beyond improving database integration. Let's examine the ASP.NET PropertyProxyValidator control that comes with the validation block in EL3. You associate it with a property on an object and when the user attempts an action it does a server postback, calls the EL3 Validator object, and displays an error if one is encountered. This keeps you from having to create a custom validator control that performs the same validation you are already doing in your business object. However most validation (regular expression validation, string length validation) can be done in client-side code. The postback is unnecessary. Unfortunately performing the validation on the client-side means writing Javascript as well as server-side code (after all, the user's browser may have javascript turned off). Now imagine that, post-LINQ, a new validation attribute called ExpressionValidatorAttribute is added to the EL3 validation block:

public ZipCodeValidatorAttribute : ExpressionValidatorAttribute<string>
{
public override Expression<Func<string,bool>> GetExpression()
{
return x => new Regex(@"[0-9][0-9][0-9][0-9][0-9]").IsMatch(x);
}
}

Notice that we are returning a validation function as an Expression which means that it instead of returning a delegate it will return a data representation of the function. An ASP.NET validator control could retrieve the expression using reflection and convert it to the following Javascript function without breaking a sweat:

function (x){
return /[0-9][0-9][0-9][0-9][0-9]/.exec(x) != null;
}

It could then run this function on the client-side, avoiding a postback. On the server-side the validation object would just compile the expression and run it (which could be done once and cached). This would allow us to use the same code for validation on the client and server-side!

Javascript is actually a very powerful functional language. You can even translate LINQ queries to it without much effort. In fact the only validations that could not be converted to Javascript would be those that require access to some server-side resource. In practice this is rare.

Almost all validation logic is functional because it doesn't modify the state of the objects it inspects. It takes some data as an input and returns a single boolean. Therefore most validation can be expressed using lambda functions and can therefore be converted to lambda expressions. Voila! We've solved the problem of duplicated validations without having to rewrite code in different languages, learn a new language, or leave the comfort of Visual Studio.

About Me

My photo
I'm a software developer who started programming at age 16 and never saw any reason to stop. I'm working on the Presentation Platform Controls team at Microsoft. My primary interests are functional programming, and Rich Internet Applications.