In our project we offer a web service to our customers and to simplify the use of the web service we have implemented web service clients as examples in different frameworks. So we have the usual suspects for Java (JAX-WS, Apache CXF and Axis).
I was asked if I’m interested in program a web service client for the .Net framework. I had already some little experience with C# and ASP.Net and so I thought it would be nice to see what .Net has to offer.
So first the goal was to implement a web service client for a contract first document / literal / wrapped web service which is WS-I Attachments Profile conform.
The big problem is that .Net does not support SwA (SOAP Messages with Attachments). There are three approaches which could work for you when you have the same problem.
- Use the open source library PocketSOAP
- Use the commercial library from Alotsoft.com
- Create your own web service stub
In this post I will show you how you could send a SOAP request manually, receive the SOAP response and parse the MIME attachments with the open source library SharpMimeTools.
So keep in mind that I’m a Java developer and not a C# developer. I also wrote these pieces of code only to show that there is also a simple way to receive a SOAP response with MIME attachments when your were forced to write a web service stub manually in C#.
Data contract
So first we create our Data contract with the xsd.exe. After that we can serialize or deserialize XML with the System.Xml.XMLSerializer from the .Net framework. You will find a reference to a XSD schema in your WSDL file from your web service for which you want to create a web service client.
Xsd.exe data_contract.xsd /c /o:c:\out
Send SOAP request
With System.Net.HttpWebRequest you can send a SOAP request manually to your endpoint. We serialize our XML with the XMLSerializer and add the SOAP Envelope, SOAP Header and SOAP Body.
The followng example show how you could use the XMLSerializer and the HttpWebRequest to create a SOAP request and send it to a web service endpoint.
FileStream fs = new FileStream(“C:\data.xml”, FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(MyData));
MyData myData = (MyData) serializerReq.Deserialize(fs);
XmlWriterSettings writerSettings = new XmlWriterSettings();
writerSettings.OmitXmlDeclaration = true;
StringWriter stringWriter = new StringWriter();
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter,
writerSettings))
{
serializerReq.Serialize(xmlWriter, myData);
}
string xmlText = stringWriter.ToString();
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.ContentType = @"text/xml;charset=""utf-8""";
req.Accept = "text.xml";
req.Method = "POST";
// create soap message (with SOAP Header, Body and Envelope)
String msg = START_MSG + xmlText + END_MSG;
byte[] reqBytes = System.Text.Encoding.UTF8.GetBytes(msg);
req.ContentLength = reqBytes.Length;
Stream reqStream = req.GetRequestStream();
// send soap request
reqStream.Write(reqBytes, 0, reqBytes.Length); reqStream.Close();
reqStream.Close();
Receive SOAP response
We will use the SharpMimeTools to parse MIME attachments. So for that we have to make our response stream MIME multipart conform.
The example show how you can create a stream which can be parsed from the SharpMimeTool library. You have to copy the HTTP headers Date, Content-Type, Content-Length and the content of the HttpWebReponse stream to a memory stream. The new memeory stream can then be parsed by the SharpMimeTool library.
HttpWebResponse res = …;
MemoryStream httpStream = …;
MemoryStream mimeStream = …;
Encoding utf8 = Encoding.UTF8;
TextReader readerReq = new StreamReader(httpStream, utf8);
TextWriter writer = new StreamWriter(mimeStream, utf8);
// create a correct mime stream form the HttpResponseStream
// add http headers which were required for a correct mime
// format
writer.WriteLine("Date: " + res.GetResponseHeader("Date"));
writer.WriteLine("Content-Type: " + res.ContentType);
writer.WriteLine("Content-Length: " + res.ContentLength);
writer.WriteLine(Environment.NewLine);
// copy rest of the stream
while (true)
{
string line = readerReq.ReadLine();
if (line == null)
{
break;
}
writer.WriteLine(line);
}
writer.Flush();
mimeStream.Position = 0;
// parse the stream for mime attachments
SharpMessage message = new SharpMessage(mimeStream,
SharpDecodeOptions.Default | SharpDecodeOptions.DecodeTnef |
SharpDecodeOptions.UuDecode);
Parse MIME attachments from the SOAP response
With the SharpMessage from the SharpMimeTools we can access the SOAP response and also the MIME attachments.
SharpMessage message = …;
if (message.Attachments != null)
{
foreach (attachment in message.Attachments)
{
Stream stream = attachment.Stream;
…
}
Finally…
To access the soap payload you could retrieve it with XPath and then deserialize it with the XMLSerializer.
… I hope this post and line of codes gave you a hint how you could parse a SOAP response with MIME attachments manually in C#.
SharpMimeTools is changing the encoding of the binary attachments I’m receiving, rendering them useless.
Right now I’m trying to manually split the byte stream without converting to string and see how that goes.
Thanks a lot for your article, it still helped a lot!