Monthly Archives: December 2008

Validation in ASP.NET MVC – part 4: example with server-side and client-side validation

This is part 4 of a series of posts. See also:

In the previous posts, I described how we implemented model-based validation on the server-side in Cuyahoga with ASP.NET MVC and as the icing on the cake, we also added some client-side validation (also model-based).

Now, everything can be found in the Cuyahoga SVN sources but I have to agree that it can be a daunting task to check out the complete sources and find all pieces of the validation puzzle. Therefore, I’ve created a little sample application with everything from the previous posts combined.

validation-sample-app

Hopefully, this will make things a little bit clearer. You can download the sample app here. Visual Studio 2008 and ASP.NET MVC Beta are required.

Enjoy!

Validation in ASP.NET MVC – part 3: client-side validation with jquery validation

This is part 3 of a series of posts. See also:

In the first two parts, I showed how you can perform validation on the server side with Castle Validation attributes and extend that model with custom validation logic. With this, we have everything we need to properly validate our model.

For a better user experience though, it would also be nice that we could re-use (part of) our validation logic on the client-side. Luckily, lots of others have already looked into this and the only thing I had to do was to throw everything together and stir it a little bit :) .

The ingredients are:

How it works

client-side-validation-1

  1. The client-side validation is called via an HtmlHelper extension method ClientSideValidation:
    <%= Html.ClientSideValidation(ViewData.Model, “my_form_id”)%>;
  2. The HtmlHelper extension requests an instance of a BrowserValidationEngine that returns the client script for validation;
  3. BrowserValidationEngine has a reference to an IValidatorRegistry instance that returns all (Castle) validators for the given model;
  4. For each validator, the referenced IBrowserValidatorProvider generates the appropriate client script;
  5. Finally, all generated client script code is combined and sent to the browser in a single javascript block.

The existing Monorail codebase proved to be of great value and could be used almost seamlessly. The only difference is the way the client code is generated. Originally, the validators generated css class attributes for the Monorail form helpers, but we don’t have those with ASP.NET MVC, so all client code is generated as jQuery validation rules.

Below, you can see the output of the validation helper for the new user form in Cuyahoga:

<script type="text/javascript">
$(document).ready(function() {
    jQuery.validator.addMethod('notEqualTo', function(value, element, param) { return value != jQuery(param).val(); }, 'Must not be equal to {0}.' );
    jQuery.validator.addMethod('greaterThan', function(value, element, param) { return ( IsNaN( value ) && IsNaN( jQuery(param).val() ) ) || ( value > jQuery(param).val() ); }, 'Must be greater than {0}.' );
    jQuery.validator.addMethod('lesserThan', function(value, element, param) { return ( IsNaN( value ) && IsNaN( jQuery(param).val() ) ) || ( value < jQuery(param).val() ); }, 'Must be lesser than {0}.' );
    jQuery.validator.addMethod('numberNative', function(value, element, param) { return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:\,\d+)?$/.test(value); }, 'Not a valid number.' );
    jQuery.validator.addMethod('simpleDate', function(value, element, param) { return this.optional(element) || /^\d{1,2}\-\d{1,2}\-\d{4}$/.test(value); }, 'Not a valid date.' );
    $("#userform").validate({
        rules : {
            UserName: {  rangelength: [1, 50] , required: true },
            Password: {   required: true , rangelength: [5, 50] , equalTo: "#PasswordConfirmation" },
            PasswordConfirmation: {   equalTo: "#Password" , rangelength: [5, 50] , required: true },
            FirstName: { rangelength: [1, 100] },
            LastName: { rangelength: [1, 100] },
            Email: {   required: true , rangelength: [1, 100] , email: true },
            Website: { rangelength: [1, 100] }
        },
        messages : {
            UserName: {  rangelength: "The username must be between 1 and 50 characters" , required: "The username may not be empty" },
            Password: {   required: "The password may not be empty" , rangelength: "The password must contain at least 5 characters" , equalTo: "The password must be the same as the confirmation password" },
            PasswordConfirmation: {   equalTo: "The password must be the same as the confirmation password" , rangelength: "The password must contain at least 5 characters" , required: "The password confirmation may not be empty" },
            FirstName: { rangelength: "The firstname must be between 1 and 100 characters" },
            LastName: { rangelength: "The lastname must be between 1 and 100 characters" },
            Email: {   required: "E-mail address may not be empty" , rangelength: "E-mail address must be between 1 and 100 characters" , email: "Invalid e-mail address" },
            Website: { rangelength: "The website url must be between 1 and 100 characters" }
        }
    });
});
</script>

which results in this:

client-side-validation-2

Summarizing validation

In this series of posts, I showed how we deal with validation in Cuyahoga and ASP.NET MVC. Personally, I think the nicest part of it is that we have our validation rules centralized and we only have to add one line of code to the view to enable client-side validation.

The code can be found in Cuyahoga SVN and more specifically in the validation sections and the ASP.NET MVC manager. I’ll try to make a standalone sample project with all the validation stuff somewhere in the near future.

Embrace the impedance mismatch

