I am at a loose end as to how to add an attachment in my SOAP request. We have to consume a thrid party web service, built in java, which is the most convoluted thing I have
I'm 90% confident I'm working on the exact same project as you guys. That soap request is a little too familiar :-)
We've gotten most of the way there by switching over to WCF and basically hand-coding the request object (creating classes that match the soap format and then using xmlelement attributes to decorate it so that it looks like their soap request. The file itself is declared as a Byte() on the Attachment class and also decorated with the xmlelement).
Here's what the WCF contract and part of the data model look like. The actual data model has a bunch of extra classes (Application Area, Data Area, Job, etc) but this gives you enough of a sense of how it's structured. The important piece is the File as Byte(). Here it is in Vb.net...
Public Class WarrantyClaim
Public OEMClaimNumber As String = ""
Public Attachment As New Attachment
End Class
Public Class Attachment
Public File As Byte()
Public Filename As String
End Class
_
Public Interface IService
_
Sub ProcessMessage(ByVal payload As WarrantyClaim)
End Interface
Next you've got your WCF client, this is pretty much the same as all WCF clients.
Public Class GmgwClient
Inherits System.ServiceModel.ClientBase(Of IService)
Implements IService
Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal configName As String)
MyBase.New(configName)
End Sub
Public Sub New(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
MyBase.New(binding, remoteAddress)
End Sub
Public Sub ProcessMessage(ByVal payload As Payload) Implements IService.ProcessMessage
MyBase.Channel.ProcessMessage(payload)
End Sub
End Class
Finally you've got the app.config. Here's the magic because we're telling WCF to use Mtom to send the message. This will take the Byte() and strip it out into a seperate MIME section replacing it with an XOP:Include. Note that for now I'm just sending it through localhost so I can see the request using tcpTrace. You can google that app but it'll basically capture the request so we can see how it looks. I setup tcpTrace to listen on port 84.
Finally, here's the actual call to the WCF client to make the request.
Dim x As New WarrantyClaim
x.OEmClaimNumber = "12345"
x.Attachment = New Attachment
x.Attachment.Filename = "sample.gif"
x.Attachment.File = IO.File.ReadAllBytes("C:\sample.gif")
Dim y As New GmgwClient("preprod")
y.ProcessMessage(x)
And here's the trace we got through tcpTrace. It's got the basic structure right and it's managed to pull the binary data out of the xml and place it in a seperate MIME section.
POST /ProcessMessage HTTP/1.1
MIME-Version: 1.0
Content-Type: multipart/related; type="application/xop+xml";start="";boundary="uuid:501aa27d-9dd1-4f8a-b56d-3fbf327e7be6+id=1";start-info="application/soap+xml"
VsDebuggerCausalityData: uIDPoysDMCv023ZIjK0Cpp504ooAAAAA//jfaCaohkab2Zx/EU7gpLZDcUldWtlGr1j4ZnrfKl4ACQAA
Host: localhost:84
Content-Length: 55125
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
--uuid:501aa27d-9dd1-4f8a-b56d-3fbf327e7be6+id=1
Content-ID:
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml;charset=utf-8;type="application/soap+xml"
http://www.starstandards.org/webservices/2005/10/transport/operations/ProcessMessage/v1_01/ProcessAttachment
urn:uuid:a85374e6-c8ca-4328-ad32-6e8b88a5ca59
http://www.w3.org/2005/08/addressing/anonymous
http://localhost:84/ProcessMessage
12345
sample.gif
--uuid:501aa27d-9dd1-4f8a-b56d-3fbf327e7be6+id=1
Content-ID:
Content-Transfer-Encoding: binary
Content-Type: application/octet-stream
GIF89a
Like I mentioned earlier - we've still got some issues. There are some tags missing from the Soap Header... but I think we'll be able to figure those out. The real problem is that the Content-ID is NOT in a format our partner can accept - they expect something like <1.a33c2d7e84634122705ebc71e53d95d4c2683d726ba54e14@apache.org> and .net is formatting them as http://tempuri.org/1/634618782531246992. This is causing their Web Service handler to crash because it doesn't know how to read escaped content-id's inside the soap message.