Link here

Link here

xVal v1.0 Now Available

ASP.NET, MVC, xVal 30 Comments »

image xVal version 1.0 is released at last! In case you’re not aware, xVal is a validation helper for ASP.NET MVC that lets you use your own choice of server-side validation framework (e.g., Microsoft’s DataAnnotations attributes, or Castle Validator, or NHibernate Validaion) and dynamically generates client-side validation code from your rules.

You can download the library from http://xval.codeplex.com/. If you want a working example of xVal in action, download the demo project or read the rest of this blog post.

So, what’s new in version 1.0?

  • Support for dynamic client-side validation summaries
  • Remote validation (i.e., evaluating rules via Ajax)
  • Additional language files for localised default validation messages: Danish, French, Dutch, Polish, Swedish, and Italian
  • Upgraded to work with jQuery 1.3.2 and jQuery.Validation 1.5.5
  • Fixes for some bugs and issues in version 0.8.

If you’d like to learn more about the basics of getting started with xVal, setting up rules, etc., check out my previous posts on the subject. In this post, I’ll describe only the new features and will assume you already know how to get started with xVal.

Client-side Validation Summaries

It’s the most commonly-requested feature, and it’s now here: you can display client-side validation messages in a “summary” format, just like ASP.NET MVC’s Html.ValidationSummary() helper does.

To do this, first make sure you’re rendering any server-generated validation messages into a standard ASP.NET MVC validation summary, and wrap that inside some element such as a DIV with some ID:

<div id="validationSummary">
    <%= Html.ValidationSummary("Please fix the following problems:") %>
</div>

Next, tell xVal that you want it to merge your client-generated messages into this summary by appending “.UseValidationSummary()” onto your existing call to Html.ClientSideValidation():

<%= Html.ClientSideValidation("booking", typeof(Booking))
        .UseValidationSummary("validationSummary") %>

That’s it! Just make sure that, when you call UseValidationSummary(), you pass the ID of the element containing your server-generated validation summary.

Note: This feature requires you to be using xVal with jQuery Validation (not ASP.NET Native validation) because internally, it’s built on a jQuery Validation feature. xVal makes your client-generated messages and your server-generated messages seamlessly fit together in a single summary list.

Remote (Ajax) Validation

xVal already supported standard client-side rules, custom client-side rules, server-side rules, and rules defined as combinations of these. But what if you want a rule that behaves like a client-side rule (so it’s evaluated dynamically before the user submits the form) but its logic actually has to run on the server? For example, if you want a “username must be unique” rule, you can’t do that with pure JavaScript because it requires a database lookup to evaluate.

Not surprisingly, “remote” rules fill this gap. All you have to do is say that a certain field is subject to remote validation, and provide an action method that can be called to validate any given input. It’s usually best to add a RemoteRule to an existing collection of rules directly in your view:

<%= Html.ClientSideValidation("booking", typeof(Booking))
        .AddRule("BookingDate", new RemoteRule(Url.Action("ValidateBookingDate"))) %>

Then, implement an action method that can validate some input. The action method will receive the complete contents of the form at the moment when validation is triggered, and can return its verdict in the form of a RemoteValidationResult, e.g.:

public RemoteValidationResult ValidateBookingDate(Booking booking)
{
    var error = Booking.ValidateBookingDate(booking);
    return error == null ? RemoteValidationResult.Success 
                         : RemoteValidationResult.Failure(error.ErrorMessage);
}

That does the job. For an example of this in action, download the v1.0 demo project.

image

Note: I suggest adding RemoteRules as ad-hoc rules in your views (using .AddRule() as shown above) rather than embedding them directly in your domain model like most other rules, because they need to know the URL of the action method that evaluates them, and that information doesn’t really belong in a good technology-agnostic domain model.

Note: This feature also requires you to be using xVal with jQuery Validation (not ASP.NET Native validation) because internally, it’s built on a jQuery Validation feature. If there’s strong demand for supporting remote validation with ASP.NET Native validation, it will be done for a future release.

