Kaytee Frei

Web Developer

Hello there! I'm Kaytee Frei, a web developer located in Central WI. I have a broad range of web skills, but my true passion lies in creating simple and visually appealing experiences.

MVC 5 Ajax.BeginForm doesn't work OOTB

Over the past few weeks I've been working on converting an existing site (built with MVC 4) to a new project. We've got a new design and are updating from Bootstrap 2.* to Bootstrap 3.*, updating from MVC 4 to MVC 5, and making several other changes to incorporate our new company framework.

The old MVC 4 project was started way back when I was still learning the MVC pattern/framework and is definitely in need of some updates and cleaning up. Because so much was changing, we decided as a team that starting with a fresh new project and pulling in what we could from the old project as needed was the best way to go. The downside to doing this is that there are a lot of configuration pieces that go into just getting a project up and running, much less doing anything exciting. Visual Studio 2013 has a ton of project templates, several just for MVC Web projects, and they've gotten pretty good as far as including all the standard things to get you started.

However, today I found a hole in the MVC 5 Web Template that we started with. I was trying to use their Ajax form helper to submit a form without reloading the whole page (using Ajax.BeginForm), but the Ajax portion of it was not working. It was doing a full "post back" just like it would if I was using Html.BeginForm, and therefore was not triggering my functions that I specified for OnSuccess and OnFailure. It wasn't even validating. So I searched around a bit and realized that I had to add the reference to the jQuery validation bundle (@Scripts.Render("~/bundles/jqueryval")) in my Layout file. After adding this reference to my Layout file, the fields were being validated. If there was an error, the form wasn't being submitted (which is good/expected). However, if there were no input errors, the form was submitted, but not with Ajax (the whole page was reloaded).

I did some searching but couldn't find any helpful posts on the ASP.NET MVC site about using an Ajax form, and couldn't really find any post that specifically listed all the javascript files that I needed to include for the validation/ajax to work. It seemed like it should've been working, and was misleading that the template included a validation bundle. I assumed it would include everything needed for both HTML and Ajax forms. Silly me.

Several posts said to reference the Microsoft Ajax files (MicrosoftAjax.debug.js and MicrosoftMvcAjax.debug.js) but they are now deprecated and have been replaced. Several posts said to make sure that "jquery.unobtrusive*" is included in your validation bundle. The validation bundle created by the template did NOT include that line, and there were also no files included in the project that would match that reference. So I thought maybe these posts were a little out-dated and were referencing another deprecated file. I kept searching for other possible problems but came up with nothing.

I decided to create a new project that I could play around with and see if it was some of the custom code that I had written that was possibly clashing with a new MVC 5 feature or was for some other reason causing the Ajax to not work properly. Even with just the bare minimum amount of code, the ajax call did not work. At least it wasn't anything I had written that was causing this to fail. Turns out you do need to include "jquery.unobtrusive*" in your validation bundle, but you also need to add a NuGet package that adds the necessary javascript files to your project (Microsoft jQuery Unobtrusive Ajax).

Maybe someone had a good reason for not including this package in the template, but I can't think of any. Especially when you look at all of the other (probably unnecessary) packages that are included by default. I didn't see any sort of disclaimer or note about having to add a package when trying to use Ajax.Begin form, in fact I haven't even seen a good example on how to use it all. All the examples on the ASP.NET site seem to use Html.BeginForm and here are is the lovely results you get when you search for Ajax.BeginForm on their site:

Search Results

NuGet Packages

Here is breakdown of all of the NuGet packages that have an impact on this particular issue. I've included the name of the package, whether or not it is included with the ASP.NET Web Application MVC Template, and the files that are included in each of them (files that include the version number in their name may be on a different version than what they were when I wrote this post). I left the .map, .intellisense, and -vs-doc files out of these lists.

Package: "jQuery" (Included, but can be updated)

  • jQuery-1.10.2.js (jquery-2.1.1.js if you update)
  • jQuery-1.10.2.min.js (jquery-2.1.1.min.js if you update)

Package: "jQuery Validation" (Included, but can be updated)

  • jQuery.validate.js
  • jQuery.validate.min.js

Package: "Microsoft jQuery Unobtrusive Validation" (Included, but can be updated)

  • jQuery.validate.unobtrusive.js
  • jQuery.validate.unobtrusive.min.js

Package: "Microsoft jQuery Unobtrusive Ajax" (NOT Included, but needed for Ajax.BeginForm to work)

  • jQuery.unobtrusive-ajax.js
  • jQuery.unobtrusive-ajax.min.js

Here is some sample code that should work if you've included the correct packages and references.

Update: If you are still having trouble getting this to work after following all the steps above, you may be missing a couple lines in your web.config (the one at the root level, not the one in the Views folder). Check to see if your form has onclick and onsubmit attributes that start with "Sys.Mvc.AsyncForm.handle..." and also check for the following javascript error after clicking into and out of a text box: "Uncaught ReferenceError: Sys is not defined". If this is what's happening for you, you need to add two appSettings keys to your web.config inside the configuration node:

    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
comments powered by Disqus