A question popped up in a public compact framework newsgroup yesterday. The OP was feeding strings coming from a multiline text box to a web service for storing in the database. To his surprise when he retrieved the strings back (via the same web service) they would display small boxes in place of line breaks.
The symptom is consistent with having just LF (0xa) as a string break instead of required CRLF (0xd0xa) and yet when the data were sent to the web service the CRLFs were there. What happened? The investigation shows that on the web service side the strings are delievered without “CRs“
The answer hides in the SOAP protocol. If you have a web service that has a method Test, taking a single string parameter, the request is passed via HTTP POST request that looks like this:
POST /FormatSvc/svc.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/Test"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Test xmlns="http://tempuri.org/">
<s>string</s>
</Test>
</soap:Body>
</soap:Envelope>
The string there is the actual string parameter passed to the method. Naturally, if it contains CRLF inside, the XML parser is going to treat it as a whitespace, which is exactly what's happening. To get around this we need to force some sort of encoding on our parameters or tell XML to preserve whitespace. While there is probably a way of doing it, there seems to be a simpler workaround. A standard, run-of-the-mill web service written in ASP.NET supports several request methods - SOAP, SOAP 1.2, POST and GET. How to select the method to be used? The answer is - you need to use wsdl.exe to generate web service proxy for you.
wsdl.exe http://yourwebserver/yourservice /Protocol:HttpGet
produces yourservice.cs - a web service proxy, that can be placed into your project instead of the web reference. Since in GET request parameters are UrlEncoded, this will preserve the special characters and CRLFs
There is one small catch. By default ASP.NET 1.1 does not accept GET requests for web services. This can be changed in C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.config by uncommenting the line that says: <!--<add name="HttpGet"/>-->
This is not the best solution. A better one would be to use POST client. In my experiments for some reason wsdl.exe refused to produce anything when invoked with /Protocol:HttpPost. What I've done is I edited the .cs file produced for /Protocol:HttpGet replacing
System.Web.Services.Protocols.HttpGetClientProtocol
with
System.Web.Services.Protocols.HttpPostClientProtocol
in the class statement, and
[System.Web.Services.Protocols.HttpMethodAttribute(typeof(System.Web.Services.Protocols.XmlReturnReader), typeof(System.Web.Services.Protocols.UrlParameterWriter))]
with
[System.Web.Services.Protocols.HttpMethodAttribute(typeof(System.Web.Services.Protocols.XmlReturnReader), typeof(System.Web.Services.Protocols.HtmlFormParameterWriter))]
on each method.
WSDL.EXE can be found in .NET SDK usually located in <Visual Studio Directory>\Sdk\v1.1\Bin