I have made some SOAP code by using svcutil.exe on the wsdl file, and I wish to somehow dump/get the XML that the request contains. How do I do that?
Thank you in advance.
Edit: Oh I forgot: I use .Net 2008
Printable View
I have made some SOAP code by using svcutil.exe on the wsdl file, and I wish to somehow dump/get the XML that the request contains. How do I do that?
Thank you in advance.
Edit: Oh I forgot: I use .Net 2008
This is from the support of a 3the party webservice I'm using
In the method 'ProcessMessage(SoapMessage message)', the request is save into the Clipboard.Quote:
•Save the following code with the name "SqlSoapTracer.cs" in the same folder that contains the SOAP client project files.
•In the Solution Explorer window, perform the following steps:
◦Select the project by name, right-click and point to Add, and then select Add Existing Item.
◦In the Add Existing Item dialog box, browse and select the SqlSoapTracer.cs file from the location you saved it to in step 1.
◦Select Show All Files and expand the Web References node and select the Reference.cs file.
•In the Code Editor window, update the Reference.cs file by locating the entry points for your Web methods there. To add SOAP trace support when the Web methods execute in client code, add the following snoopattribute() call in the Reference.cs code directly before the entry point for each Web method you want to trace, as shown in the following lines of code.
Code:[System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:ContactService#login",
RequestNamespace="urn:ContactService", ResponseNamespace="urn:ContactService")]
[return: System.Xml.Serialization.SoapElementAttribute("token")]
[snoopattribute()]
public string login(string user, string pass, login_options login_options) {
object[] results = this.Invoke("login", new object[] {
user,
pass,
login_options});
return ((string)(results[0]));
}
This registers a SOAP extension that invokes the SOAP tracing of these Web methods when they are executed.
To make it more easy to read, you can add your own method to the class that writes the request to a file instead of the clipboard.
The new 'ProcessMessage(SoapMessage message)' looks then like the next
This will result in 2 files, 1 for the request and 1 for the request/responseCode:public override void ProcessMessage(SoapMessage message) {
SoapClientMessage client = (SoapClientMessage)message;
switch (client.Stage) {
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
try {
m_newStream.Position = 0;
StreamReader reader = new StreamReader(m_newStream);
m_info.request = FormatXml(reader.ReadToEnd());
m_newStream.Position = 0;
m_newStream.SetLength(0);
StreamWriter writer = new StreamWriter(m_newStream);
writer.Write(m_info.request);
writer.Flush();
Clipboard.SetDataObject(m_info.request + "\r\n", true);
SaveStream(m_info.request + "\r\n");
}
catch (Exception e) {
m_info.requestException = e;
}
m_newStream.Position = 0;
Copy(m_newStream, m_oldStream);
break;
case SoapMessageStage.BeforeDeserialize:
m_newStream.SetLength(0);
try {
Copy(m_oldStream, m_newStream);
m_newStream.Position = 0;
StreamReader reader = new StreamReader(m_newStream);
string tempData = reader.ReadToEnd();
m_info.response = FormatXml(tempData);
m_newStream.Position = 0;
m_newStream.SetLength(0);
StreamWriter writer = new StreamWriter(m_newStream);
writer.Write(tempData);
writer.Flush();
Clipboard.SetDataObject(m_info.request + "\r\n\r\n" + m_info.response + "\r\n", true);
SaveStream(m_info.request + "\r\n\r\n" + m_info.response + "\r\n");
}
catch (Exception e) {
m_info.responseException = e;
}
m_newStream.Position = 0;
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage");
}
}
private void SaveStream(string stream) {
DirectoryInfo dir = new DirectoryInfo(Path.Combine(Application.StartupPath, "SOAP debug\\"));
if (!dir.Exists)
dir.Create();
string tempFile = Path.Combine(Application.StartupPath, "SOAP debug\\" + DateTime.Now.ToString("MM-dd-yyyy hh.mm.ss"));
string fileName = tempFile + ".txt";
FileInfo fi = new FileInfo(fileName);
int i = 1;
while (fi.Exists) {
fileName = string.Format("{0} ({1}).txt", tempFile, i);
fi = new FileInfo(fileName);
i++;
}
StreamWriter SR = new StreamWriter(fileName);
SR.Write(stream);
SR.Flush();
SR.Close();
SR.Dispose();
}
Thank you. :)
Where exactly should I put the snoop function? Is it like this?
I don't know that much about SOAP in C#. I've only used it in C++ using GSOAP before (where debugging is much easier).Code:namespace Carl2_360_Integration.UpdatePerson {
using System.Runtime.Serialization;
using System;
.
.
.
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class UpdatePersonServiceClient : System.ServiceModel.ClientBase<Carl2_360_Integration.UpdatePerson.UpdatePersonService>, Carl2_360_Integration.UpdatePerson.UpdatePersonService {
public UpdatePersonServiceClient() {
}
......
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[snoopattribute()]
Carl2_360_Integration.UpdatePerson.UpdatePersonResponse Carl2_360_Integration.UpdatePerson.UpdatePersonService.UpdatePerson(Carl2_360_Integration.UpdatePerson.UpdatePersonRequest request) {
return base.Channel.UpdatePerson(request);
}
[snoopattribute()]
public void UpdatePerson(Carl2_360_Integration.UpdatePerson.CARL2Header CARL2SoapHeader, Carl2_360_Integration.UpdatePerson.PersonType Person) {
Carl2_360_Integration.UpdatePerson.UpdatePersonRequest inValue = new Carl2_360_Integration.UpdatePerson.UpdatePersonRequest();
inValue.CARL2SoapHeader = CARL2SoapHeader;
inValue.Person = Person;
Carl2_360_Integration.UpdatePerson.UpdatePersonResponse retVal = ((Carl2_360_Integration.UpdatePerson.UpdatePersonService)(this)).UpdatePerson(inValue);
}
.......
}
.
.
.
}
If it is correct you have something in the client code like next
Next, right-click 'getAll' -> 'Go to Definition'. Visual Studio will now automatically navigate to the Reference.cs file.Code:MyWebservice service = new MyWebserivce();
service.getAll();
In my example, the code in de reference file looks like
That is the place where the snoopattribute should be placedCode:/// <remarks/>
[System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:SectionService#getAll", RequestNamespace="urn:SectionService", ResponseNamespace="urn:SectionService")]
[return: System.Xml.Serialization.SoapElementAttribute("sections")]
public section[] getAll(string token, long entries_on_page, long page_num, out long total_count) {
object[] results = this.Invoke("getAll", new object[] {
token,
entries_on_page,
page_num});
total_count = ((long)(results[1]));
return ((section[])(results[0]));
}
Your file looks a bit different, but I guess you have it at the right place. Didn't give you any result then?Code:[return: System.Xml.Serialization.SoapElementAttribute("sections")]
[snoopattribute()]
public section[] getAll(string token, long entries_on_page, long page_num, out long total_count) {
Theres a neat little application I use for this. It's called soapUI, you can get it at http://soapui.org. It's in java so you'll need to install the framework if you haven't already. But this is by far some of the best software I've used when developing web services using soap. You give it the WSDL url and it does all the work for you. Shows you what it sends as a request (including the headers) gives you the xml for both versions of SOAP. Most importantly for me, it actually returns a friendly error when something is wrong. I love it, makes it easier to debug web services on production machines as well.
Thank you (both) for your time.
I have been able to get my XML out using Fiddler, but I would like to see if I could get the snooper class to work. That way I can tell the customer to run in debug mode if they get an error that I can't reproduce.
Sort of. I also have to call an Open() and Close() function.
No, alas, I don't get any result. But my file looks a lot different. For instance, I don't have things like the [return: .... ] statement.Quote:
Next, right-click 'getAll' -> 'Go to Definition'. Visual Studio will now automatically navigate to the Reference.cs file.
....
That is the place where the snoopattribute should be placed
Your file looks a bit different, but I guess you have it at the right place. Didn't give you any result then?Code:[return: System.Xml.Serialization.SoapElementAttribute("sections")]
[snoopattribute()]
public section[] getAll(string token, long entries_on_page, long page_num, out long total_count) {
Lars