14

There are so many topics on SO about issues with the Ajax.BeginForm not correctly updating the target element with the return partial view:
mvc4 ajax updating same page
ASP.NET MVC 4 - Ajax.BeginForm and html5
MVC 4 (razor) - Controller is returning a partialview but entire page is being updated
MVC 4 Ajax is not updating the PartialView within the page
However, all of these are answered by either manually writing out the jQuery ajax, or including a missing javascript file.

  @using (Ajax.BeginForm("PostcardDetails", new AjaxOptions()
  {
    InsertionMode = InsertionMode.Replace,
    UpdateTargetId = "details"
  }))
  {
    <div id="PostcardSearchResults">
      @{Html.RenderAction("PostcardSearchResults", Model);}
    </div>
  }
  <div id="details">
  </div>

Relevant controller code:

[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Get)]
public ActionResult PostcardSearchResults(PostcardSearchFilter filter)
{
        PostcardSearchResults model = new PostcardSearchResults(filter);
        return PartialView("_PostcardSearchResults", model);
}

In my layout, I am referencing these jQuery files. Additionally, I've verified that the page is outputting the proper path, and that it finds the correct files. I've tried switching the ordering of unobtrusive-ajax.min.js and validate.min.js, to no success.

<script type="text/javascript" src="@Url.Content("~/Scripts/globalize.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery-1.9.1.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery-ui-1.10.0.custom.min.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>

Additionally, in my website's root web.config, and the web.config in my View folder, I have included:

<add key="webpages:Version" value="2.0.0.0"/>
<add key="PreserveLoginUrl" value="true"/>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>

I'm at a loss for where else to look. There are no javascript errors being thrown, and the controller is being properly hit, returning a PartialViewResult. The Form element in the HTML is populating all the correct data- attributes.

Community
  • 1
  • 1
drovani
  • 928
  • 1
  • 17
  • 37

12 Answers12

13

There is a problem with jquery.unobtrusive-ajax.min and JQuery 1.9 because JQuery 1.9 doesn't support the live() method any more. So you should use the JQuery migrate plug-in, and reference the JQuery migrate js.

