UpdateTargetId'e görünüm eklemek yerine yeni sayfaya yönlendirmek için bir ASP.NET MVC Ajax yanıtı nasıl alınır?


88

Bir form oluşturmak için Ajax.BeginForm'u kullanıyorum, belirli bir denetleyici eylemine ajax geri gönderimi yapacak ve ardından eylem başarılı olursa, kullanıcı başka bir sayfaya yönlendirilmelidir (eylem başarısız olursa, bu durumda bir durum mesajı görüntülenir. 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]
   }

Silme başarılı olursa, bir Yeniden Yönlendirme sonucu döndürüyorum:

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

Ancak Ev Denetleyici Dizini görünümü UpdateTargetId'ye yükleniyor ve bu nedenle bir sayfa içinde bir sayfayla sonuçlanıyorum. Düşündüğüm iki şey:

  1. Ya bunu yanlış tasarlıyorum ve bu tür eylemi farklı şekilde ele almalıyım (ajax kullanmadan).
  2. Bir Yönlendirme sonucu döndürmek yerine, istemci tarafında yeniden yönlendirmeyi yapan içinde javascript bulunan bir görünüm döndürün.

# 1 hakkında yorum yapan var mı? Ya da 2 numaralı çözüm iyi bir çözümse, "yeniden yönlendirme javascript görünümü" nasıl görünür?

Yanıtlar:


171

Bunu JavascriptResultbaşarmak için kullanabilirsiniz .

Yeniden yönlendirmek için:

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

Mevcut sayfayı yeniden yüklemek için:

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

En basit seçenek gibi görünüyor.


1
Katılıyorum, bu doğru yaklaşım. Bu yanıt stackoverflow.com/a/2841608/498969 , bir temel denetleyici kullanarak bu işlevi varsayılan olarak nasıl uygulayabileceğinizi gösterir.
Adam Spicer

@Ben Foster: Bu taramayı kullanarak http :: window.location .. url'sini açmaya çalışır. Bunu stackoverflow.com/questions/13896307/…
Andrus

30
Projenizdeki bir denetleyiciye yeniden yönlendirmek istiyorsanız, sizin için Url yardımcısını kullanabilirsiniz. Örneğin:return JavaScript( "window.location = '" + Url.Action("Edit","Dispatch") + "'" );
Chris Morgan

Bu ağlamak istememe neden oluyor. Fikirlerin ve temel denetleyici fikrinin birleşimi harika.
secretwep

30

URL ile bir JSON döndürebilir ve istemci tarafında JavaScript kullanarak window.location'ı değiştirebilirsiniz. Sunucudan bir JavaScript işlevini çağırmaktansa bu yolu tercih ediyorum, ki bunun kaygıları birbirinden ayırdığını düşünüyorum.

Sunucu tarafı:

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

İstemci tarafı:

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

Elbette daha fazla mantık ekleyebilirsiniz çünkü sunucu tarafında bir hata olabilir ve bu durumda result özelliği bu durumu gösterebilir ve yeniden yönlendirmeyi önleyebilir.


13

Zarif olmasa da, bazı durumlarda benim için çalışıyor.

Kontrolör

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

Modeli

    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>

2
Neden zarif değil? Kesinlikle yazılmış ve net hissettiriyor. Bu yaklaşımı beğendim. +1
T-moty

12

Üretmeye çalıştığınız davranış, AJAX kullanılarak gerçekten en iyi şekilde yapılmaz. AJAX, başka bir sayfaya tamamen yeniden yönlendirmek yerine sayfanın yalnızca bir bölümünü güncellemek istiyorsanız en iyi şekilde kullanılacaktır. Bu, AJAX'ın tüm amacını gerçekten bozar.

AJAX'ı tarif ettiğiniz davranışla kullanmamanızı öneririm.

Alternatif olarak, isteği gönderecek jquery Ajax kullanmayı deneyebilir ve ardından istek tamamlandığında bir geri arama belirtebilirsiniz. Geri aramada, başarısız olup olmadığını belirleyebilir ve başarılı olan başka bir sayfaya yönlendirebilirsiniz. Jquery Ajax'ı kullanmanın çok daha kolay olduğunu gördüm, özellikle de zaten kitaplığı zaten başka şeyler için kullandığım için.

Jquery ajax ile ilgili belgeleri burada bulabilirsiniz , ancak sözdizimi aşağıdaki gibidir:

jQuery.ajax( options )  

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

jQuery.getJSON( url, data, callback )

jQuery.getScript( url, callback )

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

Öyleyse, Sil eylemine normal bir POST yapın ve çoğu durumda başarılı olur ve ardından Ana Dizin sayfasına yeniden yönlendirebilirim. Başarısız olduğu durumlarda, hata mesajlarıyla ve kullanıcının gerçekleştirmesi için uygun eylemle farklı bir görünüm görüntüleyin. İyi ses?
Jeff Widmer

Evet, kulağa daha mantıklı geliyor.
Joseph

