3

Hy!

I'm developing a C# SOAP service to communicate with one of our governmental services. They also use SOAP for communication, but now they introduced two new endpoints that handle requests very differenty. The first thing that I noticed is that when I called $SoapClient->Request(...) from the PHP code of the client app, it failed with the error Looks like we got no XML document. The only way to get the actual response is to try-catch the SoapFault and then call$response = $SoapClient->__getLastResponse() to read it. It was indeed not an xml, but a binary format, kind of like the source of E-mail attachments.

After I figured it out, and downloaded the PDF file, it was still malformed. First I think that PHP is messing up something, but then I looked at the logs of the WebService and it was already malformed. I tried many different encodings with StreamReader, with no luck. Then I changed it to BinaryReader for that two endpoints. It's now way closer to the response I'm looking for, but still, there are seemingly random garbage characters included, like shown on this screenshot:

The left side is what I'm looking for, and the right is what I got. enter image description here

My code:

string soapResult;
try
{
    using (HttpWebResponse webResponse = (HttpWebResponse)httpRequest.EndGetResponse(asyncResult))
    {
        if (request == "edoc/getDocument" || request == "edoc/downloadFile")
        {
            using (BinaryReader rd = new BinaryReader(webResponse.GetResponseStream()))
            {
                soapResult = Encoding.Default.GetString(rd.ReadBytes(10000000));
            }
        }
        else
        {
            using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
            {
                soapResult = rd.ReadToEnd();
            }
        }
    }
}
...

How can I overcome this? I'm struggling for days now, but can't figure out what's wrong...

EDIT: The actual response looks exactly like this:

--MIME_Boundary
Content-ID: <c907fb5b-7aa7-4556-88fd-5074f43aafbb>
Content-Type: application/xop+xml; type="text/xml"; charset=UTF-8
Content-Transfer-Encoding: 8bit

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><env:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:Timestamp wsu:Id="Timestamp-JAuOpC673QOitIDD7tlAuA22" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsu:Created>2021-08-19T12:00:14Z</wsu:Created><wsu:Expires>2021-08-19T12:05:14Z</wsu:Expires></wsu:Timestamp></wsse:Security></env:Header><env:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><ns10:getDocument xmlns="http://eeszt.gov.hu/ns/common/ws/messageHeaderTypes/v3" xmlns:ns2="http://eeszt.gov.hu/ns/common/cdm/v3" xmlns:ns3="http://eeszt.gov.hu/ns/common/ws/messageTypes/v3" xmlns:ns4="http://eeszt.gov.hu/ns/eDoc/ws/eDocService/v1" xmlns:ns5="http://eeszt.gov.hu/ns/eDoc/ws/eDocService/messages/v1" xmlns:ns6="http://eeszt.gov.hu/ns/eDoc/ws/eDocService/Request/v1" xmlns:ns7="http://eeszt.gov.hu/ns/documentrenderer/ws/common/messages/v1" xmlns:ns8="http://eeszt.gov.hu/ns/common/ws/queryTypes/v3" xmlns:ns9="http://eeszt.gov.hu/ns/common/ws/errorTypes/v3" xmlns:ns10="http://eeszt.gov.hu/ns/eDoc/ws/eDocService/Response/v1" xmlns:ns11="http://eeszt.gov.hu/ns/common/ws/versionInfoTypes/v3" xmlns:ns12="http://eeszt.gov.hu/ns/documentrenderer/ws/DocumentRendererService"><ns10:getDocumentResponse><ns3:businessMessageHeader><initiator><userId>O60547</userId><userName>Dr. Psyklon</userName><clientUserId>O60547</clientUserId><applicationId>DokiRex.NET:v1.57</applicationId><applicationName>DokiRex.NET</applicationName><applicationFunction>edoc_get_document</applicationFunction><organizationId>E200158</organizationId><organizationName>Asd</organizationName><organizationUnitId>002001581</organizationUnitId><organizationUnitName>Eeszt Dev</organizationUnitName></initiator><representedUser><userId>O60547</userId><userName>Orvos 1 DEV69</userName><clientUserId>O60547</clientUserId></representedUser><initiatorCitizen><ns2:citizenIDs><ns2:citizenID><ns2:type>1</ns2:type><ns2:id>900200018</ns2:id></ns2:citizenID></ns2:citizenIDs></initiatorCitizen><representedCitizen><ns2:citizenIDs><ns2:citizenID><ns2:type>1</ns2:type><ns2:id>900200018</ns2:id></ns2:citizenID></ns2:citizenIDs></representedCitizen><logging><submittedAt>2021-08-19T14:00:14.156+02:00</submittedAt><EESZTLogging><receivedAt>2021-08-19T14:00:14.147+02:00</receivedAt><processedAt>2021-08-19T14:00:14.234+02:00</processedAt><EESZTtransactionId>0aa47ec3-ad01-4a37-b75b-121c2f645a1c</EESZTtransactionId></EESZTLogging></logging></ns3:businessMessageHeader><ns3:status>OK</ns3:status><ns5:businessMessageContent><ns5:eDoc><ns4:id>11953</ns4:id><ns4:docType>ack</ns4:docType><ns4:docTypeName>Kézbesítés igazolás</ns4:docTypeName><ns4:docNev>Kézbesítés igazolás</ns4:docNev><ns4:docStatusz>REND</ns4:docStatusz><ns4:docStatuszName>Renderelt</ns4:docStatuszName><ns4:docFeltoltoIntezmeny>E200006</ns4:docFeltoltoIntezmeny><ns4:docFeltoltoSzervezetiEgyseg>002000061</ns4:docFeltoltoSzervezetiEgyseg><ns4:docFeltoltoUser>O60017</ns4:docFeltoltoUser><ns4:docFelelosUser>O60017</ns4:docFelelosUser><ns4:allampolgar><ns2:type>1</ns2:type><ns2:id>900200018</ns2:id></ns4:allampolgar><ns4:feltoltesIdeje>2021-06-23T19:12:52.308+02:00</ns4:feltoltesIdeje><ns4:tarolasiIdo>2021-10-01T19:12:52.000+02:00</ns4:tarolasiIdo><ns4:forrasDocId>11952</ns4:forrasDocId><ns4:parentDocId>11952</ns4:parentDocId><ns4:attachments><ns4:attachmentResponse><ns4:id>29625</ns4:id><ns4:name>kezbesitesi_jelentes.pdf</ns4:name><ns4:mimeType>application/pdf</ns4:mimeType><ns4:file><inc:Include href="cid:5bed3685-037d-438e-a306-b96d1c1ac435-1158030@eeszt.gov.hu" xmlns:inc="http://www.w3.org/2004/08/xop/include"/></ns4:file></ns4:attachmentResponse></ns4:attachments><ns4:recipients/><ns4:linkedDocuments/></ns5:eDoc></ns5:businessMessageContent></ns10:getDocumentResponse></ns10:getDocument></env:Body></soapenv:Envelope>
--MIME_Boundary
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <5bed3685-037d-438e-a306-b96d1c1ac435-1158030@eeszt.gov.hu>

%PDF-1.4
%ª«¬­
1 0 obj
<<
/Creator (Apache FOP Version 2.3)
/Producer (Apache FOP Version 2.3)
/CreationDate (D:20210623191252+02'00')
>>
endobj
2 0 obj
<<
  /N 3
  /Length 3 0 R
  /Filter /FlateDecode
