2009-05-13 9 views
1

Je ne sais pas où le problème est ...ASP.NET MVC + jQuery + IIS6: plusieurs requêtes Ajax

J'ai une demande de paiement ajax qui vérifie les informations de suivi pour un paquet sur une page avec une liste des emballages:

$(".fedex_status").each(function() { 

    var item = this; 

    // some code to construct tracking_url 

    $.ajax({ 
     type: "GET", 
     url: tracking_url, 
     async: true, 
     cache: false, 
     success: function(data) { $(item).html("(" + data + ")"); }, 
     error: function() { $(item).html("request failed...");} 
     }); 
}); 

donc, s'il y a 10 paquets sur la page (10 choses avec classe 'fedex_status') 10 demandes sont créées. Les demandes fonctionnent bien, mais les résultats sont renvoyés un à la fois (de manière sérielle). J'ai ajouté un horodatage au début et à l'arrêt d'une demande dans l'action du contrôleur:

public ActionResult Fedex(string trackingNumber) 
    { 
     DateTime requestStart = DateTime.Now; 

     TrackingService tracking = new TrackingService(); 

     string status = tracking.FedexTrackingNumberStatus(trackingNumber); 

     return Content(status + " - " + requestStart.ToString("hh:mm:ss.FFF") + " - " + DateTime.Now.ToString("hh:mm:ss.FFF")); 
    } 

Aucun des horodatages se chevauchent. Ainsi, le contrôleur traite les demandes une à la fois. Cela semble merdique.

Maintenant, la requête ajax 'devrait' être parallèle. Il revient définitivement immédiatement (son asynchrone). Lorsque je regarde les journaux IIS, les demandes ont le même horodatage que le retour d'action du contrôleur. Donc, ma question est la suivante: est-ce que jquery n'envoie pas toutes les requêtes ajax en parallèle ou est-ce que IIS ou ASP.NET traite uniquement les demandes en série. Je suis un grand noob avec IIS et les détails techniques d'ASP.NET, donc peut-être qu'il a été mal configuré pour toujours et ne répond qu'à une demande à la fois sur tout (son usage interne seulement, faible trafic). Cela dit, je suis aussi un idiot chez jquery et je ne sais pas comment tester quand les demandes sont en train d'être tirées (tout ce que je sais c'est que l'appel $ .ajax revient immédiatement).

Merci!

Répondre

4

En théorie, ASP.NET avec l'état de session activé verrouille la session pour chaque requête utilisateur, les traitant ainsi en série. Je ne pense pas que vous pouvez désactiver Session sans heurt pour un projet MVC, parce que TempData par exemple utilise la session par défaut. Mais tu peux essayer.

EDIT: voici une related question

+0

C'est malheureux. J'utilise des données temporaires dans d'autres endroits (des messages à l'utilisateur comme 'expédition créée!' Et de la merde comme ça) donc je ne peux pas m'en débarrasser. Ce contrôleur spécifique n'aura jamais besoin de TempData ou Session. Je me demande si la désactivation de TempData au niveau du contrôleur aidera ou si le fait que la session ne soit pas désactivée dans web.config l'emporte si le contrôleur l'utilise ou non. – anonymous

+0

Je pensais que c'était seulement vrai dans un sous-ensemble de circonstances (aspcompt = true vient à l'esprit). Je ne pense pas que la session, à elle seule, entraîne la sérialisation de toutes les demandes. –

+2

@Erv: Le peu de lecture que j'ai fait à ce sujet depuis cette réponse est que dans ASP.NET standard, vous pouvez spécifier le type de verrou que vous voulez sur la session par page. Par défaut je pense que c'est un verrou d'auteur et cela permet seulement 1 requête par page. Vous pouvez le changer pour un verrou de lecteur qui permettra à plusieurs lecteurs, mais bloque les écrivains, et bloquera sur un écrivain détenant le verrou. Je n'ai aucune idée de comment faire tout cela s'applique à ASP.NET MVC. J'aimerais juste dire «utiliser un verrou de lecteur partout» parce que j'utilise l'état de session pour rien de spécial. – anonymous

0

Vous appelez votre requête ajax chaque fois que vous trouvez un élément avec la classe .fedex_status.

Votre ligne

$ ("fedex_status"). Chaque

