How to get an ASP.NET MVC Ajax response to redirect to new page instead of inserting view into UpdateTargetId?

Viewed 152831

I am using the Ajax.BeginForm to create a form the will do an ajax postback to a certain controller action and then if the action is successful, the user should get redirected to another page (if the action fails then a status message gets displayed using the AjaxOptions UpdateTargetId).

using (Ajax.BeginForm("Delete", null,
        new { userId = Model.UserId },
        new AjaxOptions { UpdateTargetId = "UserForm", LoadingElementId = "DeletingDiv" },
        new { name = "DeleteForm", id = "DeleteForm" }))
   {
    [HTML DELETE BUTTON]
   }

If the delete is successful I am returning a Redirect result:

[Authorize]
public ActionResult Delete(Int32 UserId)
{
    UserRepository.DeleteUser(UserId);
    return Redirect(Url.Action("Index", "Home"));
}

But the Home Controller Index view is getting loaded into the UpdateTargetId and therefore I end up with a page within a page. Two things I am thinking about:

  1. Either I am architecting this wrong and should handle this type of action differently (not using ajax).
  2. Instead of returning a Redirect result, return a view which has javascript in it that does the redirect on the client side.

Does anyone have comments on #1? Or if #2 is a good solution, what would the "redirect javascript view" look like?

15 Answers

You can simply do some kind of ajax response filter for incomming responses with $.ajaxSetup. If the response contains MVC redirection you can evaluate this expression on JS side. Example code for JS below:

$.ajaxSetup({
    dataFilter: function (data, type) {
        if (data && typeof data == "string") {
            if (data.indexOf('window.location') > -1) {
                eval(data);
            }
        }
        return data;
    }
});

If data is: "window.location = '/Acount/Login'" above filter will catch that and evaluate to make the redirection.

The accepted answer works well except for the fact that the javascript is briefly displayed in whatever the ajax target element is. To get around this, create a partial view called _Redirect with the following code:

@model string
<script>
   window.location = '@Model';
</script>

Then, in the controller replace

return Redirect(Url.Action("Index", "Home"));

with

return PartialView("_Redirect",Url.Action("Index", "Home"));

The effect is the same as the accepted answer, but without the brief artifact in the display. Place the _Redirect.cshtml in the shared folder so it can be used from anywhere.

Related