Balázs Varga
Balázs Varga

Reputation: 1856

Can't read data correctly with BinaryReader from WebRequest

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:[email protected]" 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: <[email protected]>

%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ãÙ­
...

Upvotes: 3

Views: 1546

Answers (2)

Gy&#246;rgy Kőszeg
Gy&#246;rgy Kőszeg

Reputation: 18013

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.

Upvotes: 2

Aleš Doganoc
Aleš Doganoc

Reputation: 12052

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();
   }
}


  

Upvotes: 2

Related Questions