est dire le faire à chaque fois que vous trouvez un élément avec la .fedex_status de classe.

+0

Yup, c'est l'idée. Donc, si j'ai 10 correspondances pour fedex_status, je veux appeler 10 requêtes ajax en parallèle et retourner chacune de manière asynchrone. En ce moment, ils sont faits en série (pas vraiment de manière synchrone cependant ... les requêtes retournent immédiatement, donc elles sont asynchrones, mais les requêtes sont traitées en série). Je ne sais pas si son côté client ou côté serveur fait que les choses soient sérielles plutôt que parallèles. – anonymous

+0

La requête ne fonctionnera pas en parallèle car vous les appelez les uns après les autres! Je ne connais pas grand-chose à propos de JSON mais vous pouvez retourner l'information dans JSON dans une requête ajax puis faire une boucle dans le json et insérer les données dans le dom. Pas sûr juste une idée. –

+0

Donc, il ne peut y avoir qu'une seule requête ajax en vol à la fois? – anonymous

1

Votre code fonctionne comme prévu sur ma machine. J'ai dû insérer n'importe quel retard artificiel avec Thread.Sleep pour le voir en action cependant parce que les demandes simples ont exécuté si vite qu'il est apparu qu'elles étaient toutes accomplies immédiatement.

System.Threading.Thread.Sleep(1000); 

return Content(String.Format("Thread #{0}, Started = {1:hh:mm:ss.FFF}, Completed = {2:hh:mm:ss.FFF}, Duration = {3:hh:mm:ss.FFF}, Result = {4}", 
     System.Threading.Thread.CurrentThread.ManagedThreadId, 
     requestStart, 
     DateTime.Now, 
     DateTime.Now.Subtract(requestStart), 
     status)); 

Un test rapide sur ma machine en utilisant Firefox et la connexion au serveur intégré Web Visual Studio a montré que deux demandes ont été exécutées simultanément sur le client et gérées par deux threads différents sur le serveur. Pour autant que je sache, il existe un nombre limité de requêtes simultanées autorisées par le navigateur. Voici un autre article sur SO qui décrit ce que chaque valeur est pour chacun des navigateurs populaires: How many concurrent AJAX (XmlHttpRequest) requests are allowed in popular browsers?

EDIT: J'ai relu votre message et j'ai vu que vous avez mentionné IIS 6. Je n'ai pas accès à IIS 6, mais en cours d'exécution sur un serveur Web IIS 7 avec un délai d'attente artificiel de 5 secondes (Thread.Sleep) a montré que plusieurs demandes étaient traitées en même temps par différents threads de serveur. Aucun d'entre eux ne démarre à la même heure, donc il peut y avoir des files d'attente sur le serveur, mais avec un délai de 5 secondes, il est facile de voir que dans Firefox 3.0 j'ai au moins 6 requêtes simultanées à la fois.

+0

Je vais devoir jouer avec ça un peu plus. Le code d'action dans mon implémentation ASP.NET MVC est identique au code ASP.NET WebForms (autre que WebForms analysant la chaîne de requête). Autre que cela, la seule différence était le changement de session de désactivation dans WebForms. Je suis certain que j'obtiens de meilleures performances de WebForms que ASP.NET MVC en raison d'une sorte de verrouillage. Si vous obtenez 2 demandes simultanées de ASP.NET MVC, alors je dois creuser plus profondément. Merci! – anonymous

+0

Y at-il une raison pour laquelle vous ne voudriez pas faire une seule requête avec tous les numéros de suivi, puis analyser les données retournées et mettre à jour l'interface utilisateur au lieu de plusieurs appels? – GuyIncognito

+0

Quelques-uns, notamment que c'est plus facile. Mais même en ignorant cela, si j'ai envoyé une requête avec un tableau de numéros de suivi, je dois alors les faire en série au niveau du serveur ou être responsable de générer un tas de threads ou rendre mon service asynchrone. Pourquoi passer par ce tracas quand j'ai un http et un serveur web pour tout faire pour moi. Dans un cas général (pas pour les informations de suivi), je voudrais explorer quelque chose comme les widgets igoogle qui font tout leur chargement sur ajax. Donc, vous avez un portail à la maison, puis un tas d'appels ajax pour charger la page. – anonymous