Как получить ответ ASP.NET MVC Ajax для перенаправления на новую страницу вместо вставки представления в UpdateTargetId? - PullRequest
83 голосов
/ 08 октября 2009

Я использую Ajax.BeginForm для создания формы, которая выполнит обратную передачу ajax для определенного действия контроллера, а затем, если действие выполнено успешно, пользователь должен быть перенаправлен на другую страницу (в случае сбоя действия появляется сообщение о состоянии). отображается с помощью 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]
   }

Если удаление прошло успешно, я возвращаю результат перенаправления:

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

Но представление Home Controller Index загружается в UpdateTargetId, и поэтому я получаю страницу внутри страницы. Две вещи, о которых я думаю:

  1. Либо я это архитектор неправильно и должен обрабатывать этот тип действовать по-другому (не используя ajax).
  2. Вместо возврата перенаправления результат, вернуть представление, которое имеет JavaScript в нем, который делает перенаправление на стороне клиента.

У кого-нибудь есть комментарии к № 1? Или, если # 2 является хорошим решением, как будет выглядеть «представление перенаправления javascript»?

Ответы [ 14 ]

164 голосов
/ 15 августа 2011

Вы можете использовать JavascriptResult для достижения этой цели.

Для перенаправления:

return JavaScript("window.location = 'http://www.google.co.uk'");

Чтобы перезагрузить текущую страницу:

return JavaScript("location.reload(true)");

Кажется, самый простой вариант.

21 голосов
/ 10 июля 2014

Вы можете вернуть JSON с URL и изменить window.location с помощью JavaScript на стороне клиента. Я предпочитаю этот способ, чем вызывать функцию JavaScript с сервера, что, по-моему, нарушает разделение интересов.

Серверная сторона:

return Json(new {result = "Redirect", url = Url.Action("ActionName", "ControllerName")});

Клиентская сторона:

if (response.result == 'Redirect')
    window.location = response.url;

Конечно, вы можете добавить больше логики, потому что на стороне сервера может быть ошибка, и в этом случае свойство result может указывать на эту ситуацию и избегать перенаправления.

12 голосов
/ 08 октября 2009

Поведение, которое вы пытаетесь воспроизвести, на самом деле лучше всего не использовать AJAX. AJAX лучше всего использовать, если вы хотите обновить только часть страницы, а не полностью перенаправить на какую-то другую страницу. Это действительно побеждает всю цель AJAX.

Я бы предложил не использовать AJAX с описанным вами поведением.

В качестве альтернативы, вы можете попробовать использовать jquery Ajax, который отправит запрос, а затем вы укажете обратный вызов, когда запрос завершится. В обратном вызове вы можете определить, не удалось или не удалось, и перенаправить на другую страницу в случае успеха. Я обнаружил, что jquery Ajax намного проще в использовании, тем более что я все равно уже использую библиотеку для других целей.

Документацию по jquery ajax можно найти здесь , но синтаксис следующий:

jQuery.ajax( options )  

jQuery.get( url, data, callback, type)

jQuery.getJSON( url, data, callback )

jQuery.getScript( url, callback )

jQuery.post( url, data, callback, type)
11 голосов
/ 12 июля 2011

Хотя не элегантно, у меня работает в определенных ситуациях.

Контроллер

if (RedirectToPage)
    return PartialView("JavascriptRedirect", new JavascriptRedirectModel("http://www.google.com"));
else
   ... return regular ajax partialview

Модель

    public JavascriptRedirectModel(string location)
    {
        Location = location;
    }

    public string Location { get; set; }

/ Views / Shared / JavascriptRedirect.cshtml

@model Models.Shared.JavascriptRedirectModel

<script type="text/javascript">
    window.location = '@Model.Location';
</script>
5 голосов
/ 17 марта 2015

Использование JavaScript определенно сделает работу.

Вы также можете использовать Content, если это больше ваш стиль.

Пример:

Контроллер MVC

[HttpPost]
public ActionResult AjaxMethod()
{
    return Content(@"http://www.google.co.uk");
}

Javascript

$.ajax({
    type: 'POST',
    url: '/AjaxMethod',
    success: function (redirect) {
        window.location = redirect;
    }
});
3 голосов
/ 08 сентября 2016

Вы можете просто написать в Ajax Success, как показано ниже:

 $.ajax({
            type: "POST",
            url: '@Url.Action("GetUserList", "User")',
            data: { id: $("#UID").val() },
            success: function (data) {
                window.location.href = '@Url.Action("Dashboard", "User")';
            },
            error: function () {
                $("#loader").fadeOut("slow");
            }
});
1 голос
/ 28 апреля 2017

Как насчет этого:

public ActionResult GetGrid()
{
   string url = "login.html";
   return new HttpStatusCodeResult(System.Net.HttpStatusCode.Redirect,url)
}

А потом

$(document).ajaxError(function (event, jqxhr, settings, thrownError) { 
   if (jqxhr.status == 302) {
      location.href = jqxhr.statusText;
   }           
});

Или

error: function (a, b, c) {
       if (a.status == 302) {
         location.href = a.statusText;
       }  
}
1 голос
/ 27 октября 2016

Вы можете просто сделать какой-то фильтр ответов ajax для входящих ответов с помощью $. AjaxSetup . Если ответ содержит перенаправление MVC, вы можете оценить это выражение на стороне JS. Пример кода для JS ниже:

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

Если данные: "window.location = '/ Acount / Login'" выше фильтра поймает это и оценит для перенаправления.

1 голос
/ 28 июля 2014

Мне нужно было сделать это, потому что у меня есть форма входа в AJAX. Когда пользователи успешно входят в систему, я перенаправляю на новую страницу и завершаю предыдущий запрос, потому что другая страница обрабатывает перенаправление обратно проверяющей стороне (потому что это система единого входа STS).

Однако я также хотел, чтобы он работал с отключенным javascript, являющимся центральным узлом входа в систему и все, поэтому я придумал это,

    public static string EnsureUrlEndsWithSlash(string url)
    {
        if (string.IsNullOrEmpty(url))
            throw new ArgumentNullException("url");
        if (!url.EndsWith("/"))
            return string.Concat(url, "/");
        return url;
    }

    public static string GetQueryStringFromArray(KeyValuePair<string, string>[] values)
    {
        Dictionary<string, string> dValues = new Dictionary<string,string>();
        foreach(var pair in values)            
            dValues.Add(pair.Key, pair.Value);            
        var array = (from key in dValues.Keys select string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(dValues[key]))).ToArray();
        return "?" + string.Join("&", array);
    }

    public static void RedirectTo(this HttpRequestBase request, string url, params KeyValuePair<string, string>[] queryParameters)
    {            
        string redirectUrl = string.Concat(EnsureUrlEndsWithSlash(url), GetQueryStringFromArray(queryParameters));
        if (request.IsAjaxRequest())
            HttpContext.Current.Response.Write(string.Format("<script type=\"text/javascript\">window.location='{0}';</script>", redirectUrl));
        else
            HttpContext.Current.Response.Redirect(redirectUrl, true);

    }
0 голосов
/ 17 апреля 2017

Вы можете получить перенаправление не на основе js от вызова ajax, вставив один из этих тегов метаобновления. Это здесь, кажется, работает: return Content("<meta http-equiv=\"refresh\" content=\"0;URL='" + @Url.Action("Index", "Home") + "'\" />");

Примечание: я обнаружил, что обновление мета автоматически отключается Firefox, что делает это не очень полезным.

...