2009-05-25 8 views
7

J'ai un service WCF hébergé dans IIS/ASP.NET qui accepte HTTP Post (ne forme pas le poste) d'objets sérialisés.Capture de données HTTP POST brutes pendant l'exception

Si le client envoie des requêtes mal formées (par exemple, il ne sérialise pas correctement l'objet), je souhaite enregistrer le message envoyé.

Nous utilisons déjà ELMAH pour capturer des exceptions non gérées, donc la simple association des données de publication serait l'option la plus simple.

Je peux obtenir le HttpContext courant pendant une exception, mais cela ne contient que les informations d'en-tête HTTP.

Ma question est la suivante: existe-t-il un moyen de capturer le corps de la requête HTTP POST d'origine? Ou, à défaut - une meilleure façon (sans un proxy inverse) de capturer l'entrée qui a causé l'erreur? Edit: Juste pour clarifier, l'exécution de la capture au niveau des paquets à tout moment n'est pas vraiment appropriée. Je suis après une solution que je peux déployer sur des serveurs de production, et qui aura des clients en dehors de notre contrôle ou de notre capacité à surveiller. Éditer # 2: Une suggestion a été faite pour accéder à Request.InputStream - ceci ne fonctionne pas si vous essayez de lire après que WCF ait lu la demande hors du flux.

Un exemple de code pour voir comment j'ai essayé d'utiliser ceci est ici.

 StringBuilder log = new StringBuilder(); 

     var request = HttpContext.Current.Request; 

     if (request.InputStream != null) 
     { 
      log.AppendLine(string.Format("request.InputStream.Position = \"{0}\"", request.InputStream.Position)); 
      if (request.InputStream.Position != 0) 
      { 
       request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
      } 

      using (StreamReader sr = new StreamReader(request.InputStream)) 
      { 
       log.AppendLine(string.Format("Original Input: \"{0}\"", sr.ReadToEnd())); 
      } 
     } 
     else 
     { 
      log.AppendLine("request.Inputstream = null"); 
     } 


     log.ToString(); 

Le ouput de log.ToString() est la suivante:

 
    request.InputStream.Position = "0" 
    Original Input: "" 
+1

Le "utilisant" avec StreamReader résultera dans le System.Web.Request.InputStream étant éliminé (ce qui signifie que les données sont perdues). – Jeff

+0

Les données sont déjà perdues. –

Répondre

3

Au moment où il arrive à votre service, la demande est traitée et n'est pas disponible pour vous.

Cependant ... vous pouvez joindre un message inspector. Les inspecteurs de message vous permettent de manipuler le message avant qu'il n'atteigne vos implémentations d'opération. Vous pouvez créer une copie du message et la copier dans OperationContext.Current.

Hack hain bien sûr, et cela signifiera une surcharge de mémoire car maintenant deux copies du message flottent pour chaque demande.

+0

Merci - ce n'est pas une solution particulièrement bonne, mais sacrifier de la mémoire en vaudra probablement la peine. –

-2

Utilisation violoniste. Gratuit de MS. Fonctionne très bien.

+1

Je parle d'erreurs qui se sont produites quand il n'y a pas de Fiddler, Wireshark, ou quoi que ce soit en cours d'exécution pour le capturer. par exemple sur un serveur de production ou de stockage intermédiaire où il n'est pas possible d'exécuter la capture de paquets tout le temps. –

-1

Avez-vous regardé la propriété System.Web.Request.InputStream? Il devrait avoir exactement ce que vous voulez. Comment "rembobiner" la propriété InputStream.

if (Request.InputStream.Position != 0) 
    { 
     Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
    } 

Une autre option que vous devriez regarder dans capture ces informations avec un HttpModule sur l'événement BeginRequest. Les données doivent être présentes à l'événement BeginRequest car je ne pense pas que WCF récupère la requête après PostAuthenticateEvent.

+1

J'ai regardé cette propriété - malheureusement ce flux ne contient que des données non lues. Au moment où l'exception s'est produite, les données d'entrée ont déjà été lues par WCF. Vous ne pouvez pas rembobiner/réinitialiser la position. –

+0

Voir ma mise à jour ... Depuis Request.InputStream.CanSeek est vrai, vous pouvez réinitialiser la position à 0 en utilisant la méthode Seek. – Jeff

+0

Merci pour la mise à jour - CanSeek est vrai, mais il n'y a toujours rien à lire dans le flux. Voir le texte mis à jour par exemple de ce que j'ai fait pour essayer et tester ceci. –

-1

sous ASP.NET (service Web ASP sous IIS) le code suivant aide:

if (request.InputStream.Position != 0) 
{ 
    request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
} 

WCF peut-être différent (qui est elle dispose InputStream après l'avoir lu)

+0

Ceci est la même réponse que Jeff a donné. Cela ne fonctionne pas non plus car le flux n'est pas disponible. –