Feb 3, 2011

jQuery.validation breaks jQuery 1.5 ajax API

Today I found out (the hard way) that the use of the jQuery.validation plugin breaks the jQuery.ajax API. Since the Asp.net MVC 3 uses jQuery.validation for its unobtrusive validation it is included in the default project template. You can imagine my surprise when I updated jQuery to v1.5, and my heavy ajaxified MVC page stopped working correctly. Every ajax request contained an parseerror with an error message stating that the callback jQuery[some random string] was not called. I tried to fiddle with the ajax settings for JSONP (namely jsonp and jsonpCallback), but no matter how I set them, the error was still present.

error_example
Error message

So I started digging around, trying to replicate the problem. When I ran simple html pages $.ajax worked as expected. Then I started to gradually test all the jQuery plugins and found out that the plugin causing the error was jQuery.validation. So here is my reproduction and a simple workaround (the whole project is available here):

The controller:

using System.Linq;
using System.Web.Mvc;

public partial class DefaultController : Controller
{
  private static readonly int[] numbers = Enumerable.Range(1, 10).ToArray();

  public virtual ActionResult Index()
  {
    return View();
  }

  [HttpPost]
  [ValidateAntiForgeryToken]
  public virtual JsonResult SimpleArray(int id)
  {
    return Json(numbers.Concat(new [] { id }));
  }
}

The view:

@{ Layout = null; }
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
  <script src="/Scripts/jquery-1.5.js" type="text/javascript"></script>
  <script src="/Scripts/jquery.validate.js" type="text/javascript"></script>
</head>
  <body>
  <script type="text/javascript">
    $(function () {
      $('a').click(function (e) {
        var req = $.ajax({
            url: '@Url.Action(MVC.Default.SimpleArray())',
            type: 'POST',
            data: $('form').serializeArray(),
            dataType: 'json'
        });
        req.success(function (response, status, xhr) { alert('Success: ' + response); });
        req.error(function (xhr, error, msg) { alert('Error "' + error + '": ' + msg); });
      });
    });
  </script>
  <a href="javascript:void(0);">Do request</a>
  <form action="#">
    <input type="hidden" value="-1" name="id" />
    @Html.AntiForgeryToken()
  </form>
</body>
</html>

The workaround:

$(function () {
$.ajaxSettings.cache = false;
$.ajaxSettings.jsonp = undefined;
$.ajaxSettings.jsonpCallback = undefined;
})


The cause of the problem is this line of JavaScript in jQuery.validate.js, that overrides the settings you pass into the $.ajax call with all the default ones (and jQuery.ajaxSettings defaults to { jsonp: "callback", jsonpCallback: function() {...}}):


// create settings for compatibility with ajaxSetup 
settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));

Cheers!

2 comments:

Julian A said...

Nullifying the jsonp and jsonpCallback properties of ajaxSettings will break jsonp.

I forked jQuery validation and made a patch to make it compatible with jQuery 1.5 by feature-detecting if jQuery supported ajax prefilters and using them when available.

Project page: https://github.com/jaubourg/jquery-validation

Full text script: https://github.com/jaubourg/jquery-validation/raw/master/jquery.validate.js

Minified script: https://github.com/jaubourg/jquery-validation/raw/master/jquery.validate.min.js

Anonymous said...

We have investigated and analyzed quantity of|numerous|a variety of} actual money slot sport proposals to develop an unique record of licensed corporations and websites that provide slots of all genres. In addition to fit bonuses given out in digital casinos, might also|you can even} be supplied inside offers for 카지노사이트 explicit video games, supplied by renowned slot providers on the web. In this case, the sport itself includes bonus rounds that will let you double or triple your income or win further spin-offs, which you won't|you will not} have to bet for. These sorts of slot bonuses are also available within free slot video games - nonetheless, the player receives solely digital factors, as a substitute of actual money rewards. High payout slots - don't let the shiny appearance of some broadly marketed slot video games deceive you.