Getting RAW Soap Data from a Web Reference Client running in ASP.net Getting RAW Soap Data from a Web Reference Client running in ASP.net asp.net asp.net

Getting RAW Soap Data from a Web Reference Client running in ASP.net


I made following changes in web.config to get the SOAP (Request/Response) Envelope. This will output all of the raw SOAP information to the file trace.log.

<system.diagnostics>  <trace autoflush="true"/>  <sources>    <source name="System.Net" maxdatasize="1024">      <listeners>        <add name="TraceFile"/>      </listeners>    </source>    <source name="System.Net.Sockets" maxdatasize="1024">      <listeners>        <add name="TraceFile"/>      </listeners>    </source>  </sources>  <sharedListeners>    <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener"      initializeData="trace.log"/>  </sharedListeners>  <switches>    <add name="System.Net" value="Verbose"/>    <add name="System.Net.Sockets" value="Verbose"/>  </switches></system.diagnostics>


You can implement a SoapExtension that logs the full request and response to a log file. You can then enable the SoapExtension in the web.config, which makes it easy to turn on/off for debugging purposes. Here is an example that I have found and modified for my own use, in my case the logging was done by log4net but you can replace the log methods with your own.

public class SoapLoggerExtension : SoapExtension{    private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);    private Stream oldStream;    private Stream newStream;    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)    {        return null;    }    public override object GetInitializer(Type serviceType)    {        return null;    }    public override void Initialize(object initializer)    {    }    public override System.IO.Stream ChainStream(System.IO.Stream stream)    {        oldStream = stream;        newStream = new MemoryStream();        return newStream;    }    public override void ProcessMessage(SoapMessage message)    {        switch (message.Stage)        {            case SoapMessageStage.BeforeSerialize:                break;            case SoapMessageStage.AfterSerialize:                Log(message, "AfterSerialize");                    CopyStream(newStream, oldStream);                    newStream.Position = 0;                break;                case SoapMessageStage.BeforeDeserialize:                    CopyStream(oldStream, newStream);                    Log(message, "BeforeDeserialize");                break;            case SoapMessageStage.AfterDeserialize:                break;        }    }    public void Log(SoapMessage message, string stage)    {        newStream.Position = 0;        string contents = (message is SoapServerMessage) ? "SoapRequest " : "SoapResponse ";        contents += stage + ";";        StreamReader reader = new StreamReader(newStream);        contents += reader.ReadToEnd();        newStream.Position = 0;        log.Debug(contents);    }    void ReturnStream()    {        CopyAndReverse(newStream, oldStream);    }    void ReceiveStream()    {        CopyAndReverse(newStream, oldStream);    }    public void ReverseIncomingStream()    {        ReverseStream(newStream);    }    public void ReverseOutgoingStream()    {        ReverseStream(newStream);    }    public void ReverseStream(Stream stream)    {        TextReader tr = new StreamReader(stream);        string str = tr.ReadToEnd();        char[] data = str.ToCharArray();        Array.Reverse(data);        string strReversed = new string(data);        TextWriter tw = new StreamWriter(stream);        stream.Position = 0;        tw.Write(strReversed);        tw.Flush();    }    void CopyAndReverse(Stream from, Stream to)    {        TextReader tr = new StreamReader(from);        TextWriter tw = new StreamWriter(to);        string str = tr.ReadToEnd();        char[] data = str.ToCharArray();        Array.Reverse(data);        string strReversed = new string(data);        tw.Write(strReversed);        tw.Flush();    }    private void CopyStream(Stream fromStream, Stream toStream)    {        try        {            StreamReader sr = new StreamReader(fromStream);            StreamWriter sw = new StreamWriter(toStream);            sw.WriteLine(sr.ReadToEnd());            sw.Flush();        }        catch (Exception ex)        {            string message = String.Format("CopyStream failed because: {0}", ex.Message);            log.Error(message, ex);        }    }}[AttributeUsage(AttributeTargets.Method)]public class SoapLoggerExtensionAttribute : SoapExtensionAttribute{    private int priority = 1;     public override int Priority    {        get { return priority; }        set { priority = value; }    }    public override System.Type ExtensionType    {        get { return typeof (SoapLoggerExtension); }    }}

You then add the following section to your web.config where YourNamespace and YourAssembly point to the class and assembly of your SoapExtension:

<webServices>  <soapExtensionTypes>    <add type="YourNamespace.SoapLoggerExtension, YourAssembly"        priority="1" group="0" />  </soapExtensionTypes></webServices>


Not sure why all the fuss with web.config or a serializer class. The below code worked for me:

XmlSerializer xmlSerializer = new XmlSerializer(myEnvelope.GetType());using (StringWriter textWriter = new StringWriter()){    xmlSerializer.Serialize(textWriter, myEnvelope);    return textWriter.ToString();}