Saturday, July 14, 2012

How to build a grid with knockout - Part 3: Sorting and Styling

In Part 3 of this tutorial we're going to add the ability to sort the data in the grid by a particular column in ascending or descending order. The sorting is going to take place on the server and is going to work in conjunction with the paging that we implemented in Part 2. I've have also added some styling to the grid so the final result will look as follows:



Step 1 - The Javascript
Within our javascript view model I've added a method SetOrder() that can will be called when the user clicks on a column header, this looks as follows:

    function SetOrder(data, event, colName) {
        if (_this.colName === colName) {
            _this.switchSortOrder();
        } else {
            _this.colName = colName;
            _this.sortOrder = "asc";
        }
        setTHClass(event);
        loadDataFromServer();
    } 
 
     _this.SetOrder = SetOrder; 
 


The first thing the code does is check if we're already sorting by the column that has been clicked, if so we reverse the sort order. If this is the first time is has been clicked we set the sort order to ascending. This is a good example of how we can use the member properties of the view model, _this.colName and _this.sortOrder, to remember the state of the grid in between actions.

Once we've ascertained the column we're sorting by and the direction we can call the setTHClass() function to show the correct icon for the sorting column. The code for this looks as follows:

   function setTHClass(event) {
        //remove the existing classes
        $(event.currentTarget).parent().find(".sort_wrapper").children("span").removeClass("asc");
        $(event.currentTarget).parent().find(".sort_wrapper").children("span").removeClass("desc");
        if (_this.sortOrder === "asc") {
            $(event.currentTarget).children(".sort_wrapper").children("span").addClass("asc");
        } else {
            $(event.currentTarget).children(".sort_wrapper").children("span").addClass("desc");
        }
    }
 

 
We make use of css classes asc and desc to show the correct icon on the sorting column. The code first removes all traces of these classes from the columns and then adds the correct one where required. Extensive use of JQuery DOM traversal functions are used to make this task easier.

The other major change is in the loadDataFromServer() function where we now have to pass information to the server specifying how the data is to be sorted, this is done by adding the querystring parameters sidx and sord to the url that we post to the server:

function loadDataFromServer() {
            var url = '/people/data';
            //add paging params
            url += '?rows=' + _this.rowsPerPage() +
            '&page=' + _this.page() +
            //add sorting params     
                           '&sidx=' + _this.colName +          
                           '&sord=' + _this.sortOrder;
 
             $.post(
                url,
                function (data) {
                    _this.records(data.TotalRowsCount);
                    _this.totalPages(data.TotalPageCount);
 
                    var results = ko.observableArray();
                    _this.people.removeAll();
 
                    ko.mapping.fromJS(data.GridData, {}, results);
                    for (var i = 0; i < results().length; i++) {
                        _this.people.push(results()[i]);
                    };
                },
                'json'
            )
        }

Step 2 - The Controller
Now we need to modify the controller to make use of the additional querystring parameters that are being passed through. The first task is to sort our data by the requested column, this can be done by using a set of dynamic linq helpers that Scott Gu blogged about, it's all contained in one file that you will need to download and add to your project. You will also need to add a using clause of System.Linq.Dynamic to your controller class.

Once you have done that we can change our controller code to look as follows:

   public JsonResult Data(int rows, int page, string sidx, string sord)
        {
            IQueryable<Person> qryPeople = GetPersonQuery();

            GridDataResult gridDataResult = new GridDataResult();
            gridDataResult.TotalRowCount = qryPeople.Count();
 
            int totalPages = 1;
            if (rows > 0)
            {
                totalPages = gridDataResult.TotalRowCount / rows;
                if (gridDataResult.TotalRowCount % rows != 0)
                    totalPages += 1;
            }
 
            gridDataResult.TotalPageCount = totalPages;
 
            //now do the sorting
            qryPeople = qryPeople.OrderBy(sidx + " " + sord);
 
            gridDataResult.GridData = qryPeople
                .Skip((page - 1) * rows)
                .Take(rows);
 
            return Json(gridDataResult);
        }

Because we are now using the Dynamic Linq helpers we can order qryPeople using strings, perfect for doing sorting!

Step 3 - The Html
 The final step is modifying the html to make sure that when a column header is clicked the view model is notified to that we can reorder the grid. We do this by binding to the table header using knockout as follows:

