Adding an attachment to SOAP request

后端 未结 6 2004
旧巷少年郎
旧巷少年郎 2020-12-28 23:36

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

6条回答
  •  太阳男子
    2020-12-29 00:09

    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.

提交回复
热议问题