2009-10-08 17 views
75

Używam formularza Ajax.BeginForm do utworzenia formularza, który wykona odsyłanie ajax'a do określonej akcji kontrolera, a następnie, jeśli akcja zakończy się powodzeniem, należy przekierować użytkownika na inną stronę (jeśli akcja się nie powiedzie, komunikat stanu zostanie pobrany wyświetlane przy użyciu AjaxOptions UpdateTargetId).Jak uzyskać odpowiedź Ajaxa ASP.NET MVC, aby przekierować na nową stronę zamiast wstawiania widoku do UpdateTargetId?

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

Jeżeli kasowania powiedzie Wracam wynik Przekierowanie:

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

ale widok Strona Główna Kontroler jest coraz załadowany do UpdateTargetId i dlatego skończyć z strony w stronie. Dwie rzeczy, myślę o:

  1. Albo ja architecting to źle i powinien obsługiwać ten typ działania inaczej (nie używając Ajax).
  2. Zamiast zwracać wynik przekierowania , należy zwrócić widok, który zawiera w nim javascript, który ma przekierowanie po stronie klienta.

Czy ktoś ma uwagi na temat nr 1? Lub jeśli # 2 jest dobrym rozwiązaniem, jak wyglądałby "widok przekierowania javascript"?

Odpowiedz

154

Y możesz użyć JavascriptResult, aby to osiągnąć.

Aby przekierować:

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

Aby odświeżyć aktualną stronę:

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

Wydaje najprostszą opcję.

+4

Awesome ... Pomógł mi. – CrazyCoderz

+4

To powinna być zaakceptowana odpowiedź. – Alex

+1

Zgadzam się, to jest właściwe podejście. Ta odpowiedź http://stackoverflow.com/a/2841608/498969 pokazuje, jak można domyślnie zastosować tę funkcję przy użyciu kontrolera podstawowego. –

12

Zachowanie, które próbujesz stworzyć, nie jest najlepiej wykonywane przy użyciu technologii AJAX. AJAX byłby najlepszy, gdybyś chciał tylko zaktualizować część strony, nie przekierowując całkowicie na inną stronę. To naprawdę pokonuje cały cel AJAX.

Proponuję po prostu nie używać AJAX z zachowaniem, które opisujesz.

Alternatywnie można spróbować użyć Ajax jquery, który przesyła żądanie, a następnie określić wywołanie zwrotne po zakończeniu żądania. W wywołaniu zwrotnym można określić, czy się nie powiodło, czy powiodło się, i przekierować na inną stronę po pomyślnym zakończeniu. Zauważyłem, że Ajax jQuery jest znacznie łatwiejszy w użyciu, zwłaszcza, że ​​i tak używam biblioteki do innych celów.

można znaleźć dokumentację o jquery ajax here, ale składnia jest następująca:

jQuery.ajax(options) 

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

jQuery.getJSON(url, data, callback) 

jQuery.getScript(url, callback) 

jQuery.post(url, data, callback, type) 
+0

tak to po prostu zrobić zwykłą pocztą do kasowania działania i w większości przypadków to się uda, a następnie mogę przekierować do Strona główna Indeks. W przypadkach, w których zakończy się niepowodzeniem, wyświetl inny widok z komunikatami o błędach i odpowiednimi działaniami, które użytkownik może podjąć. Brzmi dobrze? –

+0

Tak, to brzmi bardziej sensownie. – Joseph

+0

Poszedłem dalej, konwertując to z przesłania Ajaksu do regularnego testu POST, zgodnie z zaleceniem Josepha. To faktycznie działało lepiej, ponieważ dało mi to czystszy sposób obsługi wiadomości z potwierdzeniem usunięcia. –

8

Chociaż nie elegancki, działa na mnie w pewnych sytuacjach.

Kontroler

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

modelu

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> 
+1

Dlaczego nie elegancki? Jest mocno napisany i wydaje się jasny. Podoba mi się to podejście. +1 –

0

Nie jestem usatysfakcjonowany najlepszą odpowiedzią Józefa, zamiast naprawić poprawny problem, powiedział, że jest to niewłaściwy przypadek użycia. W rzeczywistości istnieje wiele miejsc, na przykład, jeśli konwertujesz starą bazę kodu do kodu ajaxowanego i tam POTRZEBUJESZ, to POTRZEBUJESZ. W programowaniu nie ma usprawiedliwienia, ponieważ to nie tylko ty, który kodujesz wszystkich złych i dobrych programistów i musisz pracować ramię w ramię. Więc jeśli nie koduję przekierowania w ajaxu mój kolega deweloper może zmusić mnie do znalezienia rozwiązania. Tak jak lubię używać wszystkich stron z wzorami AMD lub mvc4, a moja firma może mnie powstrzymać przez rok.

Porozmawiajmy teraz o rozwiązaniu.

Poczyniłem piekło w sprawie obsługi zapytań i odpowiedzi ajax i najprostszym sposobem, jaki odkryłem, było wysłanie kodów stanu do klienta i posiadanie jednej standardowej funkcji javascript w celu zrozumienia tych kodów. Jeśli po prostu wyślę na przykład kod 13, może to oznaczać przekierowanie.

