2011-03-31 4 views
28

Esto realmente me tiene rascándome la cabeza. A saber, porque solo ocurre en IE, no en Firefox, y tenía la impresión de que jQuery era efectivamente neutral para el navegador. Me he estado quejando de esto durante las últimas horas y he descubierto, al menos, lo que está sucediendo.jQuery AJAX produciendo 304 respuestas cuando no debería

Este jqGrid:

$("#DocumentListByPartRecordsGrid").jqGrid(
      { 
      datatype: 'local',    
      colNames: ['<b>Id</b>', '<b>Document Name</b>', '<b>Document Type</b>', '<b>Effective Date</b>', '<b>Expiration Date</b>', '<b>Delete</b>'], 
      colModel: [ 
        { name: 'ASSOCIATION_ID', Index: 'ASSOCIATION_ID', resizable: true, align: 'left', hidden: true, sortable: false }, 
        { name: 'FILE_NAME', Index: 'FILE_NAME', resizable: true, align: 'left', sortable: false, width:'20%' }, 
        { name: 'DOCUMENT_TYPE', Index: 'DOCUMENT_TYPE', resizable: true, align: 'left', sortable: false, width:'20%' }, 
        { name: 'EFFECTIVE_DATE', Index: 'EFFECTIVE_DATE', resizable: true, align: 'left', sortable: false, width:'20%' }, 
        { name: 'EXPIRATION_DATE', Index: 'EXPIRATION_DATE', resizable: true, align: 'left', sortable: false, width:'20%' }, 
        { name: 'Delete', Index: 'Delete',resizable: true, align: 'center', sortable: false, width:'20%' }, 
        ],    
      rowNum: 15, 
      rowList: [15, 50, 100], 
      imgpath: '/Drm/Content/jqGrid/steel/images', 
      viewrecords: true,    
      height: 162,   
      loadui: 'block', 
      forceFit: true 
     }); 

Llenado por esta función:

var mydata = '';  
<% if(!string.IsNullOrEmpty(Model.PCAssociatedDocuments)) { %>   
    var mydata = <%= Model.PCAssociatedDocuments %>; 
<% } %> 

for (var i = 0; i <= mydata.length; i++){ 
     jQuery("#DocumentListByPartRecordsGrid").addRowData(i, mydata[i], "last"); 
     } 

que está poblada limpiamente del modelo. Este no es el problema. El problema surge cuando se utiliza la funcionalidad de eliminación, que se formatea de nuevo en el controlador de este modo:

<a class='deleteAttachment' style='cursor: pointer;' href='#' onclick='javascript:PCDocumentDelete(" + s.AssociationId.ToString() + ", " + pcId + ");'>Delete</a> 

y llama a esta función

function PCDocumentDelete(id, pcid) { 
if (confirm("Are you sure you want to delete this document?")) { 
    $.blockUI({ 
     message: "Working...", 
     css: { 
      background: '#e7f2f7', 
      padding: 10 
     } 
    }); 
    $.ajax(
     { 
      url: '/DRM/Pc/DeleteAssociation?associationId=' + id + '&pcid=' + pcid, 
      async: true, 
      dataType: "json", 
      success: function(result) { 
       if (result.Success == true) { 
        //Reload grid      
        $.ajax({ async: false }); 
        $("#DocumentListByPartRecordsGrid").setGridParam({ url: "/Drm/Pc/DeAssociatePartRecordsWithDocument?pcid=" + pcid, datatype: 'json', myType: 'GET', page: 1 }); 
        $("#DocumentListByPartRecordsGrid").trigger("reloadGrid"); 
        $.unblockUI(); 
        $.showGlobalMessage('Specified document has been successfully disassociated from this part record.'); 
       } 
       else { 
        $.unblockUI(); 
        $.showGlobalMessage('An error occurred deleting the attachment.'); 
       } 
      }, 
      error: function(res, stat) { 
       alert(res.toString()); 
       alert(stat.toString()); 
      } 
     }); 
    return false; 
} 
else { 
    return false; 
} 

}

(showGlobalMessage es una función interna que crea un blockUI particularmente formateado)

El ajax llama a un método de nuevo en el controlador, pero el problema surge antes de que lleguemos tan lejos, entonces a menos que eone piensa que es importante, no voy a publicar ese código. Lo que ocurre es que, a menudo por razones inexplicables, el primer estallido de ajax que llama PC/DeleteAssociation vuelve con una respuesta 304 (no modificada). Sé que sucede en un get cuando nada ha cambiado y necesita ser actualizado. Pero esto no es un get, debe tratarse como una publicación, y tenía la impresión de que jquery.ajax estaba diseñado para, a menos que se indique lo contrario, no generar 304 respuestas. Obviamente me falta algo aquí y he estado mirando demasiado tiempo para atraparlo. ¿Alguien ve lo que me perdí? Gracias.