Maybe I’m a bit of a masochist, but I enjoy a good flamewar at times. For that reason, I still have TheServerSide.com in my bookmarks to check out what our Java friends are bitching about. My favorite subjects are ‘the new web framework of the month’ and the occasional persistence framework rants. Today, I checked TheServerSide to see a post with the subject “Criticism of Java Persistence Frameworks” that had a promising 46 comments. Yummie!

The comments were a little bit disappointing for my taste, but one from Robert Pappas was very interesting:

The gap between stateless HTTP and OOP is nearly as wide as the gap between OOP and RDMS.
This is why we have at least 6 major Web Frameworks for Java…and all of them have serious drawbacks (from my experience anyway).
But yes, your concerns are valid. There is a mis-match, and I’m not sure if it can be address in a seamless way. (Without switching to Object Databases)

And he’s right! The impedance mismatch that people often talk about, also exists in web programming. So instead of one impedance mismatch we have to deal with at least two of them! That makes a developers life even worse, according to the rest of the comment.

holygrailWhat struck me about this comment is the negative tone that might have been caused by frustrations when trying to bridge the gaps between relational databases, OO and web programming. Lots of developers are constantly searching for the one and only Holy Grail of Software Development and get frustrated when it appears that what they found is all but the Holy Grail.

Embrace it

One day, I came to the conclusion that the Holy Grail of Software Development doesn’t exist and that made developing software so much more fun. It’s just the mind set! Accept it and embrace it, stop searching for the Holy Grail and use the tools that help to embrace the mismatch instead of fighting it.

Back to .NET web application development: choose a good O/R mapping solution and something like ASP.NET MVC or Monorail. Definitely not the Holy Grail, but these tools embrace the impedance mismatch and that sure made development less frustrating and much more fun!

Hidden jewels in the Castle stack: Transaction Services

In Cuyahoga, we’re using a lot of components from the Castle stack. Some of the most brilliant components are the transaction services combined with the automatic transaction facility.

With this post, I’m trying to bring some well-deserved attention to these undervalued components.

The Context

Today, I was working on management of sites. In Cuyahoga 2.0, every site has its own set of content folders and templates. Now when creating a new site, we have to perform the following steps:

  1. Save the new site object in the database;
  2. Create a folder structure for the new site;
  3. Copy the selected system template objects to the new site and save in the database;
  4. Copy the template files that belong to the copied template objects to the templates folder of the site.

All steps have to be completed before we can start management of the new site, like adding pages and custom templates. Obviously, you’d like this series of steps to be completed  in a single transaction, so when something goes wrong somewhere, we don’t end up with a broken site.

As you might have noticed, the transaction also includes file operations and we all have probably experienced situations where the database and the file system were out of sync because something went wrong, either in the database, or with the file system.

Enter Castle Transactions

Castle Transaction Services makes it possible to run any arbitrary piece of code within the scope of a transaction. Components that are called in a transaction can support those transactions by requesting the current transaction via a transaction manager. This makes it very easy to write your own components that are transaction-aware.

Transactional file operations: don’t let the database and file system go out of sync

For file operations, we created a simple service that performs common file operations like writing new files, copying files and creating folders. When performing an operation, the service checks if there is a current transaction and if so, the actual operation is delegated to a class that performs the actual transactional operation. An excerpt of our transactional fileservice:

public void CopyFile(string filePathToCopy, string directoryToCopyTo)
{
    ITransaction transaction = ObtainCurrentTransaction();
    if (transaction != null)
    {
        FileWriter fileWriter = new FileWriter(this._tempDir, transaction.Name);
        transaction.Enlist(fileWriter);
        fileWriter.CopyFile(filePathToCopy, directoryToCopyTo);
    }
    else
    {
        File.Copy(filePathToCopy, Path.Combine(directoryToCopyTo, Path.GetFileName(filePathToCopy)), true);
    }
}

In the example above, the FileWriter class performs the transactional file operations by implementing an IResource interface that has three methods: Start(), RollBack() and Commit(). The CopyFile() method copies the file to a temporary location. When the transaction manager commits the transaction, the Commit() method of the FileWriter is called and the file is copied from the temporary location to the actual location. RollBack() removes the temporary file.

The complete implementation of the file service can be found in Cuyahoga SVN at https://cuyahoga.svn.sourceforge.net/svnroot/cuyahoga/trunk/Core/Service/Files. Note that the implementation is very basic and there’s much room for improvement but it already saved us lots of time when we didn’t have to clean up the mess when something went wrong.

Automatic transactions

One of the really great features of the Castle transaction services is that you just have to decorate your method with an attribute and everything is executed within the context of a transaction:

[Transaction(TransactionMode.RequiresNew)]
public virtual void CreateSite(Site site, string siteDataRoot, IList<Template> templatesToCopy, string systemTemplatesDirectory)
{
    // 1. Save new site object in the database.
    ..

    // 2. Create site directories.
    ..

    // 3. Copy template objects to new site and save in database.
    ..

    // 4. Copy template files to site templates directory.
    ...
}