Więc odpowiedź JSON jak {StatusCode: 13, messsage: '/ home/zalogowany'} oczywiście istnieje mnóstwo odmian zaproponowano jak {Stan: 'sukces', kod: 13, url: '/home/zalogowany, komunikat: «Jesteś zalogowany teraz»}

etc, więc do własnego wyboru standardowych komunikatów

Zazwyczaj Dziedziczenie z klasy bazowej kontrolera i umieścić mój wybór standardu odpowiedzi takie jak ten

public JsonResult JsonDataResult(object data, string optionalMessage = "") 
    { 
     return Json(new { data = data, status = "success", message = optionalMessage }, JsonRequestBehavior.AllowGet); 
    } 

    public JsonResult JsonSuccessResult(string message) 
    { 
     return Json(new { data = "", status = "success", message = message }, JsonRequestBehavior.AllowGet); 
    } 

    public JsonResult JsonErrorResult(string message) 
    { 
     return Json(new { data = "", status = "error", message = message }, JsonRequestBehavior.AllowGet); 
    } 

    public JsonResult JsonRawResult(object data) 
    { 
     return Json(data, JsonRequestBehavior.AllowGet); 
    } 

O używanie $ .ajax intead z Ajax.BeginForm Chciałbym użyć Jquery ajax i robię, ale znowu to nie ja na całym świecie podejmować decyzje Mam aplikację pełną Ajax.BeginForm i oczywiście nie zrobił Zrób to. Ale muszę z tym żyć.

więc jest sukces zwrotna w postać zbyt rozpocząć, nie trzeba użyć jQuery AJAX używają wywołań zwrotnych, Coś o tym tutaj Ajax.BeginForm, Calls Action, Returns JSON, How do I access JSON object in my OnSuccess JS Function?

Thanks

0

Jeśli przekierowanie z klasa JavaScript

sam widok - zmierzających kontroler

<strike>window.location.href = `'Home'`;</strike> 

nie jest sam widok

<strike>window.location.href = `'Index/Home'`;</strike> 
16

Można zwrócić JSON z adresem URL i zmienić window.location przy użyciu JavaScript po stronie klienta. Wolę to w ten sposób, niż wywoływanie funkcji JavaScript z serwera, co moim zdaniem łamie rozdzielenie obaw.

po stronie serwera:

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

po stronie klienta:

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

Oczywiście można dodać więcej logiki, ponieważ nie może być błąd po stronie serwera, a w tym przypadku nieruchomość wynik może wskazywać w tej sytuacji i unikaj przekierowania.

1

Potrzebowałem tego zrobić, ponieważ mam formularz logowania ajax. Kiedy użytkownicy logują się pomyślnie, przekierowuję na nową stronę i kończę poprzednie żądanie, ponieważ druga strona obsługuje przekierowanie z powrotem do strony ufającej (ponieważ jest to system SSS STS).

Jednak, ja też chciałem go do pracy z JavaScript wyłączone, będąc centralnym hop login i wszystko, więc wpadłem na to,

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); 

    } 
4

Korzystanie JavaScript pewnością wykonać zadanie.

Możesz również użyć Content, jeśli jest to bardziej Twój styl.

Przykład:

MVC Controller

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

JavaScript

$.ajax({ 
    type: 'POST', 
    url: '/AjaxMethod', 
    success: function (redirect) { 
     window.location = redirect; 
    } 
}); 
0

Dodaj klasę pomocniczą:

public static class Redirector { 
     public static void RedirectTo(this Controller ct, string action) { 
      UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext); 

      ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action)); 
     } 

     public static void RedirectTo(this Controller ct, string action, string controller) { 
      UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext); 

      ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action, controller)); 
     } 

     public static void RedirectTo(this Controller ct, string action, string controller, object routeValues) { 
      UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext); 

      ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action, controller, routeValues)); 
     } 
    } 

Następnie zadzwonić w swoim działaniu:

this.RedirectTo ("Index", "Cement");

Dodaj kod JavaScript, żeby jakikolwiek globalnej javascript zawiera plik lub plik układu przechwycić wszystkie ajax żądania:

<script type="text/javascript"> 
 
    $(function() { 
 
    $(document).ajaxComplete(function (event, xhr, settings) { 
 
      var urlHeader = xhr.getResponseHeader('AjaxRedirectURL'); 
 

 
      if (urlHeader != null && urlHeader !== undefined) { 
 
       window.location = xhr.getResponseHeader('AjaxRedirectURL'); 
 
      } 
 
     }); 
 
    }); 
 
</script>

0

Jako Ben Foster mówi, można zwrócić JavaScripts i będzie przekierowywać do wybranej strony.

Aby załadować stronę w aktualnej strony:

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

Aby załadować stronę w nowej karcie:

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

można po prostu napisać w Ajax Success jak poniżej:

$.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

Możesz po prostu zrobić jakiś filtr odpowiedzi ajax dla przychodzących odpowiedzi z $.ajaxSetup. Jeśli odpowiedź zawiera przekierowanie MVC, możesz ocenić to wyrażenie po stronie JS. Przykładowy kod dla JS poniżej:

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

Jeśli dane są: "window.location = '/ acount/Zaloguj'" powyżej filtra złapie to i ocenić, aby przekierowanie.

0

Możesz uzyskać przekierowania oparte na js z wywołania ajax, umieszczając jeden z tych znaczników odświeżania meta. Wydaje się, że to działa: return Content("<meta http-equiv=\"refresh\" content=\"0;URL='" + @Url.Action("Index", "Home") + "'\" />");

Uwaga: Odkryłem, że odświeżanie meta jest automatycznie wyłączane przez Firefoksa, co czyni go niezbyt użytecznym.

0

Jak o tym:

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

A potem

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

Or

error: function (a, b, c) { 
     if (a.status == 302) { 
     location.href = a.statusText; 
     } 
} 
Powiązane problemy