Respuesta

43

No puedo ver, especificando la solicitud de AJAX como POST. Así que, básicamente añadir:

$.ajax({ type: 'POST' }); 

y si éste tampoco funciona (debido a algún navegador AJAX rareza), podría intentar establecer cache: false:

$.ajax({ type: 'POST', cache: false }); 

Por cierto, todas caché: falsa hace, está añadiendo un poco al azar cosas a la URL de solicitud.

EDIT1:

En cuanto a la

... y yo tenía la impresión de que jquery.ajax fue diseñado para, a menos que se indique lo contrario , no generará 304 respuestas

jQuery no está generando ninguna respuesta aquí. Y el encabezado 304 es solo un encabezado HTTP. Las solicitudes HTTP AJAX son solicitudes HTTP normales y pueden devolver cualquier encabezado válido. Si el servidor responde con 304, el objeto XHR simplemente servirá la respuesta en caché local del servidor. Sin embargo, es completamente transparente para el usuario.

Edit2:

ha eliminado el asesoramiento sobre la prevención de almacenamiento en caché. Me parece vudú.

Edit3:

añadió que mordió de nuevo, ya que al parecer era necesario. Al mirar alrededor de la web, IE parece estar guardando ilegalmente en caché los POST de AJAX hasta cierto punto.

+1

Sí. @guildsbounty, si quieres que una llamada Ajax sea tratada como POST, tendrás que decirlo explícitamente; jQuery.ajax está predeterminado en GET. Se parece un poco a que el método que está llamando espera un GET, sin embargo, dado que está pasando sus parámetros de URL, aunque parece ser una operación de eliminación, lo que parece un poco extraño ... –

+1

extrañamente, el el vudú fue lo que funcionó al final. Incluso la publicación generaba un 304. Utilicé la prevención de almacenamiento en caché y lo arreglé ... gracias por la ayuda. – guildsbounty

+0

@guildsbounty:: d extraño. Miré un poco y IE parece tener problemas allí. Lo edité de nuevo. ¡Gracias por los comentarios! – skarmats

20
  1. Utilice siempre POST para llamadas a métodos que modifican el estado, no el GET. Esto debería ser suficiente en esta instancia para evitar que IE almacene en caché la solicitud.
  2. IE cachea agresivamente las solicitudes ajax (ver http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ y https://blog.httpwatch.com/2009/08/07/ajax-caching-two-important-facts/). Para evitar esto, puede:
    1. Agregar un parámetro de prevención de memoria caché ($.ajaxSetup({ cache: false }); hace esto automáticamente.
    2. Siempre use solicitudes POST (probablemente no apropiadas en la mayoría de los casos).
    3. Activar los encabezados de caché para las solicitudes AJAX del lado del servidor. El primer enlace demuestra cómo hacer esto usando groovy. Se deben aplicar métodos similares a cualquier marco.
+0

Al establecer el parámetro global ajax se corrigió el mismo problema cuando se usaba el método $ .load(). – lhoess

+3

* Active los encabezados de caché para las solicitudes AJAX del lado del servidor * - 'Cache-Control: no-cache' o' Expires: -1' para los perezosos como yo. – ulidtko

0

de almacenamiento en caché es la solución!

En mi caso, la aplicación usaba una sola llamada de servicio con un encabezado personalizado como proxy para vincular el navegador a la parte privada del servidor (cada llamada iba a la misma url, pero usaba un encabezado personalizado para indicar al proxy servicio que servicio para pasarlo). Todo funcionó bien en Chrome y FF, pero IE siguió devolviendo datos de la primera llamada realizada en la página. La opción cache = false en jQuery.ajax era la solución, ya que IE solo miraba la misma URL que se llamaba, ni siquiera se molestaba en ver si se usaban encabezados personalizados, o si se estaban pasando datos diferentes en el cuerpo, y solo dijo "oh, sé esto, aquí ..." y devolvió la respuesta de la primera llamada. Con la técnica de prevención de almacenamiento en memoria caché, la URL se ve diferente a la de IE, por lo que se envió a través de ella.

+0

HTTP Cache-Control resolvería su problema también. – ulidtko

Cuestiones relacionadas