How to upgrade

If you’re already using an earlier version of xVal, upgrading should only take a minute:

  1. Download the 1.0 release package from Codeplex and unzip it
  2. In your project, replace xVal.dll and xVal.jquery.validate.js and/or xVal.AspNetNative.js with the latest versions you just downloaded

What about ASP.NET MVC v2?

The good folks at Microsoft have already said that ASP.NET MVC v2 will come with built-in support for generating client-side validation code from rules in an arbitrary server-side validation framework. That’s a familiar idea… :)

So should you use that instead of xVal? If it turns out to meet your needs better then yes, of course, and if it doesn’t, then no. Use whatever suits you best!

However it will be quite a while before MVC v2 is released – currently it’s still on CTP 1 - so one option is to use xVal now and consider migrating at the same time that you upgrade your entire project to MVC v2 if indeed you choose to do that. The migration path from xVal to MVC v2’s built-in validation should be reasonably straightforward, since the two approaches appear to be rather similar, and you can always retain the option of sticking with xVal if it suits you better.

Mentions

Thanks to the following people who directly contributed to this release: House Air, Rodbv, Maarten Balliauw, Dariusz Tarczynski, Yoan80, Emmanuele, Eudega, and Howard van Rooijen.

kick it on DotNetKicks.com

xVal 0.8 (Beta) Now Released

MVC, Validation, xVal 44 Comments »

This morning I’ve released xVal 0.8 (Beta). It’s a fairly substantial update - it adds the following features:

  • Support for NHibernate.Validator (in addition to the existing support for System.ComponentModel.DataAnnotations and Castle Validator)
  • Internationalization of default client-side messages
  • Much easier to implement custom validation logic (server-side and client-side)
  • Fluent syntax for defining ad-hoc validation rules directly in a view
  • Support for comparison validators (e.g., “PasswordConfirm” must equal “Password”)
  • Works with ASP.NET MVC Release Candidate
  • Better performance (rules are now cached per model type)
  • A few bugfixes

To recap, xVal is a validation framework bridge for ASP.NET MVC. It lets you use whatever server-side validation technology you prefer (and there are plenty that work well with ASP.NET MVC), and then xVal makes client-side validation happen automatically. On the client, you can enable either jQuery.Validation or ASP.NET (WebForms-style) native validation, or you can write your own plugin.

image

This is a “beta” quality release, in that the feature set is more or less right for 1.0. The short term goal now is not to add any more major features, but instead to focus on providing proper documentation (instead of just blog posts) and make sure it works robustly in all circumstances.

Now I’ll quickly explain the new features in 0.8.

Support for NHibernate.Validator

If you’re using NHibernate, you might also be using NHibernate.Validator. It’s a server-side validation framework that plugs directly into NHibernate’s pipeline, so you can be sure objects never reach the database unless they satisfy your rules.

xVal can now detect NHibernate.Validator rules and translate many of them into client-side rules. To make this work, assuming you already have an application that uses NHibernate.Validator, add a reference to xVal.dll and  xVal.RulesProviders.NHibernateValidator.dll and then enable it in your Global.asax.cs file:

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
    xVal.ActiveRuleProviders.Providers.Add(new NHibernateValidatorRulesProvider(ValidatorMode.OverrideXmlWithAttribute));
}

If you want to use jQuery.Validator on the client, then add the following references to your master page:

<head runat="server">
    <asp:PlaceHolder runat="server">
        <script type="text/javascript" src="<%= Url.Content("~/Scripts/jquery-1.3.2.min.js") %>"></script>
        <script type="text/javascript" src="<%= Url.Content("~/Scripts/jquery.validate.js") %>"></script>
        <script type="text/javascript" src="<%= Url.Content("~/Scripts/xVal.jquery.validate.js") %>"></script>
    </asp:PlaceHolder>
</head>

Or, if you want to use ASP.NET Native validation on the client, then add the following references to your master page instead:

<head runat="server">
    <asp:PlaceHolder runat="server">
        <script type="text/javascript" src="<%= Page.ClientScript.GetWebResourceUrl(typeof(System.Web.UI.Page), "WebForms.js") %>"></script>
        <script type="text/javascript" src="<%= Page.ClientScript.GetWebResourceUrl(typeof(System.Web.UI.Page), "WebUIValidation.js") %>"></script>    
        <script type="text/javascript" src="<%= ResolveUrl("~/Scripts/xVal.AspNetNative.js")%>"></script>
    </asp:PlaceHolder>
</head>

Finally, apply client-side validation in any view by using Html.ClientSideValidation():

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

Note that before Visual Studio will recognize Html.ClientSideValidation(), you must either add <%@ Import Namespace="xVal.Html" %> to the top of your view, or reference the namespace globally in your web.config file:

<system.web>
  <pages>
     <namespaces>
        <!-- leave rest as-is -->
        <add namespace="xVal.Html"/>
    </namespaces>
  </pages>
</system.web>

So now, if your model classes define NHibernate.Validator rules, such as:

public class Member
{
    public virtual int MemberID { get; internal set; }
 
    [NotNullNotEmpty] [Length(3, 50)]
    public virtual string Name { get; set; }
 
    [NotNullNotEmpty] [Email] [Length(200)]
    public virtual string EmailAddress { get; set; }        
}

… then those rules will be applied on the client:

image

Note that NHibernate.Validator support is pretty early at the moment. I’m interested to get any feedback about how the client-side interpretation of the rules could be improved (for example, should Date properties automatically be required?).

Internationalization of default client-side messages

It’s always been possible to internationalize the server-generated validation messages – just nominate the resource type and resource string name when defining a rule:

[Required(ErrorMessageResourceType = typeof(MyResourceType), ErrorMessageResourceName = "ValueRequired")]

But it’s inconvenient to have to type that out every time. Wouldn’t it be better if you could also internationalize the default client-generated messages too? Now you can.

To try this out, download the demo project and also the latest xVal release. Copy xVal.Messages.en-US.js from the xVal release into the demo project’s ~/Scripts/ folder, and then reference it from the master page:

<head runat="server">
    <asp:PlaceHolder runat="server">
        <!-- Leave the other references as they are -->
        <script type="text/javascript" src="<%= Url.Content("~/Scripts/xVal.Messages.en-US.js") %>"></script>
    </asp:PlaceHolder>
</head>

If you run the project now, it will appear that nothing’s changed. However, simply by referencing xVal.Messages.en-US.js, you’ve told xVal to use messages defined in that file instead of using its built-in defaults. If you want to change the English messages, just edit xVal.Messages.en-US.js.

To support another language, make a copy of xVal.Messages.en-US.js, rename it to refer to the other language (e.g.,  xVal.Messages.es-ES.js), put that copy in your ~/Scripts/ folder, and then edit the messages so they’re in the other language.

image

Now, change the reference in your master page:

<script type="text/javascript" src="<%= Url.Content("~/Scripts/xVal.Messages.es-ES.js") %>"></script>

And that’s it! You’ve now got Spanish messages:

image

If you want to change the language dynamically at runtime, you should add some code that varies which xVal.Messages.*.js file gets referenced, perhaps according to the current thread culture.

Update: Thanks to the community for contributing a comprehensive set of default translations. Language files for Brazilian Portuguese, Danish, Spanish, Dutch, Polish, French, German, and Swedish will be included in the next release.

Implementing Custom Validation Logic

You could previously create custom server-side validation logic by subclassing whatever base class your server-side validation framework uses for validation rules. For System.ComponentModel.DataAnnotations, that means subclassing ValidationAttribute. For Castle Validator, it means making an attribute that implements IValidator.

Now, whatever server-side validation framework you use, you can also make custom rules run custom client-side logic by implementing xVal’s ICustomRule interface.

