Używam Ajax.BeginForm do stworzenia formularza, który wykona postback w Ajax do określonej akcji kontrolera, a następnie, jeśli akcja się powiedzie, użytkownik powinien zostać przekierowany na inną stronę (jeśli akcja się nie powiedzie, zostanie wyświetlony komunikat o stanie za pomocą 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]
}
Jeśli usunięcie powiedzie się, zwracam wynik przekierowania:
[Authorize]
public ActionResult Delete(Int32 UserId)
{
UserRepository.DeleteUser(UserId);
return Redirect(Url.Action("Index", "Home"));
}
Ale widok indeksu kontrolera głównego jest ładowany do UpdateTargetId i dlatego kończy się strona na stronie. Dwie rzeczy, o których myślę:
- Albo projektuję to źle i powinienem obsługiwać ten typ akcji inaczej (nie używając Ajax).
- Zamiast zwracać wynik przekierowania, zwróć widok, który zawiera javascript, który wykonuje przekierowanie po stronie klienta.
Czy ktoś ma komentarze do nr 1? A jeśli punkt 2 jest dobrym rozwiązaniem, jak wyglądałby „przekierowany widok javascript”?
źródło
return JavaScript( "window.location = '" + Url.Action("Edit","Dispatch") + "'" );
Możesz zwrócić JSON z adresem URL i zmienić window.location za pomocą JavaScript po stronie klienta. Wolę ten sposób niż wywoływanie funkcji JavaScript z serwera, co wydaje mi się, że przerywa podział obaw.
Po stronie serwera:
return Json(new {result = "Redirect", url = Url.Action("ActionName", "ControllerName")});
Strona klienta:
if (response.result == 'Redirect') window.location = response.url;
Oczywiście możesz dodać więcej logiki, ponieważ może wystąpić błąd po stronie serwera iw takim przypadku właściwość result może wskazywać na taką sytuację i uniknąć przekierowania.
źródło
Zachowanie, które próbujesz uzyskać, nie jest najlepiej wykonywane przy użyciu technologii AJAX. AJAX byłby najlepszy, gdybyś chciał zaktualizować tylko część strony, a nie całkowicie przekierować na inną stronę. To naprawdę podważa cały cel AJAX.
Sugerowałbym, aby po prostu nie używać AJAX z zachowaniem, które opisujesz.
Alternatywnie możesz spróbować użyć jquery Ajax, który przesyła żądanie, a następnie określa wywołanie zwrotne po zakończeniu żądania. W wywołaniu zwrotnym możesz określić, czy się nie powiodło, czy powiodło się, a po pomyślnym przekierowaniu na inną stronę. Zauważyłem, że jquery Ajax jest dużo łatwiejszy w użyciu, zwłaszcza że i tak używam biblioteki do innych celów.
Możesz znaleźć dokumentację na temat jquery ajax tutaj , 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)
źródło
Chociaż nie jest 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
Model
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>
źródło
Używanie na
JavaScript
pewno załatwi sprawę.Możesz również użyć,
Content
jeśli to bardziej Twój styl.Przykład:
Kontroler MVC
[HttpPost] public ActionResult AjaxMethod() { return Content(@"http://www.google.co.uk"); }
Javascript
$.ajax({ type: 'POST', url: '/AjaxMethod', success: function (redirect) { window.location = redirect; } });
źródło
Możesz 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"); } });
źródło
Co powiesz na to :
public ActionResult GetGrid() { string url = "login.html"; return new HttpStatusCodeResult(System.Net.HttpStatusCode.Redirect,url) }
I wtedy
$(document).ajaxError(function (event, jqxhr, settings, thrownError) { if (jqxhr.status == 302) { location.href = jqxhr.statusText; } });
Lub
error: function (a, b, c) { if (a.status == 302) { location.href = a.statusText; } }
źródło
Musiałem to zrobić, ponieważ mam formularz logowania Ajax. Gdy użytkownicy logują się pomyślnie, przekierowuję do nowej strony i kończę poprzednie żądanie, ponieważ druga strona obsługuje przekierowanie z powrotem do strony uzależnionej (ponieważ jest to system logowania jednokrotnego STS).
Jednak chciałem również, aby działał z wyłączoną obsługą javascript, będąc centralnym przeskokiem logowania i wszystkim innym, więc wymyśliłem 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); }
źródło
Możesz po prostu zrobić jakiś rodzaj filtru odpowiedzi Ajax dla odpowiedzi przychodzących za pomocą $ .ajaxSetup . Jeśli odpowiedź zawiera przekierowanie MVC, możesz ocenić to wyrażenie po stronie JS. Przykładowy kod 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 to: „window.location = '/ Acount / Login'” powyższy filtr wykryje to i oszacuje, aby wykonać przekierowanie.
źródło
Nie jestem usatysfakcjonowany najlepszą odpowiedzią Josepha, zamiast naprawić właściwy problem, powiedział, że jest to zły przypadek użycia. W rzeczywistości jest wiele miejsc, na przykład jeśli konwertujesz stary kod do kodu Ajax i tam go POTRZEBUJESZ, to POTRZEBUJESZ go. W programowaniu nie ma wymówki, ponieważ nie tylko Ty kodujesz wszystkich złych i dobrych programistów i musisz pracować ramię w ramię. Więc jeśli nie przekierowuję kodu w Ajax, mój kolega programista może zmusić mnie do znalezienia rozwiązania. Tak jak lubię korzystać ze wszystkich wzorowanych witryn AMD lub mvc4, a moja firma może trzymać mnie z daleka od tego przez rok.
Porozmawiajmy teraz o rozwiązaniu.
Zrobiłem do diabła z obsługą żądań i odpowiedzi Ajaxa, a najprostszym sposobem, jaki znalazłem, było wysłanie kodów stanu do klienta i posiadanie jednej standardowej funkcji javascript do zrozumienia tych kodów. Jeśli po prostu wyślę na przykład kod 13, może to oznaczać przekierowanie.
Więc odpowiedź json, taka jak {statusCode: 13, messsage: '/ home / logged-in'}, oczywiście jest mnóstwo proponowanych wariantów, takich jak {status: 'success', code: 13, url: '/ home / logged-in ', komunikat:' Jesteś teraz zalogowany '}
itd., więc do własnego wyboru standardowych wiadomości
Zwykle dziedziczę z podstawowej klasy kontrolera i umieszczam wybór standardowych odpowiedzi, takich jak ta
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żywaniu $ .ajax intead z Ajax.BeginForm Bardzo chciałbym używać Jquery ajax i robię to, ale znowu to nie ja na całym świecie do podejmowania decyzji Mam aplikację pełną Ajax.BeginForm i oczywiście tego nie zrobiłem. Ale muszę z tym żyć.
Więc jest również pomyślne wywołanie zwrotne w formie początkowej, nie musisz używać jquery ajax, aby używać wywołań zwrotnych. Coś o tym tutaj Ajax.BeginForm, wzywa akcję, zwraca JSON, Jak uzyskać dostęp do obiektu JSON w mojej funkcji OnSuccess JS?
Dzięki
źródło
Jeśli jesteś przekierowany z klasy JavaScript
ten sam widok - inny kontroler
<strike>window.location.href = `'Home'`;</strike>
to nie ten sam widok
<strike>window.location.href = `'Index/Home'`;</strike>
źródło
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 wezwij do działania:
this.RedirectTo ("Indeks", "Cement");
Dodaj kod javascript do dowolnego globalnego pliku dołączonego do javascript lub pliku układu, aby przechwycić wszystkie żądania Ajax:
<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>
źródło
Jak mówi Ben Foster, możesz zwrócić JavaScript, a to przekieruje Cię na żądaną stronę.
Aby załadować stronę na bieżącej stronie:
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')");
źródło
Możesz uzyskać przekierowanie nie oparte na js z wywołania Ajax, wstawiając jeden z tych metatagów odświeżania. To wydaje się 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 przeglądarkę Firefox, przez co nie jest to zbyt przydatne.
źródło