<thead>
<tr>
    <th data-bind='click: function(data, event) { SetOrder(data, event, "FirstName")}'>
        <div class="sort_wrapper">First Name<span class="grid_order ui_icon"></span></div>
    </th>
    <th data-bind='click: function(data, event) { SetOrder(data, event, "LastName")}'>
        <div class="sort_wrapper">Last Name<span class="grid_order ui_icon"></span></div>
    </th>
    <th data-bind='click: function(data, event) { SetOrder(data, event, "Age")}'>
        <div class="sort_wrapper">Age<span class="grid_order ui_icon"></span></div>
    </th>
</tr>
</thead> 
 
We now have a grid that supports paging, sorting and has been nicely styled. If you would like to download the code you can do so here.

Friday, April 6, 2012

ASP.net MVC - Handling json dates with a custom converter.

Handling dates in json can be a real pain as it has no concept of a date datatype - however by using the jQuery ajax() method and specifying a custom converter you can easily turn dates sent from the server into Date objects on the client.

A date when it comes down from the server in json format looks like this:

"BirthDate":"\/Date(1507546800000)\/"

 What is nice about this rather unfriendly format is that is has the /Date prefix (the backslashes are escape chars in json), this means we can look at a string and determine whether we should treat is as a date or not.

I typically use the jQuery ajax() method ($.ajax) to get a json payload from the server. By default if you specify a dataType of 'json' the ajax() method will use an inbuilt converter to turn the returned json string into a javascript object. Fortunately this method also takes a converters object which we can use to parse and transform the json before it is passed to the success() method.

In order for our converter to be called we need to specify a particular datatype - this cannot be one of the default in-built ones or it will be ignored  (such as json) - in this instance I've called mine jsonWithDates. When you specify your converter the first option is a string which says what you're converter is going to take in and return. You need to provide two values in the string separated by a a space (this feels a bit clumsy!). In this case I've specified "text jsonWithDates" because I specified that the dataType I want to deal with is "jsonWithDates" and I want "text" passed into my converter. When the response is received from the server jQuery will look at the converters and see that I have a converter that knows how to do the necessary conversion. Be warned that if you specify "json jsonWithDates" your converter will be passed a javascript object to convert and not a json string as jQuery will do a conversion for you implicitly, that's why I've used "text jsonWithDates".

Ok - so now we know how to hook into the pipeline and set up a converter, that's the hard part done! The second option in the converter object is a function that takes in the payload from the response and provides a converted response. It's up to you now to handle the transformation as you see fit. For my purposes I've used the JSON.parse() method which handily takes in a function that we can use to map individual values when parsing json. In my function I do a check to see if it is a date using a regular expression, if it passes I convert it to a javascript date object and return it.
 
 
Now in my success method I will receive a javascript object that has properties that are of type Date. The full code looks like the following:
 
function LoadDataFromServer() {
        $.ajax({
            url: GetGridURL(),
            type: 'GET',
            dataType: 'jsonWithDates',
            contentType: 'application/json:charset=utf-8',
            //add a custom converter to handle dates and the way 
            //they are sent back from the
            //server in .net
            converters: {
                "text jsonWithDates":
                function (jsonText) {
                    return JSON.parse(jsonText, function (key, value) {
                        // Check for the /Date(x)/ pattern
                        var match = /\/Date\((\d+)\)\//.exec(value);
                        if (match) {
                            var dateIn = new Date(parseInt(value.substr(6)));
                            return dateIn;
                        }
                        // Not a date, so return the original value
                        return value;
                    });
                }
            },
            success:
                function (data) { alert(data);  }
        });
    }
} 
Json date conversion - done!

Saturday, March 24, 2012

How to build a grid with knockout - Part 2: Paging

In Part 1 of this tutorial we built a simple HTML table using knockout, in this post we're going to add paging functionality to it.

The code for the entire index.cshtml view now looks as follows:
@{
    ViewBag.Title = "Index";
}
 
<h2>Index</h2>
 
<table id="people">
    <thead>
    <tr>
        <th>First Name</th>
        <th>Last Name</th>
        <th>Age</th>
    </tr>
    </thead>
    <tbody data-bind="foreach: people">
        <tr>
            <td><span data-bind="text: FirstName"></span></td>
            <td><span data-bind="text: LastName"></span></td>
            <td><span data-bind="text: Age"></span></td>
        </tr>
    </tbody>
