1

I've .NET webservice, which takes a encoded html-string as a parameter, decodes the string and creates a PDF from the html. I want to make a synchronous server side call to the webservice from a classic asp webpage. It works fine if use a plain text string (with no html tags), but when I send a encoded html string the webservice it seems that the string is empty when it reaches the webservice.

The webservice is working fine when I call it from client side, with both plain text string and an encoded html string.

My code looks like this:

Private Sub SaveBookHtmlToPdf(pHtml, pShopId) 
    Set oXMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.6.0")        
    Dim strEnvelope
    strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Server.HTMLEncode(pHtml)
    Call oXMLHTTP.Open("POST", "https://mydomain.dk:4430/PdfWebservice.asmx/SaveBookToPdf", false)
    Call oXMLHTTP.SetRequestHeader("Content-Type","application/x-www-form-urlencoded")
    Call oXMLHTTP.Send(strEnvelope)
    Set oXMLHTTP = Nothing
End Sub

It smells like some kind of security issue on the server. It's working when posting a asynchronous call from the client side, but not when it comes from server side - it seems that the encoded html string is somehow not allowed in a server side call to the webservice.

Anyone who know how to solve this tricky problem?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • 2
    Using [fiddler](http://www.fiddler2.com/fiddler2/) can you find out what are you really sending and what is the web service message? – balexandre Jan 04 '12 at 08:41
  • The call to the web service is done server side, so unfortunately I can't use Fiddler. I've tried to print the data sent to the webservice, to the screen and it all looks like it should, but somehow it seems that the parameter with the encoded html string is empty, when it arrives at the web service. – Steffen Jørgensen Jan 04 '12 at 15:57
  • @Steffen: What version of IIS are you using? Do you have a test server or development machine that you can install Fiddler on? – AnthonyWJones Jan 04 '12 at 16:35
  • @AnthonyWJones I'm using IIS7, but unfortunately I do not have access to a test-server where I'm allowed to install Fiddler on. – Steffen Jørgensen Jan 05 '12 at 08:13
  • @Steffen: Can you at least run the ASP site on you local development machine? – AnthonyWJones Jan 05 '12 at 11:20

3 Answers3

1

This looks all wrong to me:

 Server.HTMLEncode(pHtml)

Its quite common for developers to get confused between HTML encoding and URL encoding even though they are quite different. You are posting data that needs to be URL encoded. Hence your code should use URLEncode instead:

 strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Server.URLEncode(pHtml)

Edit:

One thing that URLEncode does that may not be compatible with a URLEncoded post is it converts space to "+" instead of "%20". Hence a more robust approach might be:

 strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Replace(Server.URLEncode(pHtml), "+", "%20")

Another issue to watch out for is that the current value of Response.CodePage will influence how the URLEncode encodes non-ASCII characters. Typically .NET does things by default in UTF-8. Hence you will also want to make sure that your Response.CodePage is set to 65001.

 Response.CodePage = 65001
 strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Replace(Server.URLEncode(pHtml), "+", "%20")
AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • I'm HtmlEncoding the string before posting it and HtmlDecoding again it when recieved at the webservice. I can't se how that should be the problem? I've tried UrlEncoding instead and it still doesn't work. – Steffen Jørgensen Jan 04 '12 at 15:48
  • @SteffenJørgensen: The purpose of HTMLEncoding is to allow text content that may happen to contain characters that are meaningful to a HTML Parser to be escaped, such as < to < and & to &. However you are posting to a server that isn't about to parse the content with a HTML parser so HTMLEncode isn't useful. OTH you are posting text content that may contain characters such space, = and & that need escaping in a manner consistent with __URLEncoding__ (note the value of the Content_Type header you are setting). URL escape sequences have the form %xx. Hence `URLEncode` is required. – AnthonyWJones Jan 04 '12 at 16:03
  • After fidling around with it, I finally got it to work, by using URLEncode instead of HTMLEncode. Thanks to everyone for helping med out. – Steffen Jørgensen Jan 05 '12 at 14:04
0

AnthonyWJones made the point about URL encoding and HTML encoding, and the original problem being experienced is likely a combine of the two, a race condition if you will. While is was considered answered, it partially wasn't, and hopefully this answers the cause of the effect.

So, as the message get HTMLEncoded, the html entities for the tags become such '<' = '&lt;'.

And as you may know, in URLEncoding, &'s delimit parameters; thus the first part of this data strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Server.HTMLEncode(pHtml) upto the "&pEncodedHtml" bit, is fine. But then "<HTML>..." is added as the message, with unencoded &'s...and the receiving server likely is delimiting on them and basically truncating "&pEncodedHtml=" as a null assign: "&pEncodedHtml=&lt;HTML&gt;... ." The delimiting would be done on all &'s found in the URL.

So, as far as the server is concerned, the data for parameter &pEncodedHtml was null, and following it were now several other parameters that were considered cruft, that it likely ignored, which just happened to actually be your message.

Hope this provides additional info on issues of its like, and how to correct.

Darkstrumn
  • 193
  • 1
  • 5
0

This may or may not help but I use a handy SOAP Class for Classic ASP which solved a few problems I was having doing it manually. Your code would be something like this:

Set cSOAP = new SOAP
cSOAP.SOAP_StartRequest "https://mydomain.dk:4430/PdfWebservice.asmx", "", "SaveBookToPdf"
cSOAP.SOAP_AddParameter "pShopId", pShopId
cSOAP.SOAP_AddParameter "pEncodedHtml", Server.HTMLEncode(pHtml)
cSOAP.SOAP_SendRequest
' result = cSOAP.SOAP_GetResult("result")

You will probably need to set your namespace for it to work ("" currently), and uncomment the 'on error resume next' lines from the class to show errors.

akiller
  • 2,462
  • 22
  • 30
  • I've tried to use the code from CashFlow.com to generate the SOAP envelope, but I can't seem to get it to work. I don't get an error and because it is a server side call, it's very hard to debug. Any ideas of what could be wrong? – Steffen Jørgensen Jan 04 '12 at 15:45
  • Did you remove all of the 'on error resume next's so that it will throw errors? Replace lines 37-40 temporarily with Response.Write(SOAP_REQUEST) to see what it is trying to send (or debug in Visual Studio etc). – akiller Jan 04 '12 at 16:36
  • Yes, I've removed all of the "on error" statements. The SOAP request looks like it should. I've compared it with the definition provided by the webservice and everything looks as it should. – Steffen Jørgensen Jan 05 '12 at 08:25
  • Do you have remote desktop access to the server? I would try executing the call with soapUI (free version available: http://www.soapui.org/) on the server and seeing what it returns. Alternatively you could base64 encode the string before sending it to the webservice (and then decode it in the webservice method to get it back to its original form). You can use CAPICOM (http://stackoverflow.com/a/4992709/171703) or various Base 64 classes for ASP (http://www.motobit.com/tips/detpg_base64encode/ & http://www.motobit.com/tips/detpg_Base64/) to do it. – akiller Jan 05 '12 at 10:31