Why does Ajax.BeginForm replace my whole page?

2019-01-23 22:26发布

问题:

Context: Asp.Net MVC3 w/Razor

I am trying to put a login form on a Razor layout (formerly master page) so that, when the user times out, s/he can be prompted to login without being redirected (as in RallyDev). So, I have created a partial _LogOn.cshtml with all the requisite stuff (username, etc.) inside an Ajax.BeginForm with an UpdateTargetId that points to a div that holds the logon controls inside the ajax form. The form posts back to the AccountsController.RefreshLogOn action, but obviously, the containing page may have been rendered from a different controller. The RefreshLogOn action returns PartialView("_LogOn"). In any case, my expectation/desire is that only the controls inside this div are replaced. What is happening instead is that my page location changes to /Accounts/RefreshLogon and the whole page is replaced by the partial. Is there another approach I should be taking?

Here's the relevant code:

_LogOn.cshtml

 @{
        using (Ajax.BeginForm("RefreshLogOn", "Accounts", 
            new AjaxOptions { 
                      OnSuccess = "logonSucceeded", 
                      OnFailure = "logonFailed",         
                      HttpMethod = "Post", 
                      UpdateTargetId = "user-info" }, 
            new { @id = "refresh"}))
        {  
        @Html.AntiForgeryToken()

       <div id="user-info">
                <p>Your session has expired.</p>
            <div class="error">@Html.ValidationSummary()</div>
            <table>
                <tr>
                    <td>Username:</td>
                    <td>@Html.TextBoxFor(model => model.UserName)</td>
                </tr>
                <tr>
                    <td>Password:</td>
                    <td>@Html.PasswordFor(model => model.Password)</td>
                </tr>
                <tr>
                    <td>Remember Me:</td>
                    <td>@Html.CheckBoxFor(model => model.RememberMe)</td>
                </tr>

            </table>
        </div>
            }
        }

AccountsController

public ActionResult RefreshLogOn (LogOnModel model)
{
    if (ModelState.IsValid)
    {
        if (MembershipService.ValidateUser(model.UserName, model.Password))
        {
            ...content elided...

            return PartialView("_LogOn");
        }

        ModelState.AddModelError("", ErrorMessages.IncorrectUsernameOrPassword);
    }

    return PartialView("_LogOn", model);
}

Ajax.BeginForm --> form tag generated:

<form action="/Accounts/RefreshLogOn" id="refresh" method="post" 
    onclick="Sys.Mvc.AsyncForm.handleClick(this, new Sys.UI.DomEvent(event));"
    onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event), 
    { 
    insertionMode: Sys.Mvc.InsertionMode.replace, 
    httpMethod: &#39;Post&#39;, 
    updateTargetId: &#39;user-info&#39;, 
    onFailure: Function.createDelegate(this, logonFailed), 
    onSuccess: Function.createDelegate(this, logonSucceeded) 
    });">

回答1:

Ajax.* helpers in ASP.NET MVC 3 use unobtrusive jquery so make sure that you have referenced the jquery.unobtrusive-ajax.js script in your view. Also you could use FireBug to see what's happening under the scenes and why the form doesn't send an AJAX request.

Also the UpdateTargetId = "form" seems suspicious especially when your form has the refresh id: @id = "refresh". Is there some other element inside your DOM with id="form"? Maybe you meant UpdateTargetId = "refresh"?



回答2:

Note: my problem was first, i referenced wrong ajax script file jquery.validate.unobtrusive.min.js instead of jquery.unobtrusive-ajax.js and latest jquery version doesn't worked, only jquery-1.7.1.min.js worked for me.

i was trying to return content after successful entry

so here is the order:

<script src="~/js/jquery-1.7.1.min.js"></script>
<script src="~/js/jquery.validate.min.js"></script>
<script src="~/js/jquery.unobtrusive-ajax.min.js"></script>

Post of Darin and Richard Everett helped. hope helps.



回答3:

I had the same problem and solution was:

  • Check that UnobtrusiveJavaScriptEnabled is true.
  • Add reference to jquery.unobtrusive-ajax.js as Darin adviced.

Unfortunatelly, it will not help for you because you set UnobtrusiveJavaScriptEnabled to false, but can help for somebody.



回答4:

Late but correct. Make sure to reference the unobtrusive-ajax.js file as well as the MicrosoftAjax.js and MicrosoftMvcAjax.js files in that order. Works



回答5:

Notice if you use Asp.Net template like I do, It bundles the file to bundles/jqueryval. So you have to add

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

to the page.



回答6:

Besides checking if the .js is referenced, also check if no other form tags are being rendered. In my case, I had another form tag on the master page with the default action that was causing the whole page to reload.