>>
stream
xœí™gPTY€ï{
ÝM“¡ÉI¢„$ç$A²¨@w“i¡ÉAQdpFIŠ ¢€ŽAFQÅ€(( ¢N#ƒ€2Ž"**KãÙ­
...
Balázs Varga
  • 1,797
  • 2
  • 16
  • 32
  • 3
    `Encoding.Default` is really suspicious. Do you know what encoding is used by the downstream system? I mean does the SOAP response define the encoding? – Peter Csala Aug 26 '21 at 14:47
  • 2
    I tried almost all of them (Unicode, UTF8, UTF7, ASCII) but those all look even worse. – Balázs Varga Aug 27 '21 at 04:29
  • ASCII just placed squares in the place of symbols/control characters, Unicode replaced the entire file with chinese characters, UTF7 caused an error that there is an ivalid sequence, and UTF8 seems like is the same as Default. – Balázs Varga Aug 27 '21 at 05:58
  • Does the response contain something like this: ``? – Peter Csala Aug 27 '21 at 06:30
  • 2
    No beacuse it's not an XML. It contains multiple files separated with a ```--MIME_Boundary```. The following headers are for the PDF I'm interested in: ```--MIME_Boundary``` ```Content-Type: application/octet-stream``` ```Content-Transfer-Encoding: binary``` – Balázs Varga Aug 27 '21 at 08:20
  • See my edit for the actual response format. It indeed contains `````` but this is another file. I'm only interested in the PDF which comes after. – Balázs Varga Aug 27 '21 at 08:26
  • 4
    Maybe you need to use the MultipartMemoryStreamProvider. [See this thread](https://stackoverflow.com/a/49493210/2599508) – John Aug 30 '21 at 08:22
  • 2
    Could you write the raw response to a file? Then you may be able to use a HEX-editor to compare the files and see the difference. – PEK Sep 02 '21 at 19:21

2 Answers2

2

You are getting a multipart response so you need to parse it to get the parts. I will provide a sample a solution using the Microsoft.AspNet.WebApi.Client NuGet package that includes extension methods for easier processing of such content. Since you use the old now obsolete HttpWebRequest you need first to transform the stream you get to a HttpContent object and then you can get a MultipartMemoryStreamProvider object from it using the extension method ReadAsMultipartAsync. This object has an array of contents so you can read each of the parts.

Here is your code changed to read the PDF part as string.

string soapResult;
using (HttpWebResponse webResponse = (HttpWebResponse)httpRequest.EndGetResponse(asyncResult))
{
   StreamContent streamContent = new StreamContent(webResponse.GetResponseStream());
   streamContent.Headers.Add("Content-Type", webResponse.ContentType);

   MultipartMemoryStreamProvider? multipart = await streamContent.ReadAsMultipartAsync();

   soapResult = await multipart.Contents[1].ReadAsStringAsync(); // read second content that has index 1
}

I would suggest you change your code to use the newer HttpClient to do web requests and then this code becomes even more simple.

string soapResult;
using (HttpClient httpClient = new HttpClient()) // For best performance you should create one HttpClinet for all the application and reuse it for all calls not create new for each call.
{
   using (HttpResponseMessage? httpResponseMessage = await httpClient.GetAsync("https://localhost:5001/api/multipart"))
   {
      MultipartMemoryStreamProvider? multipart = await httpResponseMessage.Content.ReadAsMultipartAsync();

      soapResult = await multipart.Contents[1].ReadAsStringAsync();
   }
}


  
Aleš Doganoc
  • 11,568
  • 24
  • 40
  • Thanks, your solution pointed me to the right direction. I only changed ```ReadAsStringAsync()``` to ```ReadAsByteArrayAsync()``` and wrapped it in ```Convert.ToBase64String```, so now I'm able to get a valid XML response on the other end, and just display the pdf with ```base64_decode```. – Balázs Varga Sep 06 '21 at 08:16
2

Do not read binary content as string via any Encoding. A raw PDF content is not conform to any encoding so your string result will be corrupt for sure.

If you need to return a binary content as text in your SOAP message, then use base64 encoding instead:

// binary content: as base64
if (webResponse.ContentType == "application/octet-stream")
    soapResult = Convert.ToBase64String(br.ReadBytes((int)webResponse.ContentLength));

And the receiver of your SOAP message can restore the original binary content by Convert.FromBase64String.

György Kőszeg
  • 17,093
  • 6
  • 37
  • 65