Il ressemble à Tim Carter solution ne fonctionne pas si l'appel à la référence web lance une exception. J'ai essayé d'obtenir à la crue web resonse afin que je puisse l'examiner (dans le code) dans le gestionnaire d'erreur une fois que l'exception est levée. Cependant, je trouve que la réponse du journal écrit par Tim méthode est vide lors de l'appel déclenche une exception. Je ne comprends pas complètement le code, mais il semble que Tim méthode des coupes dans le processus après le point où .Net a déjà invalidé et mis au rebut de la réponse web.
Je suis en train de travailler avec un client qui est à l'élaboration d'un web service manuellement avec un faible niveau de codage. À ce moment, ils sont en ajoutant à leur propre processus interne messages d'erreur les messages au format HTML dans la réponse AVANT le SAVON réponse au format. Bien sûr, la automagique .Net web de référence souffle sur ce sujet. Si j'ai pu obtenir lors de la crue de la réponse HTTP, après une exception est levée, je pouvais regarder et analyser n'importe quel SAVON réponse dans le mixte de retour HTTP de la réponse et de savoir qu'ils ont reçu mes données sur OK ou pas.
Plus tard ...
Voici une solution qui ne fonctionne pas, même après une execption (notez que je suis seulement après la réponse pourrait obtenir de la demande):
namespace ChuckBevitt
{
class GetRawResponseSoapExtension : SoapExtension
{
//must override these three methods
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return null;
}
public override object GetInitializer(Type serviceType)
{
return null;
}
public override void Initialize(object initializer)
{
}
private bool IsResponse = false;
public override void ProcessMessage(SoapMessage message)
{
//Note that ProcessMessage gets called AFTER ChainStream.
//That's why I'm looking for AfterSerialize, rather than BeforeDeserialize
if (message.Stage == SoapMessageStage.AfterSerialize)
IsResponse = true;
else
IsResponse = false;
}
public override Stream ChainStream(Stream stream)
{
if (IsResponse)
{
StreamReader sr = new StreamReader(stream);
string response = sr.ReadToEnd();
sr.Close();
sr.Dispose();
File.WriteAllText(@"C:\test.txt", response);
byte[] ResponseBytes = Encoding.ASCII.GetBytes(response);
MemoryStream ms = new MemoryStream(ResponseBytes);
return ms;
}
else
return stream;
}
}
}
Voici comment le configurer dans le fichier de config:
<configuration>
...
<system.web>
<webServices>
<soapExtensionTypes>
<add type="ChuckBevitt.GetRawResponseSoapExtension, TestCallWebService"
priority="1" group="0" />
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
"TestCallWebService" devrait être remplacé par le nom de la bibliothèque (qui se trouvait être le nom de la console d'essai app je travaillais dans).
Vous ne devriez vraiment pas avoir à aller à l'ChainStream; vous devriez être en mesure de le faire plus simplement de ProcessMessage:
public override void ProcessMessage(SoapMessage message)
{
if (message.Stage == SoapMessageStage.BeforeDeserialize)
{
StreamReader sr = new StreamReader(message.Stream);
File.WriteAllText(@"C:\test.txt", sr.ReadToEnd());
message.Stream.Position = 0; //Will blow up 'cause type of stream ("ConnectStream") doesn't alow seek so can't reset position
}
}
Si vous recherchez SoapMessage.Cours d'eau, il est censé être une lecture seulement les flux que vous pouvez utiliser pour inspecter les données à ce point. C'est une vis en place parce que si vous le faites lire le flux, le traitement ultérieur des bombes avec pas de données disponibles erreurs (ruisseau était à la fin) et vous ne pouvez pas réinitialiser la position de début.
Fait intéressant, si vous faites les deux méthodes, la ChainStream et la ProcessMessage façons, la ProcessMessage méthode fonctionne parce que vous avez changé le type de flux de ConnectStream de MemoryStream dans ChainStream, et MemoryStream ne permettre les opérations de recherche. (J'ai essayé le casting du ConnectStream de MemoryStream - n'était pas le permettent.)
Donc ..... Microsoft devrait autoriser les opérations de recherche sur le ChainStream type ou faire de la SoapMessage.Stream vraiment une copie en lecture seule car il est censé être. (Écrire à votre député, etc...)
Un autre point. Après la création d'un moyen de récupérer les premières HTTP de la réponse après qu'une exception, je n'ai toujours pas la réponse complète (tel que déterminé par un HTTP sniffer). C'est parce que lorsque le développement de service web ajouté le code HTML des messages d'erreur au début de la réponse, il n'a pas d'ajuster le Contenu de l'en-tête de Longueur, de sorte que la Longueur du Contenu de valeur a été inférieure à la taille de la réponse réelle du corps. Tout ce que j'ai est la Longueur du Contenu de la valeur nombre de caractères - les autres ont été portées disparues. Évidemment, quand .Net lit le flux de réponse, il se contente de lire le Contenu de Longueur nombre de caractères et ne permet pas de la Longueur du Contenu de valeur éventuellement être trompé. C'est comme il devrait l'être; mais si le Contenu de l'en-tête de Longueur valeur est incorrecte, le seul moyen que vous aurez jamais obtenir l'ensemble du corps de la réponse est avec un HTTP sniffer (j'ai d'utilisateur HTTP Analyseur de http://www.ieinspector.com).