</table>
<div class='grid_footer ui-helper-clearfix'>
    <div class='grid_info'>
        <span data-bind='text: pagesText'></span>
    </div>
    <div class='paging'>
        <a data-bind='visible: page() > 1, click: PageFirst' class='ui-button'>First</a>
        <a data-bind='visible: page() > 1, click: PageBack' class='ui-button'>Previous</a>
        <a data-bind='visible: page() < totalPages(), click: PageNext' class='ui-button'>Next</a> 
        <a data-bind='visible: page() < totalPages(), click: PageLast' class='ui-button'>Last</a>
    </div>
</div>
 
 
<script type="text/javascript">
    function peopleViewModel() {
        var _this = {};
 
        //pager data
        _this.page = ko.observable(1);
        _this.records = ko.observable(1);
        _this.totalPages = ko.observable(1);
        _this.rowsPerPage = ko.observable(1);
        _this.pagesText = ko.computed(function () { return _this.page() + 
        " of " + _this.totalPages() + " pages"; });

        _this.people = ko.observableArray();
 
        /************************
        Public Functions
        ************************/
 
        function PageFirst(item) {
            _this.page(1);
            LoadDataFromServer();
        }
 
        _this.PageFirst = PageFirst;
 
        function PageLast(item) {
            _this.page(_this.totalPages());
            LoadDataFromServer();
        }
 
        _this.PageLast = PageLast;
 
 
        function PageBack(item) {
            _this.page(_this.page() - 1);
            LoadDataFromServer();
        }
 
        _this.PageBack = PageBack;
 
        function PageNext(item) {
            _this.page(_this.page() + 1);
            LoadDataFromServer();
        }
 
        _this.PageNext = PageNext;
 
        function LoadDataFromServer() {
            var url = '/people/data';
            //add paging params
            url += '?rows=' + _this.rowsPerPage() +
            '&page=' + _this.page();
 
            $.post(
                url,
                function (data) {
                    _this.records(data.TotalRowsCount);
                    _this.totalPages(data.TotalPageCount);
 
                    var results = ko.observableArray();
                    _this.people.removeAll();
 
                    ko.mapping.fromJS(data.GridData, {}, results);
                    for (var i = 0; i < results().length; i++) {
                        _this.people.push(results()[i]);
                    };
                },
                'json'
            )
        }
 
        /************************
        Initialization
        ************************/
 
        ko.applyBindings(_this, $("body").get(0));
        LoadDataFromServer();
 
        return _this;
    }
 
    var viewModel = peopleViewModel();
 
</script>


Step 1 - The HTML
If you look at the listing above you'll see I've added a <div> below the <table>, this is where the elements of the pager are going. Within the <div> I've added four <a>s for each of the paging buttons that will be required and a <span> to show some text. I've also introduced some new knockout binding methods: visible which determines if a span will be shown or not, and click which will call a function on our javascript model when the <a> is clicked.

Step 2 - The Javascript
Within our javascript view model I've added observables to track the information that we need to make the pager work. I've also added a pagesText variable which is a ko.computed() function. This means that when any of the observables that the function references are changed knockout will do a rebind, this is paricularly usefull in this instance.

The other major change is in the LoadDataFromServer() function where we now get an object back from the server that not only contains the rows for the grid but paging information including the total number of rows and the total number of pages.

I've set the number of rows per page in this instance to 1 so that the paging functionality is obvious with only 3 rows!