Joseph'in önerisine göre bunu bir Ajax gönderisinden normal bir POST'a dönüştürerek ilerledim. Bu aslında daha iyi sonuç verdi, çünkü bana silme onayı mesajlarını işlemem için daha temiz bir yol sağladı.
Jeff Widmer

6

Kullanmak JavaScriptkesinlikle işi yapacak.

ContentBu daha çok senin tarzınsa da kullanabilirsin .

Misal:

MVC Denetleyicisi

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

Javascript

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

Teşekkür ederim! Bu bana gerçekten yardımcı oldu.
dee

5

Aşağıdaki gibi Ajax Success'te yazabilirsiniz:

 $.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");
            }
});

2

Buna ne dersin :

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

Ve sonra

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

Veya

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

1

Ajax giriş formum olduğu için bunu yapmam gerekiyordu. Kullanıcılar başarılı bir şekilde oturum açtığında, yeni bir sayfaya yönlendiriyorum ve önceki isteği sonlandırıyorum çünkü diğer sayfa, bağlı tarafa geri yönlendirmeyi ele alıyor (çünkü bu bir STS SSO Sistemi).

Bununla birlikte, javascript devre dışı bırakılarak çalışmasını, merkezi oturum açma atlama noktası olmasını istedim, bu yüzden şunu buldum

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

    }

1

$ .AjaxSetup ile gelen yanıtlar için bir tür ajax yanıt filtresi yapabilirsiniz . Yanıt MVC yönlendirmesi içeriyorsa, bu ifadeyi JS tarafında değerlendirebilirsiniz. Aşağıdaki JS için örnek kod:

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

Veriler: "window.location = '/ Acount / Login'" ise yukarıdaki filtre bunu yakalar ve yeniden yönlendirme yapmayı değerlendirir.


0

Joseph'in en iyi cevabından memnun değilim, doğru sorunu çözmek yerine, bunun yanlış kullanım durumu olduğunu söyledi. Aslında birçok yer vardır, örneğin eski bir kod tabanını ajaksifiye koda dönüştürüyorsanız ve orada buna İHTİYACINIZ varsa, o zaman buna İHTİYACINIZ VAR. Programlamada mazeret yoktur, çünkü tüm kötü ve iyi geliştiricileri kodlayan sadece siz değilsiniz ve yan yana çalışmak zorundasınız. Yani ajax'ta yeniden yönlendirmeyi kodlamazsam, geliştirici arkadaşım beni bunun için bir çözüm bulmaya zorlayabilir. Tıpkı tüm AMD desenli siteleri veya mvc4 kullanmayı sevdiğim gibi ve şirketim beni bir yıl boyunca bundan uzak tutabilir.

Öyleyse şimdi çözüm hakkında konuşalım.

Ajax isteklerini ve yanıt işlemlerini çok iyi yaptım ve bulduğum en basit yol, istemciye durum kodları göndermek ve bu kodları anlamak için standart bir javascript işlevine sahip olmaktı. Örneğin, örnek kod 13'ü gönderirsem, bu bir yönlendirme anlamına gelebilir.

Yani {statusCode: 13, messsage: '/ home / logged-in'} gibi bir json yanıtı elbette {status: 'success', code: 13, url: '/ home / logged-in gibi önerilen tonlarca varyasyon var ', mesaj:' Şimdi giriş yaptınız '}

vb, bu nedenle kendi seçtiğiniz standart mesajlara kadar

Genellikle temel Controller sınıfından devralırım ve tercih ettiğim standart yanıtları buna benzer şekilde koyarım

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

Ajax.BeginForm'un $ .ajax intead'ini kullanma hakkında Jquery ajax'ı kullanmayı çok isterim ve kullanıyorum, ancak yine de karar vermek için tüm dünyada Ajax.BeginForm ile dolu bir uygulamam var ve tabii ki bunu yapmadım. Ama bununla yaşamak zorundayım.

Yani başlangıç ​​formunda da bir başarı geri araması var, geri aramaları kullanmak için jquery ajax kullanmanıza gerek yok. araması var,

Teşekkürler


0

JavaScript sınıfından yönlendirme yapıyorsanız

aynı görünüm - farklı denetleyici

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

aynı görüş değil

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

0

Bir yardımcı sınıf ekleyin:

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

Sonra harekete geçin:

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

Tüm ajax isteklerini engellemek için herhangi bir genel javascript içeren dosyaya veya düzen dosyasına javascript kodu ekleyin:

<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

Ben foster'ın dediği gibi Javascripts'i iade edebilirsiniz ve o sizi istenen sayfaya yönlendirecektir.

Sayfayı geçerli sayfaya yüklemek için:

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

Sayfayı yeni sekmeye yüklemek için:

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

0

Bu meta yenileme etiketlerinden birini yerleştirerek bir ajax çağrısından js tabanlı olmayan bir yeniden yönlendirme alabilirsiniz. Bu işe yarıyor gibi görünüyor: return Content("<meta http-equiv=\"refresh\" content=\"0;URL='" + @Url.Action("Index", "Home") + "'\" />");

Not: Meta yenilemelerin Firefox tarafından otomatik olarak devre dışı bırakıldığını keşfettim, bu da pek kullanışlı değil.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.