Unobtrusive jQuery Validation Using MVC3 and Razor

Introduction to Razor

Razor continues the valuable MVC tradition of model based validation that works on both the client and the server. MVC3 adds the ability to use jQuery and unobtrusive validation to the default toolkit while still allowing you to write your own custom client side validation where necessary. Razor simplifies the syntax of generating model validated forms to speed your development time.

Rich user interface web applications must closely control the amount of JavaScript sent to the client because every line of JavaScript code has to be downloaded by the client and each individual JavaScript file is a separate web request that introduces additional latency. MVC3 allows you to use the jQuery validation library instead of the Microsoft MVC validation libraries. This is very valuable if your web application is already using jQuery as many rich UI web applications do.

Using jQuery to perform validation and using jQuery's AJAX methods to call REST MVC services allows you to completely de-reference the Microsoft MVC and ASP.NET AJAX libraries and use a pure jQuery approach to your client side. The result is your client code will all leverage the same framework and it will save your end users from downloading 3 files weighing in at a total of about 114k.

Unobtrusive validation leverages the jQuery unobtrusive validation plug-in to allow simple inline HTML element attributes to define what validation rules should be enforced. The result is very efficient validation that doesn't clutter up the HTML. Clean and neat HTML allows for the fastest page load times possible. Generated pages have sophisticated validation with the minimum page download size imaginable.

Razor improves on the ASPX syntax for building model bound forms. Razor's @ syntax for field rendering requires fewer keystrokes and the improved intellisense support for the bound model accelerates development speed.

Model Validation Attributes

The .NET framework provides a number of attributes that you can apply to your object model to validate against. These attributes are found in the System.ComponentModel.DataAnnotations namespace and are applied to the properties on your object.

If you are using the Entity framework and want to apply model validation attributes to your Entity Framework objects, you can create a partial class to add this markup.

  • Required - Indicates that this field must have a value.
  • Range - The value provided must be between two numbers.
  • StringLength - Defines the maximum length of a string.
  • RegularExpression - Specifies a regular expression for complex pattern matching validation.
  • CustomValidation - Allows you to define custom code to validate the attribute.
  • DisplayName - When the model's labels are rendered, the DisplayName attribute defines the name that will be shown to the end user.

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using System.ComponentModel.DataAnnotations;
  using System.ComponentModel;
  
  namespace UnobtrusiveMVC.Models
  {
      public class Boat
      {
          [Required]
          [StringLength(20,ErrorMessage="Avast! Yarr boat name must be less than 20 characters matey!")]
          [DisplayName("Boat Name")]
          public string BoatName { get; set; }
  
          [Required]
          [StringLength(20)]
          [RegularExpression(@"Captain.*",ErrorMessage="Your captain name must start Captain!")]
          [DisplayName("Captain's Name")]
          public string CaptainName { get; set; }
  
          [Required,Range(0,100)]
          public int CaptainSaltinessPercent { get; set; }
      }
  }

Creating the Razor Page with Validation

To enable unobtrusive validation, you can either enable it site-wide in your web.config or you can enable it on a per-page basis by using the Html.EnableUnobtrusiveJavaScript(true) function in the page header.

Consistency is the central pillar of usability and using the web.config approach will enable unobtrusive validation across your entire web site. If you need to opt out specific pages later, you can always use the Html.EnableUnobtrusiveJavaScript(false) function to disable it.

  …
  <appSettings>
  <add key="ClientValidationEnabled" value="true"/>
  <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
  </appSettings>
  …

The @Html.ValidationSummary command defines how your errors are displayed. If you want ASP.NET to automatically generate an error list as a <UL> collection, use @Html.ValidationSummary(false). If you want to specify the exact place each error message is placed for each element, use @Html.ValidationSummary(true). You can use the auto-generated summary side-by-side with custom placed error message elements.

Inline Validation

It is a web form usability best practice to include inline error messages next to the fields that have failed validation. This allows the user to see the message describing the problem right next to where they need to fix it in order to continue.

If you want to specify the exact location your error messages, will appear, you can use the @Html.ValidationMessageFor to specify the location on the page you want the validation messages for a specific element to be placed. If this function is used, all validation errors will be rendered at the specified location.

  @Html.ValidationMessageFor(model => model.BoatName)
  When it is rendered out to the user's browser, the HTML below will be written:
  <span class="field-validation-valid" data-valmsg-for=" BoatName" data-valmsg-replace="true"></span> 
  

It is worth noting that the validation message HTML is only a placeholder. The HTML tags on the field itself define the message that will be displayed.

Rendering Fields To Be Validated

To render the fields that leverage the validation, you will need to define the proper model in the header of your page and render your fields Razor's @Html helpers. Rendering the actual fields to be validated requires rendering the field to be validated and rendering a container that the error message will be displayed in.

  • @Html.TextBoxFor - Standard textbox.
  • @Html.HiddenFor - A hidden field that stores a value but renders no visible UI element to the page.
  • @Html.DropDownListFor - A drop down list that allows the user to choose one option from a list of options.
  • @Html.CheckBoxFor - A single checkbox option.
  • @Html.ListBoxFor - A multi-select listbox bound to an array of options.
  • @Html.PasswordFor - A password field.
  • @Html.RadioButtonFor - A single radio button option.
  • @Html.TextAreaFor - Multi-Line text area.
  • @Html.DisplayFor - Generic display, will follow what is set in the UI Hints.

  @model UnobtrusiveMVC.Models.Boat
  @{
      View.Title = "Index";
      Layout = "~/Views/Shared/_Layout.cshtml";
      Html.EnableUnobtrusiveJavaScript(true);
  }
  <h2>Index</h2>
  @using (Html.BeginForm()) {
      
      @Html.ValidationSummary(true)
      <fieldset>
      @Html.ValidationMessageFor(model => model.BoatName)
      @Html.ValidationMessageFor(model => model.CaptainName)
  
      <div class="editor-label">
          @Html.LabelFor(model => model.BoatName)
      </div>
      <div class="editor-field">
          @Html.TextBoxFor(model => model.BoatName)
      </div>
      <div class="editor-label">
          @Html.LabelFor(model => model.CaptainName)
      </div>
      <div class="editor-field">
          @Html.TextBoxFor(model => model.CaptainName)
      </div>
      
      <input type="submit" value="Save"></fieldset>
  }

You can also manually render the HTML for the data you wish to collect. For example, if you wanted to custom render the HTML for a text box that will make sure the fields starts with "David", you could do so by using the HTML below:

  <input data-val="true" data-val-length="Too long." data-val-regex-pattern="David.*" data-val-regex="The Manual Validated Field must start with David." data-val-length-max="10" data-val-required=" Manual Validated Field is required." id="ManualField" name="ManualField" type="text" value="" />

Conclusion

MVC3 is a dramatic step forward for the creation of web applications with sophisticated client-side validation without a lot of client side coding. The ability to define validation rules in the model and have those rules enforced on both the client and the server helps the user and makes your code more maintainable.



Related Articles

Downloads