20

I will update this problem with the solution, I wanted to include my problem and solution as I wasn't able to find it on Stackoverflow. If you want to jump in with the solution, feel free.

I have a newly created 'Empty' MVC5 project created using Visual Studio 2013. I needed a from and wanted AJAX behavior if possible. Using Ajax.BeginForm was always straight-forward in MVC3 so I thought it would be in MVC5 also.

However none of the javascript functions I've specified in OnBegin, OnFailure or OnSuccess inside the AjaxOptions are invoked when I click the submit button. Instead an Ajaxless post is sent to the server, this has shown to be true by examining Request.IsAjaxRequest which returns false.

I have concluded that for some reason, then, ajax isn't being used at all. I've checked a number of things such as web.config, my layout scripts, etc.

My layout includes the following scripts:

<script src="~/Scripts/jquery-1.5.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

My web.config includes:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
</configuration>

My view:

@model ContactEnquiryViewModel

@{
AjaxOptions ContactOptions = new AjaxOptions()
{
    OnBegin = "OnConactFormBegin()",    
    OnSuccess = "OnContactFormSuccess()",
    OnFailure = "OnContactFormFailure()"
    };
}

<div id="EnquiryFormContainer">

@using (Ajax.BeginForm("Contact", "Home", new { formName = "EnquiryForm" }, ContactOptions))
    {
    @Html.HiddenFor(m => m.Subject)

    <div class="field">
        @Html.LabelFor(m => m.FirstName)
        @Html.TextBoxFor(m => m.FirstName)
        <div class="validation">
            @Html.ValidationMessageFor(m => m.FirstName)
        </div>
    </div>

    <div class="field">
        @Html.LabelFor(m => m.LastName)
        @Html.TextBoxFor(m => m.LastName)
        <div class="validation">
            @Html.ValidationMessageFor(m => m.LastName)
        </div>
    </div>

    <div class="field">
        @Html.LabelFor(m => m.Email)
        @Html.TextBoxFor(m => m.Email)
        <div class="validation">
            @Html.ValidationMessageFor(m => m.Email)
        </div>
    </div>

    <div class="field">
        @Html.LabelFor(m => m.PhoneNumber)
        @Html.TextBoxFor(m => m.PhoneNumber)
        <div class="validation">
            @Html.ValidationMessageFor(m => m.PhoneNumber)
        </div>
    </div>

    <div class="field">
        @Html.LabelFor(m => m.Comments)
        @Html.TextAreaFor(m => m.Comments)
        <div class="validation">
            @Html.ValidationMessageFor(m => m.Comments)
        </div>
    </div>

    <div id="submitButtonContainer">
        <input type="submit" value="Submit" name="submit" />
    </div>
    }
</div>

My controller action (unfinished):

[HttpPost]
public ActionResult Contact(ContactViewModel viewModel, String formName = "")
    {
    if (Request.IsAjaxRequest())
        {
        return new EmptyResult();               
        }

    return new EmptyResult();
    }

I have checked some other posts on this problem, and couldn't find a solution. Though some hinted at the possible solution, I was confused by the Microsoft CDN (http://www.asp.net/ajaxlibrary/cdn.ashx).

On the Microsoft CDN they have the following section:

The following ASP.NET MVC JavaScript files are hosted on this CDN:

ASP.NET MVC 5.0

http://ajax.aspnetcdn.com/ajax/mvc/5.0/jquery.validate.unobtrusive.js
http://ajax.aspnetcdn.com/ajax/mvc/5.0/jquery.validate.unobtrusive.min.js

ASP.NET MVC 4.0

http://ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.js
http://ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.min.js

ASP.NET MVC 3.0

http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.js
http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.min.js
http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js
http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js
http://ajax.aspnetcdn.com/ajax/mvc/3.0/MicrosoftMvcAjax.js
http://ajax.aspnetcdn.com/ajax/mvc/3.0/MicrosoftMvcAjax.debug.js 

ASP.NET MVC 2.0

http://ajax.aspnetcdn.com/ajax/mvc/2.0/MicrosoftMvcAjax.js
http://ajax.aspnetcdn.com/ajax/mvc/2.0/MicrosoftMvcAjax.debug.js 

ASP.NET MVC 1.0

http://ajax.aspnetcdn.com/ajax/mvc/1.0/MicrosoftMvcAjax.js
http://ajax.aspnetcdn.com/ajax/mvc/1.0/MicrosoftMvcAjax.debug.js 

