Asynchronous vs synchronous msxml 4 http call
One site I work on has been ported from ASP to ASP.NET. Many clients have a bookmark to the old ASP page which does not exist anymore. Redirection is possible but it is slow over mobile networks like GSM/GPRS/UTMS. To work around the problem I have implemented an ASP page that does a http GET request to the correct ASP.NET page on the localhost and sends the result back to the user.
This is the core:
Public Sub getURL(ByVal sURL)
'**
'Purpose: Request the url and send the output to the end user
Dim oRequest
Dim sUserAgent
Dim sAccept
oRequest = Server.CreateObject("MSXML2.ServerXMLHTTP.4.0")
'prepare the request
On Error Resume Next
oRequest.open("GET", sURL, True)
sUserAgent = Request.ServerVariables("HTTP_USER_AGENT")
sAccept = Request.ServerVariables("HTTP_ACCEPT")
If sUserAgent <> "" Then oRequest.setRequestHeader("User-Agent", sUserAgent)
If sAccept <> "" Then oRequest.setRequestHeader("Accept", sAccept)
'send and wait for reply
oRequest.send()
oRequest.waitForResponse(HTTP_REQUEST_TIMEOUT)
'Check if ther is an error
lRequestError = err.number
On Error GoTo 0
If lRequestError <> 0 Then handleError(ERROR_REQUEST_FAILED)
If oRequest.readyState <> 4 Then '4 => request complete
oRequest.abort()
handleError(ERROR_REQUEST_TIMEOUT) 'Does Response.End()
End If
'Send the response back to the user
Response.ContentType = oRequest.getResponseHeader("Content-Type")
Response.Expires = oRequest.getResponseHeader("Expires")
Response.Write(oRequest.responseText)
oRequest = Nothing
End Sub
I have a strange problem in a Win2k3 environment with a lot of machines in NLB. When page1.asp calls page1.aspx I see the following time taken fields in the IIS log:
Page1.asp: 50 ms
Page1.aspx: 29995 ms
These results are impossible as page1.asp executes page1.aspx and waits for page1.aspx to complete output before it sends it to the client. So the call time of Page1.aspx must be lower than the call tome of Page1.asp. It seems like the aspx page waits for the asp page to close the connection somehow. The interesting thing is that it does not have this problem if it calls a remote server.
We found the fix but I haven't managed to epxlain to myself why it works. I guess the asynchronous thread causes problems, but why the heck does it only cause problems when going to localhost?
The fix is to make the request synchronously by changing the code like this:
'prepare the request
On Error Resume Next
oRequest.open("GET", sURL, True False)
sUserAgent = Request.ServerVariables("HTTP_USER_AGENT")
sAccept = Request.ServerVariables("HTTP_ACCEPT")
If sUserAgent <> "" Then oRequest.setRequestHeader("User-Agent", sUserAgent)
If sAccept <> "" Then oRequest.setRequestHeader("Accept", sAccept)
'send and wait for reply
oRequest.send()
oRequest.waitForResponse(HTTP_REQUEST_TIMEOUT)
'Check if ther is an error
lRequestError = err.number
On Error GoTo 0
If lRequestError <> 0 Then handleError(ERROR_REQUEST_FAILED)
If oRequest.readyState <> 4 Then '4 => request complete
oRequest.abort()
handleError(ERROR_REQUEST_TIMEOUT) 'Does Response.End()
End If
Explanations are more than welcome.