Step 3 - The Controller 
The code for the controller method now looks as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace knockoutGrid.Controllers
{
    public class PeopleController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
 
 
        public JsonResult Data(int rows, int page)
        {
            List<Person> people = new List<Person>();
            people.Add(new Person("Richie""McCaw", 33));
            people.Add(new Person("Dan""Carter", 32));
            people.Add(new Person("Owen""Franks", 23));
 
            GridDataResult gridDataResult = new GridDataResult();
            gridDataResult.TotalRowCount = people.Count;
 
            int totalPages = 1;
            if (rows > 0)
            {
                totalPages = gridDataResult.TotalRowCount / rows;
                if (gridDataResult.TotalRowCount % rows != 0)
                    totalPages += 1;
            }
 
            gridDataResult.TotalPageCount = totalPages;
            gridDataResult.GridData = people.Skip((page - 1) * rows).Take(rows);
 
            return Json(gridDataResult);
        }
 
    }
 
 
    public class GridDataResult
    {
        public int TotalRowCount { getset; }
        public int TotalPageCount { getset; }
        public object GridData { getset; }
    }
 
    public class Person
    {
        public string FirstName { getset; }
        public string LastName { getset; }
        public int Age { getset; }
 
        public Person(string firstName, string lastName, int age)
        {
            this.FirstName = firstName;
            this.LastName = lastName;
            this.Age = age;
        }
    }
 
} 





I've added a class called GridDataResult - this will enable us to send some more information about the paging back to the browser, because I want to use this class for all my controller methods that return data to a grid I have made the GridData property of type object (you could use generics if you wanted to). The MVC JSON serializer has no problems with serializing this into JSON properly.

The GridData() controller method is still straight forward with some added logic to work out the total rows and pages for the grid. The LINQ methods skip() and next() are used to get the correct subset of the data to be sent back . If you are using a database framework that supports LINQ (such as the Entity Framework) to retrieve your records from a database this is particularly usefull.

And that's it! A grid with paging - done!

How to build a grid with knockout and ASP.Net MVC


Fairly recently the team at CBS decided to adopt knockout to help us build our UIs. One of our major undertakings was to replace the JQGrid with a knockout equivalent, we haven't regretted it for a minute. The ability to quickly adapt the functionality to meet the different demands of our various clients plus the ability to style easily and effectively (a big gripe with the JQGrid)  has paid off handsomely.

This tutorial is broken into 3 parts:
Part 1 - building the basic HTML table using knockout and loading data from the server
Part 2 - implementing paging
Part 3 - implementing sorting


In this tutorial I'm going to take you through building a basic html table using knockout and retrieving data from a controller method on the server.

Step 1 - Install the knockout and knockoutMapping js files
You can either download these from the knockout website or use NuGet - if you're using NuGet then you need to install the knockoutjs package and the knockout.mapping package this will add a couple of js files to the scripts folder in your solution.

Once you have the js files added you need to reference them, I normally add them to my _Layout.cshtml file as I use them on virtually every page in my applications. Your _layout.cshtml file should look as follows:

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/knockout.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/knockout.mapping-latest.js")" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <div id="header">
            <div id="title">
                <h1>My MVC Application</h1>
            </div>
            <div id="logindisplay">
                @Html.Partial("_LogOnPartial")
            </div>
            <div id="menucontainer">
                <ul id="menu">
                    <li>@Html.ActionLink("Home""Index""Home")</li>
                    <li>@Html.ActionLink("About""About""Home")</li>
                    <li>@Html.ActionLink("People""Index""People")</li>
                </ul>
            </div>
        </div>
        <div id="main">
            @RenderBody()
        </div>
        <div id="footer">
        </div>
    </div>
</body>
</html>
 
Step 2 - Build a ViewThe view I added for this demo is called Index.cshtml and lives in a Views/People folder. The code looks as follows:

@{
    ViewBag.Title = "Index";
}
 
<h2>Index</h2>
 
<table id="people">
    <thead>
    <tr>
        <th>First Name</th>
        <th>Last Name</th>
        <th>Age</th>
    </tr>
    </thead>
    <tbody data-bind="foreach: people">
        <tr>
            <td><span data-bind="text: FirstName"></span></td>
            <td><span data-bind="text: LastName"></span></td>
            <td><span data-bind="text: Age"></span></td>
        </tr>
    </tbody>
    
</table>
 
<script type="text/javascript">
    function peopleViewModel() {
        var _this = {};
 
        _this.people = ko.observableArray();
        ko.applyBindings(_this, $("#people").get(0));
 
        function LoadPeopleFromServer() {
            $.post(
                '/people/data',
                function (data) {
                    var results = ko.observableArray();
                    ko.mapping.fromJS(data, {}, results);
                    for (var i = 0; i < results().length; i++) {
                        _this.people.push(results()[i]);
                    };
                },
                'json'
            )
        }
 
        LoadPeopleFromServer();
 
        return _this;
    }
 
    var viewModel = peopleViewModel();
 