They would seem to suggest the only script you'll need for MVC5 is jquery.validate.unobtrusive.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Tentux
  • 714
  • 1
  • 4
  • 13
  • i guess there is a typo on the line `OnBegin = "OnConactFormBegin()";` – Melih Yıldız' Dec 05 '14 at 00:59
  • Yes, this was a typo, method should be OnContactFormBegin. – Tentux Feb 13 '15 at 13:28
  • As RitchieD has pointed out by using NuGet you can easily overcome these issues by fetching the appropriate libraries. If you're experiencing a problem like the one described it's likely due to missing libraries or incompatible libraries being used. – Tentux Feb 13 '15 at 13:30

8 Answers8

29

To get a local copy as part of your MVC project" From VS2013, right click on your MVC 5 project, select "Manage NuGet Packages". Select "Online" and search for "jquery.unobtrusive-ajax", Then Install "Microsoft.jQuery.Unobtrusive.Ajax".

Luke
  • 22,826
  • 31
  • 110
  • 193
RitchieD
  • 1,831
  • 22
  • 21
28

I had the same issue on a dummy MVC5 project.

Add this to your BundleConfig

        bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                    "~/Scripts/jquery.unobtrusive*",
                    "~/Scripts/jquery.validate*"));

Add this to your layout.cshtml

@Scripts.Render("~/bundles/jqueryval")

I didn't add any new files to my projects so if you have an MVC 4 or 5 web project, I doubt if you would need to add any extra js files.

It solved my issue. I hope it solves yours.

TGX
  • 81
  • 6
user3201809
  • 391
  • 3
  • 3
  • And this works fine when you've got the files local, but I quite like using the Content Delivery Networks provided by Microsoft, jQuery, etc. It spreads the bandwidth usage, plus users get to use local distribution networks close to their locality, and if many websites are referencing the same script from the same location I would presume caching saving would come into play. – Tentux Aug 26 '14 at 20:04
  • Specificly, we need `jquery.unobtrusive-ajax.js`. I needed to search Nuget for `Ajax`. – Christian Gollhardt Dec 02 '15 at 23:54
  • This is the correct solution as MVC4 and 5 indeed add this by default and the effect is that the 'jquery.unobtrusive-ajax.js' script is inserted in the page. – Peter Mar 09 '16 at 08:31
9

Everything has started working since I included the following script in my layout:

<script src="http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.min.js"></script>

On the Microsoft CDN it looks as though this script is MVC3-specific.

Feel free to contribute better ways if possible, or answer the question: "Why isn't this script included in the MVC project template (VS2013)?"

Tentux
  • 714
  • 1
  • 4
  • 13
  • 1
    It works for you because you are using obsolete version of jQuery. If you would use jQuery included in MVC 5 it would not work. Since the script you are including **is MVC 3 specific**. http://stackoverflow.com/a/15373173/368065 This is a proper solution for MVC 5. – Kikaimaru Feb 26 '14 at 11:13
  • I am using MVC 5 with jQuery 1.10 in a solution created with VS.2013 and AJAX works with jquery.unobtrusive-ajax.*.js together with the validation scripts. – Lord of Scripts Jun 20 '14 at 17:20
3

Did you check if your web.config file contains

<appSettings>
    <!-- this one is for client side validation -->
    <add key="ClientValidationEnabled" value="true" />

    <!-- this is for unobtrusive ajax -->
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Cagatay Kalan
  • 4,066
  • 1
  • 30
  • 23
1

I had the same issue and the solution was actually to make sure that the script references are in the right order (specifically that @Scripts.Render("~/bundles/jquery") appears before @Scripts.Render("~/bundles/jqueryval"))

For some reason it wasn't like it by default when creating the new project and adding the nuget packages

Erez breiman
  • 466
  • 4
  • 8
1

Adding reference to the javascript file jquery.unobtrusive-ajax.js worked for me.

Alexander
  • 11
  • 2
0

For me it was a little bit peculiar and counter-intuitive.

The page was displayed from the controller with a custom route attribute:

[Route("contact")]
[HttpGet]
public ActionResult Contact()
{
    return this.View();
}

but the POST action handling the AjaxRequest had no [Route("contact")] attribute and that's why it didn't work.

Cătălin Rădoi
  • 1,804
  • 23
  • 43
0

For me it was the way i posted the form: Changing <a href="#" onclick="$('form')[0].submit(); return false;">Submit</a> Into <button type="submit" value="">Submit</button> solved my problem.

TnZ
  • 1