Pertanyaan Bagaimana mengelola permintaan pengalihan setelah panggilan Ajax jQuery


saya menggunakan $.post() untuk memanggil servlet menggunakan Ajax dan kemudian menggunakan fragmen HTML yang dihasilkan untuk menggantikan div elemen di halaman saat pengguna. Namun, jika waktu sesi habis, server mengirimkan arahan pengalihan untuk mengirim pengguna ke halaman login. Dalam hal ini, jQuery mengganti div elemen dengan isi halaman login, memaksa mata pengguna untuk menyaksikan adegan langka memang.

Bagaimana saya bisa mengelola arahan arahan dari panggilan Ajax dengan jQuery 1.2.6?


1181
2017-10-13 21:29


asal


Jawaban:


Saya membaca pertanyaan ini dan menerapkan pendekatan yang telah disebutkan mengenai pengaturan kode status respons ke 278 untuk menghindari browser yang secara transparan menangani pengalihan. Meskipun ini berhasil, saya sedikit tidak puas karena ini sedikit meretas.

Setelah lebih banyak menggali, saya membuang pendekatan ini dan menggunakannya JSON. Dalam hal ini, semua tanggapan terhadap permintaan ajax memiliki kode status 200 dan isi respons berisi objek JSON yang dibuat di server. Javascript pada klien kemudian dapat menggunakan objek JSON untuk memutuskan apa yang perlu dilakukan.

Saya punya masalah yang sama dengan Anda. Saya melakukan permintaan ajax yang memiliki 2 kemungkinan respons: yang mengarahkan browser ke halaman baru dan yang menggantikan bentuk HTML yang ada di halaman saat ini dengan yang baru. Kode jquery untuk melakukan ini terlihat seperti ini:

$.ajax({
    type: "POST",
    url: reqUrl,
    data: reqBody,
    dataType: "json",
    success: function(data, textStatus) {
        if (data.redirect) {
            // data.redirect contains the string URL to redirect to
            window.location.href = data.redirect;
        }
        else {
            // data.form contains the HTML for the replacement form
            $("#myform").replaceWith(data.form);
        }
    }
});

Objek JSON "data" dibangun di server untuk memiliki 2 anggota: data.redirect dan data.form. Saya menemukan pendekatan ini jauh lebih baik.


631
2017-10-07 22:54



Saya memecahkan masalah ini dengan:

  1. Menambahkan tajuk khusus ke tanggapan:

    public ActionResult Index(){
        if (!HttpContext.User.Identity.IsAuthenticated)
        {
            HttpContext.Response.AddHeader("REQUIRES_AUTH","1");
        }
        return View();
    }
    
  2. Mengikat fungsi JavaScript ke ajaxSuccess acara dan memeriksa untuk melihat apakah ada header:

    $(document).ajaxSuccess(function(event, request, settings) {
        if (request.getResponseHeader('REQUIRES_AUTH') === '1') {
           window.location = '/';
        }
    });
    

213
2017-11-20 08:39



Tidak ada browser yang menangani respons 301 dan 302 dengan benar. Dan pada kenyataannya standar bahkan mengatakan mereka harus menangani mereka "transparan" yang merupakan sakit kepala MASSIVE untuk vendor Perpustakaan Ajax. Di Ra-Ajax kami dipaksa menggunakan kode status respons HTTP 278 (hanya beberapa "kode sukses" yang tidak digunakan) untuk menangani pengalihan transparan dari server ...

Ini benar-benar mengganggu saya, dan jika seseorang di sini memiliki beberapa "tarikan" di W3C, saya akan menghargai bahwa Anda dapat membiarkan W3C tahu bahwa kita benar-benar harus menangani kode 301 dan 302 sendiri ...! ;)


106
2018-01-27 18:10



Solusi yang akhirnya diimplementasikan adalah menggunakan pembungkus untuk fungsi callback panggilan Ajax dan dalam pembungkus ini memeriksa keberadaan elemen tertentu pada potongan HTML yang dikembalikan. Jika elemen ditemukan maka pembungkus mengeksekusi redirection. Jika tidak, pembungkus meneruskan panggilan ke fungsi panggilan balik yang sebenarnya.

Sebagai contoh, fungsi wrapper kami adalah sesuatu seperti:

function cbWrapper(data, funct){
    if($("#myForm", data).length > 0)
        top.location.href="login.htm";//redirection
    else
        funct(data);
}

Kemudian, ketika membuat panggilan Ajax kami menggunakan sesuatu seperti:

$.post("myAjaxHandler", 
       {
        param1: foo,
        param2: bar
       },
       function(data){
           cbWrapper(data, myActualCB);
       }, 
       "html"
);

Ini berhasil bagi kami karena semua panggilan Ajax selalu mengembalikan HTML di dalam elemen DIV yang kami gunakan untuk mengganti bagian halaman. Juga, kami hanya perlu mengarahkan ulang ke halaman login.


85
2017-08-23 19:21



Saya suka metode Timmerz dengan sedikit sentuhan lemon. Jika kamu pernah kembali Jenis konten dari teks / html ketika kamu mengharapkan JSON, Anda kemungkinan besar akan diarahkan. Dalam kasus saya, saya hanya cukup memuat ulang halaman, dan itu dialihkan ke halaman login. Oh, dan periksa bahwa status jqXHR adalah 200, yang tampak konyol, karena Anda berada dalam fungsi kesalahan, bukan? Jika tidak, kasus kesalahan yang sah akan memaksa pemuatan berulang (oops)

