Archive for 2010 / March

:   :   :  

Client-Side Validation Using xVal and ASP.NET MVC 2

Posted on 31 March 2010 and tagged with , 3 comments

Validating input on the server-side in ASP.NET MVC 2 is quite easy when using the new Data Annotations on our Model classes. It means that we have automatic validation every time someone submits data to our Controller, the model binder of ASP.NET MVC will take care of running the validation rules we set up in the model.

However the problem arises when we want client side validation on our model. We don’t want to repeat our validation rules to a client side library as that will be a pain in the ass to maintain later, when the model changes. What we do want is something that is using our preexisting rules in a way that the client side library understands.

This is where xVal enters the game. It does exactly what I just described, which is converting our Data Annotation attribute-rules to rules which the excellent jQuery Validation plugin can understand. To give an example of how you can implement xVal with ASP.NET MVC, I will create a user registration form which will feature a few standard validation rules.

Validating a user registration form

Begin with downloading xVal library from CodePlex and reference the file from our new and empty ASP.NET MVC 2 project in Visual Studio. Also add the xVal.jquery.validate.js file to our scripts folder. We need a user class to play with. Add a class named User in the Models folder and add the following code.

[MetadataType(typeof(UserMetadata))]
public class User {
    public string Username { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public string Name { get; set; }

    private class UserMetadata {
        [Required, StringLength(30)]            
        public object Username { get; set; }

        [Required, StringLength(30)]
        public string Password { get; set; }

        [Required, DataType(DataType.EmailAddress)]
        public object Email { get; set; }
    }
}

This will require a user to enter a username, password and email address. Username and password will require a maximum of 30 characters long and the name field will be optional.

We got the model, but we need somewhere to store them. For this simple demo I will be creating a dummy repository class which saves the user objects in memory, like the following snippet.

public class UserRepository {
    readonly List<User> _users = new List<User>();

    public void Create(User user) {
        // Save to database
        _users.Add(user);
    }
}

Now we need a controller and actions for our registration form. Two Register actions will be created – one for the GET and one for the POST. The GET will simply return a View and display a registration form, with the fields of our model. When submitting the form we will get to our POST action method which will check the ModelState.IsValid property if the input data is valid, if not the method will return the View, with supplied data. Otherwise the user object is saved to our dummy database and the user is redirected to the success page.

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

[HttpPost]
public ActionResult Register(User user) {
    if (!ModelState.IsValid)
        return View(user);

    _userRepository.Create(user);

    return RedirectToAction("Registered");
}

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

If you have created the View files for these actions you should be having a fully functional registration form, with server-side validation.

Magically turn on client-side validation

The server-side validation is working, and all we ever want now is client-side validation! The steps to make that work is so easy it is laughable. We only need to include these script files in the head section.

<script src="/scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="/scripts/jquery.validate.js" type="text/javascript"></script>
<script src="/scripts/xval.jquery.validate.js" type="text/javascript"></script>

Client Side Validation with xValLastly we need to tell xVal to output the Data Annotation rules to our page, so that it can be read by JavaScript. This is very easily done with the following HtmlHelper method, at the bottom of our View page:

<%= Html.ClientSideValidation<User>() %>

That’s all!? Yes, in fact that is all we have to do, to get client-side validation in ASP.NET MVC 2. Try it out, and then get back here to see what more ways you can customize xVal.

Remote validation

Sometimes only client-side validation is not enough to validate certain properties of a model. We need to validate business rules which uses a database to validate. In these cases it can be really useful to move the validation back to the server, but still keeping the snappy, instant validation that client-side validation gives us.

In xVal this is possible through something that is called RemoteRule. To create a Remote Rule you only need to create a new Action method in your Controller, which receives the model, validates it, and finally returns a true/false result. In our project we will check if a username is already taken, so that two users can’t have the same username. We will start with the following Action method:

public RemoteValidationResult UsernameIsTaken(User user) {
    var exists = _userRepository.ExistsUsername(user.Username);
    return exists
        ? RemoteValidationResult.Failure("Username is already taken.")
        : RemoteValidationResult.Success;
}

I also updated the UserRepository class to include an ExistsUsername method which returns true if the username starts with “yadda”.

To register the Remote Rule with xVal we need to open the “Register” view and find the ClientSideValidation method we used earlier, and run a method on the returned object.

<%= Html.ClientSideValidation<User>()
    .AddRule("Username", new RemoteRule(Url.Action("UsernameIsTaken"))) %>

Remote Validation is now hooked up and you can try it out by typing “yadda” in the username field. It should then say the username is taken when you tab out of the field. Awesomely easy!

Custom attributes with client-side validation

In those cases where you do not need remote validation but only classic JavaScript validation will do just fine, then creating a new Data Annotation attribute is a good idea. We will use this technique when validating if a password is good-enough for us.

We will start with a new class, that inherit from ValidationAttribute (from Data Annotation) and implements the ICustomRule interface (from xVal). From the inherited class you will override the IsValid method which does the actual validation. In this case we will use Regular Expressions to determine if the password is decent. The other method, which we got from the ICustomRule interface will tell xVal which JavaScript function to run when doing the client-side validation. I have named it “GoodPassword”, and it won’t receive any parameters (null). If the validation fails, it will use the error message set in the constructor.

public class GoodPasswordAttribute : ValidationAttribute, ICustomRule {
    public GoodPasswordAttribute() {
        ErrorMessage = "Enter a better password.";
    }

