J'écris un service Web (en utilisant ASP.NET MVC) et à des fins de support, nous aimerions pouvoir enregistrer les demandes et les réponses au plus près du format brut, sur le fil (c'est-à-dire avec HTTP méthode, chemin, tous les en-têtes et le corps) dans une base de données.
Ce dont je ne suis pas sûr, c'est de savoir comment obtenir ces données de la manière la moins «mutilée». Je peux reconstituer ce à quoi je pense que la demande ressemble en inspectant toutes les propriétés de l' HttpRequest
objet et en construisant une chaîne à partir d'elles (et de même pour la réponse) mais j'aimerais vraiment obtenir les données de demande / réponse réelles qui sont envoyé sur le fil.
Je suis heureux d'utiliser n'importe quel mécanisme d'interception tel que des filtres, des modules, etc. et la solution peut être spécifique à IIS7. Cependant, je préfère le garder en code géré uniquement.
Des recommandations?
Edit: Je note qu'il y HttpRequest
a une SaveAs
méthode qui peut enregistrer la demande sur le disque mais cela reconstruit la demande à partir de l'état interne en utilisant une charge de méthodes d'assistance internes qui ne sont pas accessibles publiquement (c'est pourquoi cela ne permet pas d'enregistrer sur un utilisateur fourni stream je ne sais pas). Il semble donc que je devrais faire de mon mieux pour reconstruire le texte de demande / réponse à partir des objets ... gémissement.
Edit 2: Veuillez noter que j'ai dit toute la demande, y compris la méthode, le chemin, les en-têtes, etc. Les réponses actuelles ne regardent que les flux de corps qui n'incluent pas ces informations.
Edit 3: Personne ne lit les questions ici? Cinq réponses à ce jour et pourtant aucune ne fait même allusion à un moyen d'obtenir toute la demande brute sur le fil. Oui, je sais que je peux capturer les flux de sortie et les en-têtes et l'URL et tout ce qui se passe à partir de l'objet de requête. Je l'ai déjà dit dans la question, voir:
Je peux reconstituer ce à quoi je pense que la demande ressemble en inspectant toutes les propriétés de l'objet HttpRequest et en construisant une chaîne à partir d'elles (et de même pour la réponse) mais j'aimerais vraiment obtenir les données de demande / réponse réelles qui est envoyé sur le fil.
Si vous savez que les données brutes complètes (y compris les en-têtes, l'url, la méthode http, etc.) ne peuvent tout simplement pas être récupérées, il serait utile de le savoir. De même, si vous savez comment tout obtenir au format brut (oui, je veux toujours dire y compris les en-têtes, l'url, la méthode http, etc.) sans avoir à le reconstruire, ce que j'ai demandé, alors ce serait très utile. Mais me dire que je peux le reconstruire à partir des HttpRequest
/ HttpResponse
objets n'est pas utile. Je le sais. Je l'ai déjà dit.
Remarque: avant que quiconque ne commence à dire que c'est une mauvaise idée, ou limitera l'évolutivité, etc., nous mettrons également en œuvre des mécanismes de limitation, de livraison séquentielle et d'anti-relecture dans un environnement distribué, de sorte que la journalisation de la base de données est de toute façon nécessaire. Je ne cherche pas à savoir si c'est une bonne idée, je cherche comment cela peut être fait.
la source
Réponses:
Utilisez définitivement
IHttpModule
et implémentez les événementsBeginRequest
etEndRequest
.Toutes les données "brutes" sont présentes entre
HttpRequest
etHttpResponse
, ce n'est tout simplement pas dans un seul format brut. Voici les parties nécessaires pour créer des vidages de style Fiddler (à peu près aussi proches du HTTP brut que possible):Pour la réponse:
Notez que vous ne pouvez pas lire le flux de réponse , vous devez donc ajouter un filtre au flux de sortie et capturer une copie.
Dans votre
BeginRequest
, vous devrez ajouter un filtre de réponse:Magasin
filter
où vous pouvez y accéder dans leEndRequest
gestionnaire. Je suggère dansHttpContext.Items
. Il peut alors obtenir les données de réponse complètesfilter.ReadStream()
.Ensuite, implémentez en
OutputFilterStream
utilisant le modèle Decorator comme wrapper autour d'un flux:la source
La méthode d'extension suivante sur HttpRequest créera une chaîne qui peut être collée dans Fiddler et rejouée.
la source
HttpRequestBaseExtensions
et de changerHttpRequest
pourHttpRequestBase
à chaque endroit.Vous pouvez utiliser la variable serveur ALL_RAW pour obtenir les en-têtes HTTP d'origine envoyés avec la requête, puis vous pouvez obtenir le InputStream comme d'habitude:
consultez: http://msdn.microsoft.com/en-us/library/ms524602%28VS.90%29.aspx
la source
HttpContext.Current.Request
pour récupérer le contexte actuel en dehors des contrôleurs MVC, des pages ASPX, etc ... assurez-vous simplement qu'il n'est pas nul en premier;)Eh bien, je travaille sur un projet et j'ai fait, peut-être pas trop profond, un journal en utilisant les paramètres de requête:
Regarde:
Vous pouvez décorer votre classe de contrôleurs pour la consigner entièrement:
ou enregistrez juste quelques méthodes d'action individuelles
la source
Avez-vous besoin de le conserver dans un code géré?
Il convient de mentionner que vous pouvez activer la journalisation des échecs de suivi dans IIS7 si vous n'aimez pas réinventer la roue. Cela enregistre les en-têtes, le corps de la requête et de la réponse ainsi que de nombreuses autres choses.
la source
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
à la fin deRegister(..)
inWebApiConfig.cs
, mais cela peut varier entre les versions.J'ai suivi l'approche de McKAMEY. Voici un module que j'ai écrit qui vous permettra de démarrer et, espérons-le, vous fera gagner du temps. Vous devrez évidemment brancher le Logger avec quelque chose qui fonctionne pour vous:
la source
Encoding.UTF8
, ou peutEncoding.Default
- être lors de la lecture du flux de demande? Ou utilisez simplement unStreamReader
( avec des mises en garde )OK, il semble donc que la réponse soit "non, vous ne pouvez pas obtenir les données brutes, vous devez reconstruire la requête / réponse à partir des propriétés des objets analysés". Eh bien, j'ai fait le truc de la reconstruction.
la source
utilisez un IHttpModule :
la source
si pour une utilisation occasionnelle, pour contourner un virage serré, que diriez-vous de quelque chose de brut comme ci-dessous?
la source
Vous pouvez accomplir cela dans un
DelegatingHandler
sans utiliser leOutputFilter
mentionné dans d'autres réponses dans .NET 4.5 à l'aide de laStream.CopyToAsync()
fonction.Je ne suis pas sûr des détails, mais cela ne déclenche pas toutes les mauvaises choses qui se produisent lorsque vous essayez de lire directement le flux de réponse.
Exemple:
la source
Je sais que ce n'est pas du code géré, mais je vais suggérer un filtre ISAPI. Cela fait quelques années que j'ai eu le "plaisir" de maintenir mon propre ISAPI mais d'après ce que je me souviens, vous pouvez avoir accès à tout cela, à la fois avant et après qu'ASP.Net l'ait fait.
http://msdn.microsoft.com/en-us/library/ms524610.aspx
Si un HTTPModule n'est pas assez bon pour ce dont vous avez besoin, alors je ne pense tout simplement pas qu'il existe un moyen géré de le faire avec la quantité de détails requise. Mais ça va être pénible à faire.
la source
Je suis d'accord avec les autres, utilisez un IHttpModule. Jetez un œil à la réponse à cette question, qui fait presque la même chose que vous demandez. Il enregistre la demande et la réponse, mais sans en-têtes.
Comment tracer les requêtes ScriptService WebService?
la source
Il peut être préférable de le faire en dehors de votre application. Vous pouvez configurer un proxy inverse pour faire des choses comme celle-ci (et bien plus encore). Un proxy inverse est essentiellement un serveur Web qui se trouve dans votre salle de serveurs et se situe entre vos serveurs Web et le client. Voir http://en.wikipedia.org/wiki/Reverse_proxy
la source
D'accord avec FigmentEngine,
IHttpModule
semble être la voie à suivre.Regardez dans
httpworkerrequest
,readentitybody
etGetPreloadedEntityBody
.Pour obtenir le,
httpworkerrequest
vous devez faire ceci:où
inApp
est l'objet httpapplication.la source
HttpRequest
etHttpResponse
avant MVC avait unGetInputStream()
etGetOutputStream()
qui pouvait être utilisé à cette fin. Je n'ai pas examiné ces éléments dans MVC, donc je ne suis pas sûr qu'ils soient disponibles mais cela pourrait être une idée :)la source