Combining JQuery Form Validation and Ajax Submission with ASP.NET

asp.net 0 comments suggest edit

As I mentioned before, I’m really excited that we’re shipping jQuery with ASP.NET MVC and with Visual Studio moving forward. Just recently, we issued a patch that enables jQuery Intellisense to work in Visual Studio 2008.

But if you’re new to jQuery, you might sit down at your desk ready to take on the web with your knew found JavaScript light saber, only to stare blankly at an empty screen asking yourself, “Is this it?”

See, as exciting and cool as jQuery is, it’s really the vast array of plugins that really give jQuery its star power. Today I wanted to play around with integrating two jQuery plugins – the jQuery Form Plugin used to submit forms asynchronously and the jQuery Validation plugin used to validate input.

Since this is a prototype for something I might patch into Subtext, which still targets ASP.NET 2.0, I used Web Forms for the demo, though what I do here easily applies to ASP.NET MVC.

Here are some screenshots of it in action. When I click the submit button, it validates all the fields. The email field is validated after the input loses focus.

validation

When I correct the data and click “Send Comment”, it will asynchronously display the posted comment.

async-comment-response

Let’s look at the code to make this happen. Here’s the relevant HTML markup in my Default.aspx page:

<div id="comments" ></div>

<form id="form1" runat="server">
<div id="comment-form">
  <p>
    <asp:Label AssociatedControlID="title" runat="server" Text="Title: " />
    <asp:TextBox ID="title" runat="server" CssClass="required" />
  </p>
  <p>
    <asp:Label AssociatedControlID="email" runat="server" Text="Email: " />
    <asp:TextBox ID="email" runat="server" CssClass="required email" />
  </p>
  <p>
    <asp:Label AssociatedControlID="body" runat="server" Text="Body: " />
    <asp:TextBox ID="body" runat="server" CssClass="required" />
  </p>
  <input type="hidden" name="<%= submitButton.ClientID %>" 
    value="Send Comment" />
  <asp:Button runat="server" ID="submitButton" 
    OnClick="OnFormSubmit" Text="Send Comment" />
</div>
</form>

I’ve called out a few important details in code. The top DIV is where I will put the response of the AJAX form post. The CSS classes on the elements provide validation meta-data to the Validation plugin. What the heck is that hidden input doing there?

Notice that hidden input that duplicates the field name of the submit button. That’s the ugly hack part I did. The jQuery Form plugin doesn’t actually submit the value of the input button. I needed that to be submitted in order for the code behind to work. When you click on the submit button, a method named OnFormSubmit gets called in the code behind.

Let’s take a quick look at that method in the code behind.

protected void OnFormSubmit(object sender, EventArgs e) {
    var control = Page.LoadControl("~/CommentResponse.ascx") 
        as CommentResponse;
    control.Title = title.Text;
    control.Email = email.Text;
    control.Body = body.Text;

    var htmlWriter = new HtmlTextWriter(Response.Output);
    control.RenderControl(htmlWriter);
    Response.End();
}

Notice here that I’m just instantiating a user control, setting some properties of the control, and then rendering it to the output stream. I’m able to access the values in the submitted form by accessing the ASP.NET controls.

This is sort of like the Web Forms equivalent of ASP.NET MVC’s partial rendering ala the return PartialView() method. Here’s the code for that user control.

<%@ Control Language="C#" CodeBehind="CommentResponse.ascx.cs" 
    Inherits="WebFormValidationDemo.CommentResponse" %>
<div style="color: blue; border: solid 1px brown;">
    <p>
        Thanks for the comment! This is what you wrote.
    </p>
    <p>
        <label>Title:</label> <%= Title %>
    </p>
    <p>
        <label>Email:</label> <%= Email %>
    </p>
    
    <p>
        <label>Body:</label> <%= Body %>
    </p>
</div>

Along with its code behind.

public partial class CommentResponse : System.Web.UI.UserControl {
    public string Title { get; set; }
    public string Email { get; set; }
    public string Body { get; set; }
}

Finally, let’s look at the script in the head section that ties this all together and makes it work.

<script src="scripts/jquery-1.2.6.min.js" type="text/javascript"></script>
<script src="scripts/jquery.validate.js" type="text/javascript"></script>
<script src="scripts/jquery.form.js" type="text/javascript"></script>
<% if (false) { %>
<script src="scripts/jquery-1.2.6-vsdoc.js" type="text/javascript"></script>
<% } %>
<script type="text/javascript">
    $(document).ready(function() {
        $("#<%= form1.ClientID %>").validate({
            submitHandler: function(form) {
                jQuery(form).ajaxSubmit({
                    target: "#comments"
                });
            }
        });
    });
</script>

The if(false) section is for the jQuery intellisense, which only matters to me at design time, not runtime.

What we’re doing here is getting a reference to the form and calling the validate method on it. This sets up the form for validation based on validation meta data stored in the CSS classes for the form inputs. It’s possible to do this completely external, but one nice thing about this approach is now you can style the fields based on their validation attributes.

We then register the ajaxSubmit method of the jQuery Form plugin as the submit handler for the form. So when the form is valid, it will use the ajaxSubmit method to post the form, which posts it asynchronously. In the arguments to that method, I specify the #comments selector as the target of the form. So the response from the form submission gets put in there.