</script>
 
 
I've kept the HTML and Javascript in one file in order to make this easy to follow. If you have no experience of knockout I would strongly suggest you follow the excellent interactive tutorial on the knockout site. The HTML is vanilla knockout, it uses the data-bind attribute to specify how knockout binds values on the javascript model to DOM elements.

The javascript is more interesting: you'll notice that the peopleViewModel() object has a property _this.people which is an observableArray, this means that knockout will take notice when elements are added and removed from it and update the DOM accordingly. The LoadPeopleFromServer() method makes use of the jQuery ($.post) method to retrive data from the server in a JSON format, this JSON is returned to us as an array of javascript objects by JQuery, this is then taken by the knockout mapping utility and turned into an ko.observableArray of javascript objects. The beauty of using the mapping utlity is that we don't have to create any javascript objects to represent people, this is all done for us! This also has the advatage that if we add a new property to a person object on the server we don't need to change any javascript, only the HTML where we want the new value shown.

You may wonder why _this.people has been declared and we then push objects into it once they have returned from the server rather than just passing it into the mapping method. The reason for this is that the mapping method creates a new observableArray and assigs it to the variable you passed in. This ruins your knockout bindings as they were bound to the original array that you declared. You can get around this by only binding once you have got data back from the server but this gets more complicated once you introduce paging, etc. This pattern works and is easy to follow and implement.

Step 3 - The Controller Method
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace knockoutGrid.Controllers
{
    public class PeopleController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
 
 
        public JsonResult Data()
        {
            List<Person> people = new List<Person>();
            people.Add(new Person("Richie""McCaw", 33));
            people.Add(new Person("Dan""Carter", 32));
            people.Add(new Person("Owen""Franks", 23));
 
            return Json(people);
        }
 
    }
 
    public class Person
    {
        public string FirstName { getset; }
        public string LastName { getset; }
        public int Age { getset; }
 
        public Person(string firstName, string lastName, int age)
        {
            this.FirstName = firstName;
            this.LastName = lastName;
            this.Age = age;
        }
    }
 
}

The controller code is relatively simple, normally I would be retrieving data from a database but here I've hard coded it. The only things you really need to take heed of are the use of the JsonResult type that is being returned and the Json method that is needed to turn the list of people into valid JSON.

In Part 2 I will show you how to implement paging!

I have put the source code up on bitbucket, you can download it here.

Thursday, November 10, 2011

How to add offline functionality to your web pages using ASP.net MVC

I was recently tasked with creating an iPad client for our online survey product Prospero . My initial thoughts were that I was going to have to buy a Mac and a book on iPad programming, however after a bit of thought I realised that I could potentially use HTML5 and a combination of its offline caching and local storage capabilities.

The first issue that needs to be covered is geting the web browser to cache a version of a web page and all its required resources (images, scripts, etc) locally. Web browsers do this a lot of the time anyway in order to optimise performance, however in order for them to be used in an offline storage scenario they need to be stored in a separate cache. The way that you do this is by adding a manifest file to the page, this is done by adding a manifest attribute to the html tag.as follows:

<html manifest="/manifest.mf">


I choose to use an ashx (or web handler) to provide the manifest file so my code actually looks like the following:

<html manifest="/manifest.ashx"> 
 

  
The reason that I use a web handler is that you don't you need to make configuration changes to IIS in order to allow the manifest file extension to be associated with the correct content type. I like to keep IIS customisation to an absolute mimimum as it's just one more thing that can go wrong when deploying an app. The code for the web handler looks as follows:

using System;
using System.Web;
 
namespace Prospero
{
    public class Manifest : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/cache-manifest";
            context.Response.WriteFile(context.Server.MapPath("~/content/survey.mf"));
        }
 
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}
 
 

In this example I have a manifest file survey,mdf in the content directory of my application.

The next rather daunting task is to work out what exactly needs to be written in the out in the manifest file. I realised that this should be pretty easy to work out by opening the web page and checking what resources had been downloaded using Firebug . I then wondered if someone has written a tool to automate this process and a quick Google turned up Manifested  . This awesome little tool will analyse your web page and tell you exactly what should be in your manifest file - just cut and paste the results into your .mf file!