To try this out, download the demo project and add a new class to the DomainModel project called DivisibleByAttribute:

public class DivisibleByAttribute : ValidationAttribute, ICustomRule
{
    private int Divisor { get; set; }
    public DivisibleByAttribute(int divisor)
    {
        Divisor = divisor;
        ErrorMessage = string.Format("Must be a multiple of {0}.", divisor);
    }
 
    public override bool IsValid(object value)
    {
        if(!(value is int))
            return false;
        return ((int)value) % Divisor == 0;
    }
 
    public CustomRule ToCustomRule()
    {
        return new CustomRule(
            "DivisibleByN",            // JavaScript function name
            new { divisor = Divisor }, // Params for JavaScript function
            ErrorMessage               // Message if invalid
        );
    }
}

Since this derives from ValidationAttribute, your DataAnnotations runner will enforce it on the server when you attach it to some model property:

[Required] [Range(1, 20)] [DivisibleBy(4)] public int NumGuests { get; set; }

To run similar logic on the client, implement a JavaScript function called DivisibleByN:

<script type="text/javascript">
    function DivisibleByN(value, element, params) {
        return value % params.divisor == 0;
    }
</script>

Note that you should put this before any call to Html.ClientSideValidation(). Now, you’ll get client-side and server-side validation of your custom rule:

image

If you want to internationalize your custom rule’s message, then alter DivisibleByAttribute’s ToCustomRule() function so that it uses the CustomRule constructor that lets you specify a resource type and a resource string.

Defining Ad-Hoc Validation Rules in a View

xVal focuses on model based validation. That means you normally define rules in your model layer. However, sometimes it’s useful to throw in a few extra rules that apply only to a specific MVC view. There’s now a quick and easy way of doing this.

To try it out, download the demo project, go to the PlaceBooking.aspx view, and then edit the Html.ClientSideValidation() call to the following:

<%= Html.ClientSideValidation<Booking>("booking")
    .AddRule("Name", new RegularExpressionRule("^[a-z]{3}\\d{3}$", RegexOptions.IgnoreCase) {
                        ErrorMessage = "Must be three letters followed by three numbers."
                     })
    .AddRule("BookingDate", new RangeRule(DateTime.Now, null) {
                                ErrorMessage = "Must be in the future."
                            })
%>

(Note: you’ll also need to add a <%@ Import Namespace="xVal.Rules"%> directive to the top of the view.)

Now, your view’s ad-hoc rules will be combined with the model rules:

image

If you’re the sort of person who doesn’t like model based validation at all, you could use this feature to build your complete rules configuration inline in a view. Just start with a RuleSet.Empty and add ad-hoc rules to it:

<%= Html.ClientSideValidation("booking", RuleSet.Empty) 
     .AddRule("Name", new RequiredRule())
     .AddRule("BookingDate", new RequiredRule())
     .AddRule("BookingDate", new DataTypeRule(DataTypeRule.DataType.Date))
     /* Etc */
%>

The advantages of model-based validation are clear (DRY), but this gives you extra flexibility that might come in handy.

What next?

The next step is to let people start using this and ask for feedback about how it could be improved. I’ll shy away from adding major new features right now because I don’t personally have time to manage an enormous project. I’m more interested in any bugs you might find or ways in which the current feature set could be applied better. There are already a few issues registered on Codeplex that I’ll be attending to, or better still, you could submit a patch!

Just a reminder: if you’re able to provide translations of the language file into any other major language, and if you’re happy for me to include your translation in the next release, please send it to me.Update: Thanks to everyone for all the translations. We’ve now covered all the main ones, so no more are needed.

With thanks to MarkJPerry, DavidHayden, sjmueller, trevor, goneale, imm102, lobex, DerekMcDermott, richardu, Peter Mounce, Billy McCafferty, Mike Saunders, Andrew Scott, Vadim, and various others who have provided useful feedback on the previous release.

kick it on DotNetKicks.com

Site Meter