As I mentioned before, the hidden input just ensures that ASP.NET runs its lifecycle in response to the form post so I can handle the response in the button’s event handler. In ASP.NET MVC, you’d just point this to an action method instead and not worry about adding the hidden input.

In any case, play around with these two plugins as they provide way more rich functionality than what I covered here.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

17 responses

  1. Avatar for Kirk Clawson
    Kirk Clawson November 21st, 2008

    The link to the validation plugin is pointing to the Form plugin. :)

  2. Avatar for haacked
    haacked November 21st, 2008

    @Kirk. Fixed! Thanks!

  3. Avatar for Ajay
    Ajay November 21st, 2008

    Phil,
    Can we see some ASP.Net MVC samples with inbuilt Ajax helpers and jQuery combined. Its long pending, I guess.
    ASP.Net MVC Rocks!!! Keep up the good work.
    Thanks.

  4. Avatar for Thomas Hansen
    Thomas Hansen November 21st, 2008

    I think form input retrieval like these are a gazillion times easier to implement using something like Ra-Ajax ( http://ra-ajax.org )

  5. Avatar for rtpHarry
    rtpHarry November 21st, 2008

    Does this mean that I should be moving away from using the built in asp.net validator controls in future?

  6. Avatar for Kyle Baley
    Kyle Baley November 21st, 2008

    I can see this being useful to convert existing web pages to use AJAX form submission. But what are your thoughts on using this method vs. collecting the data you need and using $.ajax or $.post to send it to, say, an MVC action? I've been doing the latter because if feels more task-based. You collect the data you need, call a URL, and handle the callback all for a specific task, not an entire form. Plus then you don't actually need a form.

  7. Avatar for Matt Hinze
    Matt Hinze November 21st, 2008

    This doesn't really apply to most ajax scenarios. Why not just go the normal, non-ajax way with this form? You need validation (and server side) PLUS modals plus multiple forms and success and failure json wrappers to your response html.

  8. Avatar for Steve
    Steve November 21st, 2008

    Thanks Phil.
    I've been using the jquery form plugin with validators and it's worked well.
    Other worthwhile plugin's to explore:
    jquery mask
    jquery jqmodal - great for modal dialogs (http://dev.iceburg.net/jquery/jqModal/)
    jquery blockUI
    Now, what I've done personally is wrap this functionality up into Html helpers.
    ie.
    Html.Dialog()
    Additionally, adding 'ajax' validation support like above, I attach helpers to the normal forms (rather than create a separate 'ajax form helper'). That part is nice because it's easy to encapsulate all the validation scripts, etc... in the helpers.
    Glad to see jquery get some press - it's an incredible library - good support from the community - and truly 'unobtrusive'.
    I think MS should create a jquery plugin to do the ms ajax 'proxy' scripting - it's the one part of the ms ajax library that I like.
    Even better - ask Nikhil Kothari to include it in his Script# :)

  9. Avatar for Josh
    Josh November 21st, 2008

    I have been using the JQuery validation library since MVC Preview 4, and with great success. Adding in a few other JQuery libraries to your arsenal, you have the ability to really create some user friendly forms.

  10. Avatar for Justice~!
    Justice~! November 22nd, 2008

    @Ajay - tune in this coming week or two as I'll be talking about examples more than likely, or E-mail me and then I'll tell you.
    @Kyle - funny you should mention this!

  11. Avatar for Gabriel Bog&#233;a
    Gabriel Bog&#233;a November 22nd, 2008

    Hi Phil, I've been doing tests along these lines lately. I know you just wanted to demonstrate the plugins but I've been seeing a lot of people using jQuery to submit their forms instead of using the MVC Ajax.BeginFom helper. I usually prefer to use the helper methods when they are available instead of using jQuery.
    Is the jQuery form submit just another option or is the MVC team leaning towards leaving the ajax to jQuery and not focusing so much on the MVC ajax helpers?

  12. Avatar for Shiju Varghese
    Shiju Varghese November 23rd, 2008

    I did the blog post Ajax and Validations using jQuery with ASP.NET MVC Preview 5. Check weblogs.asp.net/.../...lidations-using-jquery.aspx

  13. Avatar for Josh
    Josh December 18th, 2008

    Are you sure about this line:
    var control = Page.LoadControl("~/CommentResponse.ascx")
    as CommentResponse;
    it looks like a vb to me. and it does not compile, of course. ('var' could not be found..."
    Thanks.

  14. Avatar for haacked
    haacked December 18th, 2008

    @Josh are you using ASP.NET 3.5? You can replace "var" with CommentResponse if not.

  15. Avatar for Naveed
    Naveed February 18th, 2009

    Thanks, its nice

  16. Avatar for skaue
    skaue March 30th, 2009

    Didn't get this to work with a page using a masterpage. I added a breakpoint in the OnFormSubmit event in default.aspx.cs, and it steps in there only the second time the form is submitted. The first time, the entire page is (re-)loaded in the comments-div.
    Crap, this is why I stayed with MVC, instead of strugling with webforms... :-(

  17. Avatar for Timur
    Timur February 9th, 2011

    @Tommy
    there is an issue not only with masterpages but in every complex case where input placed inside container so that id contains "_". Such id's in pure asp.net are returning with %24 and in haack's example with "_"... and no event fires.
    haack, can you assist in those cases?