    public override bool IsValid(object value) {
        if (!(value is string))
            return false;

        // Requires passwords to have atleast 5 chars and one number
        return Regex.IsMatch(value.ToString(), @"^.*(?=.{5})(?=.*\d)(?=.*\w).*$");
    }

    public CustomRule ToCustomRule() {
        // First parameter is the JavaScript function name
        return new CustomRule("GoodPassword", null, ErrorMessage);
    }
}

Finally the last thing is implementing the JavaScript function, which will use the same regex pattern as the server-side. The pattern could have been sent over to the JavaScript function through a parameter, but I wanted to keep them separate incase the JavaScript version needed modifications. Following is the last snippet showing the final JavaScript function.

function GoodPassword(value, element, params) {
    var regex = /^.*(?=.{5})(?=.*\d)(?=.*\w).*$/g;
    return (value.match(regex) != null);
}

Now try this in the form by typing passwords such as “monster2” and “foo”. We have got both client-side validation and server-side validation of our custom rule!

Summary

In this post we have covered how to implement basic client-side and server-side validation using xVal, jQuery Validation and Data Annotation in ASP.NET MVC 2. We also went further and created remote validation and custom rules for both server-side and client-side. See the demo link below for a quick look how it turned out, and download the source for a closer look.

View the demo
Download the source

Read More »

To-Do Chrome Extension Part 2 – Browser Action Popup

Posted on 25 March 2010 and tagged with 0 comments

This is part two of the series on making a to-do extension for Google Chrome.

In this post I will cover how to implement a good database layer for our extension, as well as how to use the jsTemplate library to display our data nicely. Fairly simple right? Let’s get to work.

We will begin with writing the necessary HTML markup for displaying the tasks. To make it easier to display data from JavaScript in HTML we will be using a template system called jsTemplate, created by Google. It will allow us to separate the presentation from logic, which is always a good idea.

Let’s add the jsTemplate library to our popup.html file. There are three files needed to run the library, but to save some file requests I joined them to one file. You can find this file in the ZIP-archive at the bottom of this post. Extract the file in the /js/libs/ folder and add the following line to the head section:

<script src="js/libs/jstemplate.js" type="text/javascript"></script>

We need to define the properties of a task – a task will have a descriptive title, a boolean for whether the task is completed, and lastly a date of creation. Translating this to HTML markup means we need a checkbox, text element and a remove button for each task item. The date of creation will not be displayed in my version, but it is always good idea to include it incase you need it later. The template for a task item will look like the snippet below.

<div id="results">
    <div class="item" jsselect="$this" jsvalues="id:id">
        <input type="checkbox" class="completed" checked="checked" jsvalues="checked:completed" />
        <span class="title" contenteditable="true" jscontent="title"></span>    
        <button class="remove" title="Remove Task">Remove</button>
    </div>
</div>

As you have probably already seen—there are a number of weird, non-standard attributes in the code. These are used by jsTemplate to select properties from the data we pass in. The jsselect attribute means we will iterate over the variable specified in it—in this case the $this variable. The jsvalues attribute can change properties of the element, and jscontent sets the text of the element. Now there is one more attribute that is not very commonly used in HTML, which is the contenteditable attribute. It makes it possible to edit the content even though it is not an input or textarea element, which is perfect for this specific use-case (we can style it just like we want to).

We will also need a text box for entering a new task, which will look like this:

<input type="text" id="add" placeholder="Write task and press enter..." />

Just a normal input element, but with the new HTML 5 attribute called placeholder. It shows the text in gray and when clicking the text box it disappears. Very cool feature, that previously required lots of scripts and styling.

Data storage in extensions

If you load the extension in Chrome it won’t really do much at all – even though we have made a template and included the necessary scripts. What we need to do is bind the data storage to the template system so that it has some data to play with. To store data in Chrome we can use two different systems, Local Storage or Web Database. The most common and easiest one is Local Storage and is also the one we will use here. It is simply an object that we can set properties on and they are automatically saved for us, even after browser restarts.

Remember that localStorage can only store strings, which means you have to store your objects in a JSON-string with JSON.stringify(object)

Before we get ahead of ourselves and hook up the template system (fun!), we will create a class for handling data storage. This will make it a lot easier to get, add and remove tasks from the storage.

TaskRepository = function() {
    this.init();
    return this;
};

TaskRepository.prototype = {
    tasks: [],
    index: 0,

    init: function() {
        this.load();
    },

    create: function(task) {
        if (task == null) throw new TypeError('Missing task parameter');

        task.id = this.index++;

        this.tasks.push(task);
        this.save();
    },

    // 'get' and 'remove' functions removed for brevity,
    // see ZIP-archive for full code sample.

    load: function() {
        this.tasks = (localStorage.tasks ? JSON.parse(localStorage.tasks) : []);
        this.index = localStorage.index ? localStorage.index : 0;
    },

    save: function() {
        localStorage.tasks = this.tasks ? JSON.stringify(this.tasks) : null;
        localStorage.index = this.index;
    }
};

That is quite a bit of code but quite simple at a closer look. Basically what it does is load data from localStorage in init() and puts it in a local variable, tasks, and each method uses that variable to query data. After editing data you will have to save the data back to localStorage with the save method. An index number variable is also increased every time you create a task – it is used as ID which makes it easier to get and remove a specific task.

Hook up the template system and display some data

We are now ready to display some data in our browser action popup. To do that we create a View class which will include all presentation logics like load, edit and remove. We initialize this class in the onload event (and of course, in the popup.html file).

View = function() { return this; }
View.prototype = {
    init: function() {
        // Manually create a task
        db.create({
            title: 'My first task is to make a task',
            completed: false,
            created: new Date()
        });
        
        this.renderView();
    },

    renderView: function() {
        // Tells jsTemplate to load our tasks and display them with our template
        jstProcess(new JsEvalContext(db.tasks), document.getElementById('results'));
    }
};

var db = new TaskRepository();
var view = new View();

window.onload = function() { view.init(); };

Round up

task If you reload the extension in Chrome you should see one task appearing in the list, and you should also notice that the layout is worse than the web was ‘99 (see image). There is no way to add a task either, nor remove or edit yet. In the next post we will fix all these points.

Download the Source

Download To-Do Extension Source (Part 2)

Read More »

Experimental APIs in Chrome Extensions - #1

Posted on 20 March 2010 and tagged with 0 comments

This post covers the new Chrome Extension API methods which are in development. Some of which are already in the dev release of Google Chrome (5.0.356.2). Most of these methods will most likely change before they are released in the stable channel, but it will give you an idea of what you can expect from the extension API in the future.

Enabling experimental APIs

To use the experimental methods you need to first turn them on in both Chrome and on per extension basis. Begin with adding --enable-experimental-extension-apis to the command arguments of Chrome. Next find the extension you want to try the experimental APIs on and add experimental to the permission section of the manifest file.

Clipboard (chrome.experimental.clipboard)

Copying text is already possible in Chrome by selecting text in a textarea and executing the execCommand("Copy") method. Though, this is quite a hacky way so it is great to know that this will now be offered through an API method. Methods for cutting and pasting data is also available.

Following is an example of usage:

// Select
document.getElementById('textarea1').select();

// Copy/Cut [executeCopy(tabid, callback)]
chrome.experimental.clipboard.executeCopy(1, function() {
    console.log('copied!');

    // Focus an element
    document.getElementById('textarea2').focus();

    // Paste [executePaste(tabid, callback)]
    chrome.experimental.clipboard.executePaste(1, function() {
        console.log('pasted!');
    });
});

What I am missing is a method where I can pass a string as an argument, which will be copied directly, without needing to select the text beforehand.

Infobar (chrome.experimental.infobars)

chrome-experimental-infobar2You are most likely familiar with infobars from when you login to a web page and Chrome asks if it should remember your login. Infobars can be used when you want to alert users of a completed action, or when you want to give user a choice to take an action (e.g. backup the extensions data).

Following is an example usage:

// Show an infobar [show(details, callback)]
chrome.experimental.infobars.show({ path: 'infobar.html' }, function(window) {
    console.log('Infobar showed, in window ', window);
});

It would be great if we got some default CSS styles for buttons and links for a consistent look, as currently we have to style them ourselves. I am pretty sure this is in the pipeline, though.

Idle (chrome.experimental.idle)

This API is quite interesting. It allows us to query which state (idle, active) Chrome currently is in. This can be useful when you want to run a certain process when Chrome gets in idle state, e.g. pause the music of a music player after being idle for 30 minutes.

Following is an example usage:

// Find out which state Chrome is in. [queryState(threshold, callback)]
chrome.experimental.idle.queryState(15, function(state) {
    console.log('Chrome is in ', state, ' state.');
});

// Event which fires when state changes
chrome.experimental.idle.onStateChanged.addListener(function(state) {
    console.log('Changed to ', state, ' state.');
});

Currently the documentation for this API is not ready (or the API itself for that matter) which means I don’t know which unit the threshold is in, but we can assume it is in seconds.

Stay up to date

As these experimental APIs changes a lot before they are released it is a good idea to check back at the documentation at Google Code regularly. You can also have a look at the latest trunk, more specifically the extension_api.json file, for the absolute latest APIs.

These were only some of the experimental APIs the extension API offers, for more a full documentation see the links above. I will also continue writing these type of posts for the experimental APIs in Chrome.

Read More »

To-Do Chrome Extension Part 1 – Project Setup

Posted on 7 March 2010 and tagged with 0 comments

This is part one of the series on making a to-do extension for Google Chrome.

In this series we will create a simple to-do extension where you can add tasks through a browser action popup. When you have completed a task, you should be able to remove it from the list. The browser action icon should display how many tasks you have left to complete. It will also feature a basic theme picker in the options page.

This series on Chrome Extensions is aimed towards beginners in extension developing but with basic experience in JavaScript and HTML.

Let’s start with creating a good folder structure for our extension. We know we will store images, HTML, CSS and JavaScript files. We might even use external JavaScript libraries like jQuery. Images, CSS and JavaScript files will go into their own separate folders. Our HTML files will stay in the root folder. This makes the following folder structure:

  • CSS
  • Images
  • JS 
    • Libs

Manifest File

After we have created these folders we will create a manifest.json file that holds metadata about our extension in JSON format. There are two required properties that you need to specify in the manifest file—name and version—but we will go ahead and add a few more that we need for our to-do extension.

Create a manifest.json file and fill in the following information.

{
	"name": "To Do",  
	"description": "A simple To Do extension.",
	"version": "1.0.0",
	"icons": { 
		"32": "images/icon32.png",
		"48": "images/icon48.png",
		"128": "images/icon128.png" 
	},
	"browser_action": {
		"default_icon": "images/icon19.png",
		"popup": "popup.html"
	},
	"options_page": "options.html"
}

That is quite a mouthful, but I will break it down row by row. The first three properties are quite self-explanatory so I will go directly to icons section. There are two required icon sizes that you should ship with your extension; these are 48x48 and 128x128 pixels. The 128 pixel icon will be displayed in the install dialog and the 48 pixel icon shows up on the extensions page. I also added a reference to a 32 pixel icon as that is the size the extensions gallery is using.

Next property is browser_action which defines the clickable icon next to the Omnibar in Google Chrome. It needs a default icon with size of 19 pixels. If you link to an image larger than 19 pixels it will be resized to fit. Popup property is the HTML file that will be shown when you click the browser action icon. We will simply call this file popup.html.

Lastly we define a page that will act as a options page, named options.html. Users will be able to access it from the options button at the extensions page.

The manifest file is finished for now, but we need to create a few files that we have referenced in the file.

Creating Necessary Files

Creating a clear and good looking icon is quite challenging so we can use one of the icon-search services available on the web. I’m usually using one called Iconfinder.net which feature a large library of icons and ability to filter on name and size. For our simple extension I found a good icon of which I then created four different sizes (19x19, 32x32, 48x48 and 128x128) and saved them in the images folder.

Now we need a couple of HTML files, namely popup.html and options.html, and their respective JavaScript and CSS files (with the same name). The HTML files should be saved in the root next to manifest.json, JavaScript files in the js folder, and CSS files in the css folder.

We will add some basic HTML 5 markup to the HTML files. Open both popup.html and options.html and paste the following code snippet in each file. Also change {name} to the filename in each file (e.g. “Popup” in popup.html).

<!DOCTYPE html>
<html>
<head>
    <title>{name} - To-Do</title>
    <link rel="stylesheet" href="css/{name}.css" type="text/css" />
    <script src="js/{name}.js" type="text/javascript"></script>
</head>
<body>
    <h1>{name}</h1>
</body>
</html>

Creating a file to keep up with version changes in your extension is good practice. I usually create a very basic JSON file called release-notes.json, where I store changes in the following format:

{
    "version": "1.0.0",
    "log":[
        "Initial release."
    ]
}

Copy the JSON data and paste it in a file called release-notes.json in the root folder. I will later in this series describe how you can display it in your extension’s options page.

Running the Extension

extension-loaded Finally we are ready to load the extension into Google Chrome to see if it works. You do this by navigating to chrome://extensions/. Turn developer mode on if it is off. Next click the Load unpacked extension… button. You will be presented with a folder browser. Find the folder you created for the extension, and press OK. The extension should now load and display in the list. A browser action icon should also be visible in the toolbar.

Of course there is no functionality at all in this version of the extension. We will work on that in the next part of this series.

Download the Source

Download To-Do Extension Source (Part 1)

Read More »

Loading Posts...