eWorld.UI - Matt Hawley

Ramblings of Matt

MVC UI Validation Framework

April 2, 2008 16:36 by matthaw

The last few days I've been working on a MVC UI validation framework that closely follows that of ASP.NET. While my implementation is only in it's baby steps, I decided I would post it to the MVC Contrib project, and follow as much standards as what they have. Overall, the framework is very simple and straight forward in it's use.

Here were my requirements:

  1. It must closely match the ASP.NET UI validation framework.
  2. It should support all of the ASP.NET validators in their minimalistic implementation.
  3. It should require very minimal script inclusion or code to make this happen.
  4. It should only by a client side framework as you should be protecting your data on the server side through normal validations.

What I came up with, includes:

  1. It utilizes the ASP.NET UI validation framework by leveraging the WebUIValidation.js file (emitted through WebResource.axd).
  2. It supports all of the validators, with extended support for validation groups:
    1. RequiredValidator
    2. RegularExpressionValidator
    3. RangeValidator (currently does not support Date or Currency data types)
    4. CompareValidator
    5. CustomValidator
  3. It exposes 2 script inclusion calls, and 1 form validation setup call
    1. ValidatorRegistrationScripts() - Will render the WebUIValidation.js script, and scripts for form validation upon submission. This should be placed within the head tag.
    2. ValidatorInitializationScripts() - Will render all of the "expando" attributes for all validators upon the page and any initialization calls to set things up. This should be placed at the very end of your page before the closing body tag.
    3. FormValidation() - Will return an IDictionary object containing the "onsubmit" attribute. This should be called when creating your <form> tag.
  4. It is only a client-side framework leveraging ASP.NET's WebUIValidation.js

Since you now have an idea of the requirements and what was met, here's an example of it in action:

   1:  <%@ Import Namespace="MvcContrib.UI.Html" %>
   2:  <html>
   3:     <head>
   4:        <%= Html.Form().ValidatorRegistrationScripts() %>
   5:     </head>
   6:     <body>
   7:        <% using(Html.Form<MyController>(c => c.Save(), FormMethod.Post, Html.Form().FormValidation())) { %>
   8:        First Name: <%= Html.TextBox("firstName") %>
   9:        <%= Html.Form().RequiredValidator("firstNameRequired", "firstName", "First Name is Required.") %>
  10:        <%= Html.Form().RegularExpressionValidator("firstNameRegex", "firstName", "[a-zA-Z]*", "First Name can only contain letters.") %>
  11:        <br />
  12:        Age: <%= Html.TextBox("age") %>
  13:        <%= Html.Form().RequiredValidator("ageRequired", "age", "Age is Required.") %>
  14:        <%= Html.Form().RegularExpressionValidator("ageRegex", "age", "[0-9]*", "Age can only be numeric.") %>
  15:        <%= Html.Form().RangeValidator("ageRange", "age", "18", "35", ValidationDataType.Integer, "Age is not in target range of 18-35.") %>
  16:        <br />
  17:        <%= Html.SubmitButton("submit", "Save") %>
  18:        <% } %>
  19:        <%= Html.Form().ValidatorInitializationScripts() %>
  20:     </body>
  21:  </html>

At this point, I've posted it as a patch to MVC Contrib project, and hoping they apply it Smile. If you would like to get your hands on it, check out the patches page, mine is #1063. Please let me know your input, I tried making it as simple as possible to use, and I believe I've achieved that.

Update: My patch has been applied by Eric :) Get the latest build (>= 0.0.1.96) it if you'd like to check this out. Also, let me know of any issues you may find by logging bugs on the CodePlex site.



Comments

April 6. 2008 21:37

This is very impressive, Matt.

Now what would be nice is if the validation rules came from the model. Using the example from your code, let's say you had a Person class which had a method named GetValidators that returned an array of ValidationRules. That method could look like this:

public List<ValidatedProperty> GetValidators()
{
return new List<ValidatedProperty>{

   new ValidatedProperty("firstName", new List<ValidationRule>{
      new RequiredFieldValidation(),
      new RegexValidation( "[a-zA-Z]", "First Name can only contain letters" )
   },

   new ValidatedProperty( "age", new List<ValidationRule>{
      new RequiredFieldValidation( "Age is Required." ),
      new RegexValidation( "[0-9]*" ),
      new RangeValidation<int>( 18, 35 )
   }

};
}

Now it would be easy to pass the model into the view to construct the validation dynamically, like:

First Name: <%= Html.TextBox("firstName") %>
<%= Html.Validate( "firstName", Validations["firstName"] ) %>

The benefit of doing it like this is in the controller's Save() action, we could also reconstitute the validators from the model and double-check on the server side. Maybe something like:

public void Save()
{
  Person person = new Person( Request.Form["firstName"] );
  Binding.UpdateFrom( person, Request.Form );
  if( Validator.IsValid( person.GetValidators() )
     person.Save()
  else
     // throw an exception or whatever
}

What do you think? Sorry for the lack of formatting... =/

Troy Goode

April 7. 2008 15:19

I like that idea, we'll see when it can be implemented Smile

matthaw

April 9. 2008 15:40

Hey Matt - as a longtime user of your eWorld stuff it's nice to see you throw some love at MVC! Have some thoughts for you...

1) Agree with other points that you don't want to have to declare validation for "Last name can't be NULL" in every page that takes a last name (Registration, Ship To, Bill To, Contact, whatever). There's a lot that we know with the model already - in fact if you're a SubSonic user SmileSmileSmileSmile you know the lengths, nullability, datatypes... etc...
2) It might be interesting to creat a validation lib that works specifically with other frameworks. SubSonic is one of em Smile. You could also do a custom thing for LinqToSql (I have  some code... email me!)

That would rock Smile

Rob Conery

April 9. 2008 16:59

Pingback from code-inside.de

Wöchentliche Rundablage: ASP.NET MVC, Silverlight 2, .NET, RegEx, .NET, Icons, CSS, UI | Code-Inside Blog

code-inside.de

April 10. 2008 00:55

I agree with Troy.  I think the Model is the correct place to put the validation.  Consider something like an attribute style validation mechanism like the Application Validation Block.  By doing this you allow all views to leverage the same validation. When the view is rendered, you could interrogate the model for the validation attributes and inject those into the view for the pieces of the model that are presented in a form.

Scott Prugh

April 10. 2008 11:32

Pingback from mhinze.com

Links Today (2008-04-08)

mhinze.com

April 26. 2008 12:14

Pingback from weblogs.asp.net

47 ASP.NET MVC Resources to Rock Your Development - Craig Shoemaker

weblogs.asp.net

May 11. 2008 04:30

I m having problem using the MVC Contrib getting following error any assitance will be helpful for me

The type 'System.Web.Mvc.ComponentController' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'

<%=Html.Form().ValidatorRegistrationScripts %>

Muhammad Taufiq Yusuf

September 27. 2008 04:37

Hi,
I have recently install mvc.net preview 5. My web application was working before in preview 4. But now I am getting following error. Could someone help me please?:

Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

Compiler Error Message: CS0012: The type 'System.Web.Mvc.HtmlHelper' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

Source Error:



Line 4:  
Line 5:      <h2>Search Criteria</h2>
Line 6:        <%= Html.ErrorSummary("Sorry, there was a problem", (string[])TempData["errors"]) %>
Line 7:      <form action="<%= Url.Action("Search", new {str="Dummy"}) %>" method="post">
Line 8:         <b> hello here I am Srini</b>


Source File: c:\projectsh\vs9h\web\TestMvc\TestMvc\Views\Application\SearchRequest.aspx    Line: 6

srini

November 23. 2008 09:55

Hi, i'm using ASP.NET MVC Beta 1 Release and the latest version of MvcContrib, the problem is i want to use validation but the visual studio doesn't recognize the Html.Form tag. I try to use de FormHelper but it doesn't support types FormHelper<T> and neither accept arguments. Is there something change in Beta 1 version of MVC? Why  can't use Html.Form tag? Thank's in advance and sorry for my poor english

Fabiana Di Polo

March 22. 2009 06:19

You do need mvcfutures assembly. Is this correct?

Bayram Çelik

June 4. 2009 23:46

You may also want to check out the Validator Toolkit ASP.NET MVC on Codeplex. That helped me.
http://mvcvalidatortoolkit.codeplex.com

tom

Comments are closed

Copyright © 2000 - 2024 , Excentrics World