$.ajax(
   error:  function (jqXHR, timeout, message) {
    var contentType = jqXHR.getResponseHeader("Content-Type");
    if (jqXHR.status === 200 && contentType.toLowerCase().indexOf("text/html") >= 0) {
        // assume that our login has expired - reload our current page
        window.location.reload();
    }

});

57
2017-10-13 21:54



Gunakan tingkat rendah $.ajax() panggilan:

$.ajax({
  url: "/yourservlet",
  data: { },
  complete: function(xmlHttp) {
    // xmlHttp is a XMLHttpRquest object
    alert(xmlHttp.status);
  }
});

Coba ini untuk pengarahan ulang:

if (xmlHttp.code != 200) {
  top.location.href = '/some/other/page';
}

44
2018-05-23 10:02



Saya hanya ingin berbagi pendekatan saya karena ini mungkin dapat membantu seseorang:

Saya pada dasarnya termasuk modul JavaScript yang menangani hal-hal otentikasi seperti menampilkan nama pengguna dan juga menangani kasus ini redirect ke halaman login.

Skenario saya: Kami pada dasarnya memiliki server ISA di antara yang mendengarkan semua permintaan dan merespons dengan 302 dan tajuk lokasi ke halaman login kami.

Dalam modul JavaScript saya pendekatan awal sesuatu seperti itu

$(document).ajaxComplete(function(e, xhr, settings){
    if(xhr.status === 302){
        //check for location header and redirect...
    }
});

Masalahnya (karena banyak di sini sudah disebutkan) adalah bahwa browser menangani redirect dengan sendirinya karena itu saya ajaxComplete callback tidak pernah dipanggil, tetapi saya mendapat respons dari halaman Login yang telah dialihkan yang jelas adalah sebuah status 200. Masalahnya: bagaimana Anda mendeteksi apakah tanggapan 200 yang berhasil adalah halaman login Anda yang sebenarnya atau hanya beberapa halaman lain yang sewenang-wenang ??

Solusinya

Karena saya tidak dapat menangkap tanggapan pengalihan 302, saya menambahkan a LoginPage tajuk pada halaman login saya yang berisi url dari halaman login itu sendiri. Dalam modul saya sekarang mendengarkan header dan melakukan redirect:

if(xhr.status === 200){
    var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage");
    if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){
        window.location.replace(loginPageRedirectHeader);
    }
}

... dan itu bekerja seperti pesona :). Anda mungkin bertanya-tanya mengapa saya memasukkan url di LoginPage tajuk ... pada dasarnya karena saya tidak menemukan cara untuk menentukan url GET yang dihasilkan dari pengalihan lokasi otomatis dari xhr obyek...


31
2018-05-06 23:55



Saya tahu topik ini sudah tua, tapi saya akan memberikan pendekatan lain yang saya temukan dan dijelaskan sebelumnya sini. Pada dasarnya saya menggunakan ASP.MVC dengan WIF (tapi ini tidak terlalu penting untuk konteks topik ini - jawabannya memadai tidak peduli yang digunakan kerangka kerja. Petunjuk tetap tidak berubah - berurusan dengan masalah yang terkait dengan kegagalan otentikasi saat melakukan permintaan ajax).

Pendekatan yang ditunjukkan di bawah ini dapat diterapkan untuk semua permintaan ajax di luar kotak (jika mereka tidak mendefinisikan ulang sebelum mengirim acara jelas).

$.ajaxSetup({
    beforeSend: checkPulse,
    error: function (XMLHttpRequest, textStatus, errorThrown) {
        document.open();
        document.write(XMLHttpRequest.responseText);
        document.close();
    }
});

Sebelum permintaan ajax dilakukan CheckPulse metode dipanggil (metode pengontrol yang dapat berupa apa pun yang paling sederhana):

[Authorize]
public virtual void CheckPulse() {}

Jika pengguna tidak diautentikasi (token telah kadaluwarsa) metode tersebut tidak dapat diakses (dilindungi oleh Authorize atribut). Karena kerangka kerja menangani autentikasi, sementara token berakhir, ia menempatkan status http 302 ke respons. Jika Anda tidak ingin browser Anda menangani tanggapan 302 secara transparan, tangkap di Global.asax dan ubah status respons - misalnya menjadi 200 OK. Selain itu, tambahkan tajuk, yang menginstruksikan Anda untuk memproses respons tersebut dengan cara khusus (nanti di sisi klien):

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302
        && (new HttpContextWrapper(Context)).Request.IsAjaxRequest())
    {                
        Context.Response.StatusCode = 200;
        Context.Response.AddHeader("REQUIRES_AUTH", "1");
    }
}

Akhirnya di sisi klien, periksa header khusus tersebut. Jika ada - redirection penuh ke halaman log masuk harus dilakukan (dalam kasus saya window.location diganti dengan url dari permintaan yang ditangani secara otomatis oleh kerangka saya).

function checkPulse(XMLHttpRequest) {
    var location = window.location.href;
    $.ajax({
        url: "/Controller/CheckPulse",
        type: 'GET',
        async: false,
        beforeSend: null,
        success:
            function (result, textStatus, xhr) {
                if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') {
                    XMLHttpRequest.abort(); // terminate further ajax execution
                    window.location = location;
                }
            }
    });
}

26
2017-10-23 16:27