web-dev-qa-db-fra.com

jquery AJAX produisant 304 réponses quand il ne devrait pas

Cela m'a vraiment gratté ma tête. À savoir parce que cela ne se produit que dans IE, pas Firefox, et j'avais l'impression que JQuery était effectivement neutre du navigateur. J'ai craqué cette chose depuis quelques heures et j'ai cloué au moins, au moins ce qui se passe.

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

Rempli par cette fonction:

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

Qui est propre à proximité du modèle. Ce n'est pas le problème. La question se pose lors de l'utilisation de la fonctionnalité Supprimer, qui est formatée dans le contrôleur, comme:

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

et appelle cette fonction

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 est une fonction interne qui crée un blocui de particulièrement formaté)

L'AJAX appelle une méthode de retour dans le contrôleur, mais le problème se pose avant de le faire si loin, alors à moins que quelqu'un ne le pense important, je ne vais pas poster ce code. Ce qui se passe, c'est souvent pour des raisons inexplicables, la première rafale d'Ajax qui appelle PC/deleteAssociation revient avec une réponse de 304 (non modifiée). Je sais que cela se produit sur un get quand rien n'a changé cela doit être rafraîchi. Mais ce n'est pas un get, il devrait être traité comme un post et j'avais l'impression que Jquery.ajax a été conçue pour, sauf indication contraire, ne pas générer 304 réponses. Je manque évidemment quelque chose ici et je l'ai regardé beaucoup trop longtemps pour l'attraper moi-même. Quelqu'un vois ce que j'ai manqué? Merci.

28
guildsbounty

Je ne peux pas voir, vous spécifiez la demande Ajax en poste. Donc fondamentalement ajouter:

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

et si cela échoue toujours (en raison d'un navigateur AJAX bizarre), vous pouvez essayer de définir cache: false:

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

BTW, TOUT CACHE: FAUX fait, ajoute des éléments aléatoires à l'URL de la demande.

Edit1:

En ce qui concerne la

... et j'avais l'impression que Jquery.ajax a été conçue pour, sauf indication contraire, ne pas générer 304 réponses

jQuery n'est pas générer de réponses ici. Et l'en-tête 304 est juste un en-tête HTTP. Http AJAX Demandes sont des demandes HTTP ordinaires et peuvent renvoyer n'importe quel en-tête valide. Si le serveur répond avec 304, l'objet XHR servira simplement la réponse mise en cache locale du serveur. C'est complètement transparent pour le utilisateur, cependant.

EDIT2:

Supprimé les conseils sur la prévention de la mise en cache. Semble être vaudou pour moi.

Edit3:

Ajouté ce peu de temps parce qu'il était apparemment nécessaire. En regardant autour du Web, IE semble être illégalement en cache AJAX publier dans une certaine mesure.

44
skarmats
  1. Toujours utiliser POST pour les appels aux méthodes qui modifient l'état, pas. Cela devrait être suffisant dans ce cas pour empêcher la mise en cache IE la demande.
  2. Caches de manière agressive Demandes Ajax (voir http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ et https://blog.httpwatch.com/2009/08/07/ajax-caching-two-important-Facts/ )). Pour éviter cela, vous pouvez:
    1. Ajouter un paramètre de buse cache ($.ajaxSetup({ cache: false }); Est-ce que cela est automatiquement.
    2. Toujours utiliser POST demandes (probablement non appropriées dans la plupart des cas).
    3. Allumez les en-têtes de cache pour AJAX Demandes Server Server. Le premier lien démontre comment faire cela en utilisant à Groovy. Des méthodes similaires doivent s'appliquer à n'importe quel cadre.
21
Joshka

Cache Busting est la solution!

Dans mon cas, l'application a utilisé un appel de service unique avec un en-tête personnalisé en tant que proxy pour combler le navigateur de la partie privée du serveur (chaque appel est allé à la même URL, mais a utilisé un en-tête personnalisé pour indiquer au service proxy que le service de service passer sur). Tout a fonctionné bien sur Chrome _ et ff mais IE _ conservé les données de retour du premier appel effectué sur la page. cache = false option dans jquery.ajax était la solution depuis IE _ Il suffit de regarder la même URL appelée, n'a même pas pris la peine de regarder si des en-têtes personnalisés étaient utilisés ou si des données différentes étaient même passées. Dans le corps, et vient de dire "Oh, je connais celui-ci, ici .." et rendu la réponse du premier appel. Avec la technique de bêtise de cache, l'URL a l'air différent de IE donc il l'a envoyé.

1
Ali