Robert
  • 4,306
  • 11
  • 45
  • 95
  • 1
    A bit confused, what does it have to do with OP issue ? Are you saying .live is what Ajax.Beginform uses under the hood ? – InspiredBy Feb 26 '13 at 18:02
  • Forgot to mention that I'd already updated my `jquery.unobtrusive-ajax.min.js' with the suggestions from this post: http://stackoverflow.com/a/14512797/28310 If I hadn't, I would be getting javascript errors. I also tried using the jquery-migrate. – drovani Feb 26 '13 at 18:20
  • 1
    Yeah Ajax Beginform uses live under the hood – Gabriel Monteiro Nepomuceno Feb 26 '13 at 18:24
  • 1
    The controller is being called correctly? and what you got when you got the return? – Gabriel Monteiro Nepomuceno Feb 26 '13 at 18:26
  • I've added the code for the action in the Controller. It returns the PartialView, rendered correctly, but the browser replaces the entire page with the table, as opposed to placing it in the `#details` div. – drovani Feb 26 '13 at 20:29
  • 1
    You are using MVC4 so you don't need to put the @Url.Content("~/Scripts/globalize.js") use just "~/Scripts/globalize.js" the scenario that you describe usually happen when the scripts are not referenced correctly – Gabriel Monteiro Nepomuceno Feb 27 '13 at 02:20
  • 3
    I ended up rolling my jquery.unobtrusive-ajax.min.js back to the original file (which takes it back to using the `live()` method, and including the jQuery migrate plug-in. This solved the issue. – drovani Mar 03 '13 at 15:52
  • 1
    This solved my issue!!! Wish I read it 5 hours before banging my head on my desk!.. Thanks Gabriel. – nav Oct 23 '13 at 14:10
5

Make sure you include the unobtrusive-ajax.js to the page, which you have placed your ajax form.

<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
Cyrus
  • 99
  • 1
  • 2
2

I had this problem, I just installed the latest unobtrusive package from NuGet and solved the problem

PM> Install-Package Microsoft.jQuery.Unobtrusive.Ajax

Will need JQ 1.8+

Andy
  • 21
  • 1
2

I don't know if anyone else will run into this, but in my case, it only appeared to not be updating. I was building an simple edit form where you select the item you wish to edit from a dropdown, click a button, and it AJAX loads an edit form for the selected item.

It worked the first time, but after changing my selection in the drop down list, and clicking the button, none of the form values changed, even though I verified my server-side code was loading the new item into the view model. So it appeared Replace was not working. After stepping through jquery.unobtrisive-ajax.js, I found that it was replacing the contents of my target element, just with the same view markup it already had, which did not match the model that was passed to the view!

That's when I realized, it was the ModelState that was getting me. The second time I clicked the load button, it submitted my dropdown selection but also my filled out edit form. All of the values in the edit form were added to ModelState (as you would expect). My controller code then replaced the submitted view model (that the model binder created from the edit form values) with the view model for the selected drop down value and passed it to the partial view. However, the partial view uses a bunch of the Html.[X]For helper methods. These ignore the updated view model and pull their values directly from the ModelState. For example:

@Html.DisplayFor(m => m.Name)
@Model.Name

would display two different values for Name; the former displaying the submitted Name and the latter, the updated Name. This is the mechanism that lets MVC remember your user's form entries after a (server-side) validation error. In this case, because this is a partial page load and I'm just throwing out all of the submitted values, I don't need any of the ModelState values so I just call ModelState.Clear() before returning my view for the updated view model.

    public ActionResult GetItemEditForm(EditItemsViewModel editItemsVM)
    {
        if (editItemsVM.SelectedItemID != null)
        {
            //Load the selected item
            ItemsModelManager.GetEditItemsVM(editItemsVM);

            //Clear the submitted form values
            ModelState.Clear();
        }

        return PartialView("_ItemsEditor", editItemsVM);
    }
xr280xr
  • 12,621
  • 7
  • 81
  • 125
  • Thanks fren. Your answer made me look back at the code again to realize the previous dev was returning Content(singleProperty) instead of a PartialView(model) which is what my updated markup expected. – TechSavvySam Jun 23 '20 at 17:24
1

I was having similar problems to you - I had all my scripts bundled and loading correctly, and had all code implemented correctly. I checked package manager to see if any scripts needed to be updated and jQuery and jquery.unobtrusive-ajax did. jQuery went from 1.9 to 1.9.1. When I rebuilt my solution the target DIV was updated successfully. Try and update all JS in your solution, it may work.

MattSull
  • 5,514
  • 5
  • 46
  • 68
1

The following needs to be on any page that uses ajax.

@section Script {
    @Scripts.Render("~/bundles/jqueryval")
}
1

Wow, there are a lot of answers here. My problem was due to a bootstrap panel. It was creating a "nested" panel. I removed the panel markup and just used a plain old div and it worked. I think the UpdateTargetId has to be a direct parent of the AJAX form.

Here is the html illustrating the problem.

<div class="panel panel-default" id="notes-form">
  <div class="panel-body">
    @using (Ajax.BeginForm("EditNote", new { id = Model.Id }, new AjaxOptions { UpdateTargetId = "notes-form" }, htmlAttributes: new { @class = "form-horizontal" }))
    {
    }
  </div>
</div>
Jess
  • 23,901
  • 21
  • 124
  • 145
0

For those that need a bit more explanation....

Type this in Package Manager Console PM> Install-Package jQuery.Migrate

Reference this in your partialview:

script src="~/Scripts/jquery.unobtrusive-ajax.js">

Happy coding everyone.

cyclical
  • 395
  • 4
  • 14
0

User xr280xr's answer for including

ModelState.Clear();

worked for me. The app I'm working with is on an older jQ (1.7.x) so migrate wouldn't work in our situation. Clearing the model state in the controller did exactly what we expected BeginForm to do.

Jason Turnage
  • 59
  • 1
  • 5
0

Check The Master Page OR Your Page's Scripts Reference about jquery.unobtrusive-ajax.js if not add Reference about this js :jquery.unobtrusive-ajax.js

0

The live() method was deprecated in jQuery version 1.7, and removed in version 1.9. Use the on() method instead.For more info refer: http://www.w3schools.com/jquery/event_live.asp

0

First, install 'Microsoft.JQuery.Unobtrusive.Ajax' from NuGet Manager and later include "~/Scripts/jquery.unobtrusive" in "BundleConfig" after including "jquery-{version}.js"; which will look something similar to this:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                "~/Scripts/jquery-{version}.js",
                "~/Scripts/jquery.unobtrusive*));