Introduction
This post is about mixing Microsoft MVC helpers with native jquery ajax. The main problems i encountered along the way were:
- Double post submissions
- @Html.ValidationMessageFor not outputting
attributes
Requirements
I have a requirement to validate and post a form (id = "my-form")
The form is bound to a model decorated with validation attributes so I want to make use of helper methods such as @Html.ValidationMessageFor to harness unobtrusive benefits
I need both client side and server side validation (server side i do a unique name check with the database)
I need to do some client side processing when submitting the form to add additional form data.
Iterative Steps
STEP 1
I started off with no native jquery and used a Microsoft helper to create the ajax form:
@using (Ajax.BeginForm( ...
All worked as advertised. This gave me unobtrusive validation but it did not fulfil my customised form data posting requirement.
So I thought I'd override the submit process.
STEP 2
In my document ready i hook up the new event handler:
$(document).ready(function ()
{
// Rebind validators
$.validator.unobtrusive.parse('#my-form');
// Hook up submit event
$("#my-form").submit(SubmitForm);
});
And in my submit function i can do my own form data handling:
function SubmitForm(e)
{
// Suppress normal event behaviour
e.preventDefault();
// Validate the form
var valid = $("#my-form").validate();
if (valid.errorList.length > 0)
return;
// Collect up form data manually
var formData = ...(code removed for clarity)
// Display animated gif
$("#ajax-loader").css("display", "inline")
// Post Form
$.post(
'@Url.Action("MyAction", "MyController")', // url
formData, // data
SuccessFunction // success
)
.error(ErrorFunction); // error
}
Okay the scene is now set.
Problem
One problem is that I'm mixing two types of ajax. This leads to double posts. Using fiddler I can see the post is happening twice. (Once for the micosoft form declaration and one for the jquery post) It's because 2 handlers have been hooked up. Doing a bit of googling i found some people are removing one handler using jquery but it all looked a bit messy.
STEP 3
So I changed the @using (Ajax.BeginForm( ... syntax into a simple form tag:
<form id = "my-form">
...
</form>
Problem
Now the @Html.ValidationMessageFor is not doing its stuff. Using firebug i can see that my form inputs no longer have validation attributes applied.
@Html.ValidationMessageFor seems to only work in conjunction with a form helper.
I can't use Ajax.BeginForm(... because i get double submissions.
STEP 4
So i next used:
@using (Html.BeginForm("MyAction", "MyController", FormMethod.Post, new { id = "my-form" }))
{....
I'm using the Html.BeginForm purely to make my @Html.ValidationMessageFor do their stuff. The "MyAction" and "MyController" parameters are all redundant because my custom event handler takes over the form submission process.
Resolved
Everything seems to now work
- No double submissions
- Unobtrusive validation using @Html.ValidationMessageFor
- Customised form handling / submission
- Client and server side validation
My question.
Is this the right approach? I'd be interested to hear anyone elses experiences along these lines.
Regards
Phil