RedirectToAction doesn't happen when I start with an AJAX call

473 views Asked by At

RedirectToAction "doesn't work" when is use an ajax call, why is that?

The Login action sends me to the action Index with RedirectToAction, so I can see that view is returned. And the AJAX call end up in done. Why doesn't the URL change to ../home/index as I would expect?

If I in done manually call window.location.href = "/WebConsole53"; I will get the redirect I want, but I would rather use the redirect on the server. Can someone figure out what is the problem? Thanks.

Ajax call:

$('#btnLogin').on('click', function() {
    var url = urlHelper.getUrl('Account/login');
    var data = {
        username: $('#inputLoginUsername').val(),
        password: $('#inputLoginPassword').val()
    }

    $.ajax({
        url: url,
        method: "POST",
        data: data
    })
    .done(function (html) {
        console.log('done login');
        //window.location.href = "/mySite"; // this works
    })
    .fail(function (jqXhr, textStatus, errorThrown) {
        console.log('failed');
    });
});

Action:

[HttpPost]
[AllowAnonymous]
//[ValidateAntiForgeryToken]
public ActionResult Login(string username, string password/*, LoginViewModel model*/, string returnUrl)
{
    //if (!ModelState.IsValid)
    //{
    //    return View(model);
    //}

    // This doesn't count login failures towards account lockout To enable password failures to trigger account lockout, change to shouldLockout: true
    //var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
    //switch (result)
    //{
    //    case SignInStatus.Success:
    //        return RedirectToLocal(returnUrl);
    //    case SignInStatus.LockedOut:
    //        return View("Lockout");
    //    case SignInStatus.RequiresVerification:
    //        return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
    //    case SignInStatus.Failure:
    //    default:
    //        ModelState.AddModelError("", "Invalid login attempt.");
    //        return View(model);
    //}

    return RedirectToAction("Index", "Home");
    //return RedirectToActionPermanent("Index", "Home");
    //return RedirectToLocal(returnUrl);
    //return RedirectToAction("ShowDashboard", "Dashboard");
}

Home Index:

public ActionResult Index()
{
    return View();
//            return RedirectToAction("Login", "Account");
//            return RedirectToAction("ShowDashboard", "Dashboard");
}

Solution - full credit goes to @Stephen Muecke

Use of form submit from html.helper see doc here

@using (Html.BeginForm("login", "Account"))
{
    @Html.TextBox("Name");
    @Html.Password("Password");
    <input type="submit" value="Sign In">
}
1

There are 1 answers

1
Andy Clark On

As per the comments; this is not really best practice. However, to answer your question, the redirect does not happen as the browser is not handling the response directly. Your handling the response in your success method.

If you want to redirect as a result of an AJAX call which is dictated by the server you can use the following:

$.ajax({
    url: url,
    method: "POST",
    data: data,
    success: function (data) {
        $("body").html(data);    //Providing the result is a response to redirect ONLY
    }
})

Effectively you are just overwriting the entire body with the response, which then the browser picks up as a redirect before anything is actually rendered.

However, if you take this approach you may want to cater for other status codes, the obvious being 500 because if you do this and there is an internal error; nothing will happen except a log to the browser console