Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding an attachment to SOAP request

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 ever come across. Any other web services we have used, that required attachments, have a method or property to add the attachment. Simple. However, this one provides no such method.

We have got a version of the SOAP message together that is exactly as we want the XML, however it is the MIME part of the file that we cannot add.

Example:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<soap:Header>
<payloadManifest xmlns="http://<examplePayload>">
<manifest contentID="Content0" namespaceURI="http://<exampleManifest>" element="ProcessRepairOrder" version="2.01" />
</payloadManifest>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2011-12-19T15:25:13Z</wsu:Created>
<wsu:Expires>2011-12-19T15:30:00Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken><wsse:Username>username</wsse:Username><wsse:Password>password</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body><ProcessMessage xmlns="<examplePayload"><payload><content id="Content0">

<s:ProcessRepairOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://example.xsd" xmlns:s="http://<exampleManifest>" xmlns:gwm="http://example">
    <s:ApplicationArea>
        <s:Sender>
            <s:Component>Test</s:Component>
            <s:Task>ProcessAttachment</s:Task>
            <s:CreatorNameCode>Test</s:CreatorNameCode>
            <s:SenderNameCode>XX</s:SenderNameCode>
            <s:DealerNumber>111111</s:DealerNumber>
            <s:DealerCountry>GB</s:DealerCountry>
        </s:Sender>
        <s:CreationDateTime>2010-03-26T13:37:05Z</s:CreationDateTime>
        <s:Destination>
            <s:DestinationNameCode>GM</s:DestinationNameCode>
            <s:DestinationURI/>
            <s:DestinationSoftwareCode>GWM</s:DestinationSoftwareCode>
        </s:Destination>
    </s:ApplicationArea>
    <s:DataArea xsi:type="gwm:DataAreaExtended">
        <s:Process/>
        <s:RepairOrder>
            <s:Header xsi:type="gwm:RepairOrderHeaderExtended">
                <s:DocumentId/>
            </s:Header>
            <s:Job xsi:type="gwm:JobExtended">
                <s:JobNumber/>
                <s:OperationId>Test</s:OperationId>
                <s:OperationName/>
                <s:CodesAndComments/>
                <s:Diagnostics/>
                <s:WarrantyClaim xsi:type="gwm:WarrantyClaimExtended">
                    <s:OEMClaimNumber>00112233445566778899</s:OEMClaimNumber>
                    <gwm:Attachment>
                        <gwm:File><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:test.gif"/></gwm:File>
                        <gwm:Filename>test.gif</gwm:Filename>
                    </gwm:Attachment>
                </s:WarrantyClaim>
                <s:LaborActualHours>0.0</s:LaborActualHours>
                <s:Technician/>
            </s:Job>
        </s:RepairOrder>
    </s:DataArea>
</s:ProcessRepairOrder>
</content></payload></ProcessMessage></soap:Body></soap:Envelope>

This is the XML part that we can generate and send off, however it is incorrect as we need a MIME part in there like:

Before XML:

--MIMEBoundary
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <rootpart>

After XML

--MIMEBoundary
Content-Type: image/gif; name=test.gif
Content-Transfer-Encoding: binary
Content-ID: <test.gif>
GIF89a@�

--MIMEBoundary--

I have scoured the internet for answers but have come up blank. There doesn't seem to be much documentation around using WSE for this. I must stress that WSE is a requirement on the server side, and there is no way I can change the technology to address this issue.

Is there a way that these MIME sections can be added?

EDIT: I must add that I can get a working XML document sent through SoapUI with attachments, but cannot seem to find a way within our code.

I have added a bounty to try and get a solution to this problem. If anyone has any other ideas please let me know.

EDIT again: I know it has been a week since I was able to check the responses here, but while some give a good idea where to look I am still drawing a blank. The terrible documentation surrounding XopDocument and its methods is a big sticking point, if anyone has any examples of using SaveToXopPackage could they please provide because this is beginning to grate!

like image 844
anothershrubery Avatar asked Dec 20 '11 11:12

anothershrubery


People also ask

Can you send attachment in SOAP request?

You can send and receive SOAP messages that include binary data (such as PDF files or JPEG images) as attachments. Attachments can be referenced (that is, represented explicitly as message parts in the service interface) or unreferenced (in which arbitrary numbers and types of attachments can be included).


2 Answers

I was facing the same problem and the final solution I found was through HttpWebRequest. A sample code:

    public string ProcessAttachment(string fileInput)
    {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Settings.Default.GWM_WS_WebReference_GWM);
        req.Headers.Add("SOAPAction", "\"http://www.starstandards.org/webservices/2005/10/transport/operations/ProcessMessage/v1_01/ProcessAttachment\"");
        req.Headers.Add("Accept-Encoding", "gzip,deflate");
        req.ContentType = "multipart/related; type=\"application/xop+xml\"; start=\"<[email protected]>\"; start-info=\"text/xml\"; boundary=\"----=_Part_14_1350106.1324254402199\"";
        req.Method = "POST";
        req.UserAgent = "Jakarta Commons-HttpClient/3.1";
        req.Headers.Add("MIME-Version", "1.0");
        System.Net.ServicePointManager.Expect100Continue = false;
        Stream memStream = new System.IO.MemoryStream();
        FileStream fileStream = new FileStream(fileInput, FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[1024];
        int bytesRead = 0;
        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
        {
            memStream.Write(buffer, 0, bytesRead);
        }
        fileStream.Close();
        Stream stm = req.GetRequestStream();
        memStream.Position = 0;
        byte[] tempBuffer = new byte[memStream.Length];
        memStream.Read(tempBuffer, 0, tempBuffer.Length);
        memStream.Close();
        stm.Write(tempBuffer, 0, tempBuffer.Length);
        stm.Close();
        HttpWebResponse resp = null;
        resp = (HttpWebResponse)req.GetResponse();
        stm = resp.GetResponseStream();
        StreamReader r = new StreamReader(stm);
        return r.ReadToEnd();            
    }

The parameter fileInput is the absolute path of the file that contains the SOAP Request containing also the raw binary data of the file to be attached at the end separated with MIME Boundary

like image 102
ktsiolis gmail com Avatar answered Sep 28 '22 00:09

ktsiolis gmail com


I think that you may have a couple of options:

1) Use MTOM. This appears to automatically wrap the outgoing message in MIME blocks.

2) Microsoft actually provides support for generating and reading XOP with mime through the XopDocument class, which is what SoapEnvelope inherits from.

The save method is SaveToXopPackage and the read method is LoadFromXopPackage.

However, I think that this approach may require you to perform the sending of the message yourself through an HttpWebRequest. This blog has an example of how to implement this. The downside is that this requires a lot of extra code and configuration in order to work correctly.

The ideal solution would be to intercept the code that performs the envelope transmission, but I have been unable to locate the correct location for this in the pipeline.

like image 42
competent_tech Avatar answered Sep 27 '22 23:09

competent_tech