Now you're all set to go - all you need to do is browse to your web page and it will be cached locally. If you  use Firefox to develop in you will get a warning bar at the top of the page asking you for permission to cache data locally - say yes and you're done. Now if you re-visit the page you will not be making any internet call except a call to retrieve the manifest file (if you are still online), this is done to check if there is a newer version on the server.  The way the browser determins if the file is newer is by checking the revision number in the file - you can force the browser to download all newer versions of your cached files by incrementing the revision number.


If you would like to double check what Firefox has cached you can do so by typing about:cache in the browser URL bar, the Offline Cache Device section show what is stored.

Tuesday, September 27, 2011

How to format code in your blog - the easy way

I've spend numerous hours trawling the internet looking for ways to make the code that I use in my blog easy to read and nicely formatted. Unfortunately I've never managed to find anything that cuts the mustard and I had resigned myself to having to use numerous hacks. That is until I saw a colleague cut and paste some code that he was working on into a Wiki and it came out perfectly formatted straight from Visual Studio!

"How the %$#@ did you do that?" I shouted
"Don't know - I just cut and pasted" was the reply
"Can't be. Visual Studio doesn't use HTML for it's code editor"

Sure enough when we cut and pasted the code into a text editor you could see that it was perfectly styled using CSS. Afer a bit of digging we discovered that he had Power Productivity Tools installed which has the capacity to enable HTML cut and paste - Eureka!


You can get this add on using NuGet (Tools -> Extension Manager -> Online Gallery and then search for Power Productivity Tools).

Now I can cust and paste code like this straight from Visual Studio:
<h2>Log On</h2>
<p>
    Please enter your pin and password. 
</p>
 
@Html.ValidationSummary(true"Login was unsuccessful. Please correct the errors 
and try again.")
 
@using (Html.BeginForm()) {
    <div>
        <fieldset>
            <legend>Account Information</legend>
.....
 
 


Enjoy!

Sunday, August 21, 2011

ASP.Net MVC - validating if an email address is already in use

Problem

The need to check if an email is already registered by a signed up user is a very common scenario that any application using Forms Authentication need to cater for. Ideally you want to make use of Ajax so that the user can get instant feedback and it should fit into your current client side validation framework. At CBSL we use the JQuery Validation plugin to achieve this, it is very well featured and infintely customisable and makes it easy to cater for this scenario.

Solution
The code in the .cshtml view file looks as follows (please note that I have removed the master page to make the code simpler to replicate):
<html>
<head>
    <title>@ViewBag.Title</title>
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script type="text/javascript">

        $(document).ready(function () {

            $("#testForm").validate({
                rules: {
                    "emailAddress": {
                        required: true,
                        email: true,
                        remote: {
                            url: "EmailValidation/checkEmail",
                            type: "post"
                        }
                    }
                },
                messages: {
                    "emailAddress": { remote: "This email address is already in use." }
                }
            });

        });

    </script>
</head>
<body>
    <form action='/EmailValidation' id='testForm'>
        <h1>
            Email Validation</h1>
        <span>Email address</span>
        @Html.TextBox("emailAddress")
        <br />
        <button type="submit">Save</button>        
    </form>
</body>
</html>

Of  special interest in this code is the JQuery "validate" method that takes in a rules object where we can define what the validation rules for a field should be and what messages should be displayed if validation should fail. In particular we can specify that the field should be validated using the "email" rule, which means it will be checked for the correct formatting and we can specify the use of the "remote" rule which means there will be a callback to an action on a controller when performing validation.

The data that jQuery posts back to the controller will be the value of the field that is being validated, in return it will expect a JsonResult with the result being true if it is the validation passes or false if not.  The content of the controller file looks as follows:

using System;
using System.Web.Mvc;
using System.Web.Security;

namespace Blog.Controllers
{
    public class EmailValidationController : Controller
    {

        public ActionResult Index()
        {
            return View();
        }

        public virtual JsonResult CheckEmail(string emailAddress)
        {
            JsonResult result = new JsonResult();

            result.Data = Membership.FindUsersByEmail(emailAddress).Count == 0;

            return result;
        }

    }
}

In the example above I've used the  ASP.Net Membership service to test if there is a user with that email already in the system, easy!

For more information on the JQuery Validation plugin check out the documentation.