Initial commit — 16 posts converted from dasBlog XML, media assets
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: "jQuery Validate and Jeditable, Part 1"
|
||||
date: 2009-12-31T21:32:00-06:00
|
||||
slug: jquery-validate-and-jeditable-part-1
|
||||
published: true
|
||||
---
|
||||
|
||||
I was recently tasked to add server-and-client-side form validation for an ASP.NET MVC site - which already uses in-place editing courtesy [Jeditable](http://www.appelsiini.net/projects/jeditable). I really like the field editing experience that Jeditable provides – it makes form entry in the browser interactive, is fairly straightforward to integrate, and it’s adaptable to many scenarios. It does not, however, have any validation mechanism built in.
|
||||
|
||||
Our project already used [jQuery Validate](http://bassistance.de/jquery-plugins/jquery-plugin-validation/) for a few forms by using the HTML class definitions – like adding class=”required phone” to an INPUT element. This works great, but doesn’t provide any server-side validation tie-in.
|
||||
|
||||
Earlier this year, I remembered having seen a [presentation](http://speakerrate.com/talks/1218-useful-jquery-tips-tricks-and-plugins-with-asp-net-mvc) by [Elijah Manor](http://elijahmanor.com/) who mentioned using [xVal](http://xval.codeplex.com/) for robust server and client side validation. And with the news that [MVC 2 will have a built in validation technique similar to xVal](http://haacked.com/archive/2009/10/01/asp.net-mvc-preview-2-released.aspx), it was an easy decision to start investigating this library.
|
||||
|
||||
[xVal](http://xval.codeplex.com/) is a pretty easy to get integrated. The first step is to decorate the model with validation rules – I’ve decided to use .NET framework’s [DataAnnotations](http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx), which ends up looking like:public class ValidateViewModel
|
||||
{
|
||||
[Required(ErrorMessage = "This string is required")]
|
||||
public string StringRequired { get; set; }
|
||||
|
||||
[Range(13, 100, ErrorMessage = "Must be between 13 and 100")]
|
||||
public double DoubleRange13_100 { get; set; }
|
||||
}public class ValidatedController
|
||||
{
|
||||
public ViewResult Index()
|
||||
{
|
||||
return View(new ValidateViewModel());
|
||||
}
|
||||
}<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<ValidateViewModel>" %>
|
||||
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
|
||||
<% using(Html.BeginForm()) {%>
|
||||
<%= Html.ValidationSummary() %>
|
||||
<label for="StringRequired">String Required:</label>
|
||||
<%= Html.TextBoxFor(m => m.StringRequired) %>
|
||||
<%= Html.ValidationMessageFor(m => m.StringRequired)%>
|
||||
|
||||
<label for="DoubleRange13_100">Doulbe between 13 and 100:</label>
|
||||
<%= Html.TextBoxFor(m => m.DoubleRange13_100) %>
|
||||
<%= Html.ValidationMessageFor(m => m.DoubleRange13_100)%>
|
||||
<%} %>
|
||||
</asp:Content>
|
||||
|
||||
To validate this ViewModel server side, we use a [DataAnnotationsValidationRunner](http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/) like the one in xVal’s documentation:[AcceptVerbs(HttpVerbs.Post)]
|
||||
public ActionResult Update(ValidateViewModel model)
|
||||
{
|
||||
try {
|
||||
DataAnnotationsValidationRunner.ValidateModel(model);
|
||||
// it’s valid, do the actual update
|
||||
var domainObject = ValidateDomainModel.Find(model.id);
|
||||
Map(model, domainObject);
|
||||
domainObject.Update();
|
||||
}
|
||||
catch(RulesException ex) {
|
||||
ex.AddModelStateErrors(ModelState, null);
|
||||
}
|
||||
|
||||
return ModelState.IsValid ? RedirectToAction("Completed")
|
||||
: (ActionResult) View();
|
||||
}public static class DataAnnotationsValidationRunner
|
||||
{
|
||||
private static IEnumerable<ErrorInfo> GetErrors(object instance)
|
||||
{
|
||||
return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>()
|
||||
from attribute in prop.Attributes.OfType<ValidationAttribute>()
|
||||
where !attribute.IsValid(prop.GetValue(instance))
|
||||
select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(String.Empty), instance);
|
||||
}
|
||||
|
||||
/// <summary>Validates the given <param name="model">model</param></summary>
|
||||
/// <exception cref="RulesException">Thrown if any errors are found</exception>
|
||||
public static void ValidateModel(object model)
|
||||
{
|
||||
var errors = GetErrors(model);
|
||||
if (errors.Any())
|
||||
throw new RulesException(errors);
|
||||
}
|
||||
}
|
||||
|
||||
*Aside: the project uses the *[*Active record pattern*](http://en.wikipedia.org/wiki/Active_record_pattern)* via *[*Castle ActiveRecord*](http://www.castleproject.org/activerecord/index.html)* for data access without an intermediate business-logic layer. For this case, the rules are defined on the ViewModel and are validated in the controller. This does add some noise in the actions – I’m definitely interested in other methods for handling this. Such as - perhaps the validation could be placed inside the ViewModel?*
|
||||
|
||||
The next step is to add client-side validation. [xVal](http://xval.codeplex.com/)’s built-in [jQuery Validate](http://bassistance.de/jquery-plugins/jquery-plugin-validation/) rule generator makes this ridiculously simple – just reference jquery.validate.js and xVal.jquery.validate.js in the view, and then this single line:<%= Html.ClientSideValidation<ValidateViewModel>() %>
|
||||
|
||||
The rules defined in the ViewModel will now be validated client side and enforced for server side actions. This works great for a statically defined HTML form, but I learned that integrating with [Jeditable](http://www.appelsiini.net/projects/jeditable)’s dynamic inline forms to be not so straight forward.
|
||||
|
||||
Continued in [Part 2](/2010/01/03/jQueryValidateAndJeditablePart2.aspx)…
|
||||
Reference in New Issue
Block a user