Tutorial :Conversion of VB6 HTTP request to VB.Net 2.0



Question:

I'm attempting to update a legacy VB6 component (not written by me) to the .NET platform. There is one function which posts an XML string to a URL:

Function PostToUrl(ByRef psUrl, ByRef psData, Byref psResponseText, ByRef psErrorMsg, ByRef psUsername, ByRef psPassword)        On Error Resume Next          Dim objWinHTTP        PostToUrl = False      psErrorMsg = ""      psResponseText = ""      Dim m_lHTTPREQUEST_SETCREDENTIALS_FOR_SERVER      m_lHTTPREQUEST_SETCREDENTIALS_FOR_SERVER    =0          Set objWinHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")          objWinHTTP.Open "POST", psUrl        If psUsername <> "" Then          Call objWinHTTP.SetCredentials(psUsername, psPassword, m_lHTTPREQUEST_SETCREDENTIALS_FOR_SERVER)      End If      objWinHTTP.SetRequestHeader "Host", "http://www.xxx.com/CSIHTTP.asp"      objWinHTTP.SetRequestHeader "X-Method", "Submit"      objWinHTTP.SetRequestHeader "Content-Type", "text/xml"        objwinHTTP.setTimeouts 3000, 15000, 15000, 120000          Call objWinHTTP.Send(psData)        ' Handle errors  '          If Err.Number <> 0 Then            psErrorMsg = Err.Description & " test"          PostToUrl = False        ElseIf objWinHTTP.Status <> 200 AND objWinHTTP.Status <> 202 Then            psErrorMsg = "(" & objWinHTTP.Status & ") " & objWinHTTP.StatusText          PostToUrl = False        Else            psErrorMsg = objWinHTTP.ResponseText & "(" & objWinHTTP.Status & ") " & objWinHTTP.StatusText          PostToUrl = True        End If        Set objWinHTTP = Nothing  End Function  

I've updated this to:

Public Function PostXml(ByVal XML As String) As Boolean            Try              Dim URL As String = My.Settings.NTSPostURL               'TODO: supply username and password!  '              Dim Bytes As Byte() = Me.Encoding.GetBytes(XML)              Dim HTTPRequest As HttpWebRequest = DirectCast(WebRequest.Create(Me.PostURL), HttpWebRequest)              Dim Cred As New NetworkCredential("username", "password", "http://www.xxx.com")                With HTTPRequest                  .Method = "POST"                  .ContentLength = Bytes.Length                  .ContentType = "text/xml"                  .Credentials = Cred                  .Timeout = 120000                  .Method = "Submit"              End With                Using RequestStream As Stream = HTTPRequest.GetRequestStream()                  RequestStream.Write(Bytes, 0, Bytes.Length)                  RequestStream.Close()              End Using                Using Response As HttpWebResponse = DirectCast(HTTPRequest.GetResponse(), HttpWebResponse)                    If Response.StatusCode <> HttpStatusCode.OK Then                        Dim message As String = [String].Format("POST failed. Received HTTP {0}", Response.StatusCode)                        Throw New ApplicationException(message)                    End If                End Using            Catch ex As WebException              Dim s As String = ex.Response.ToString() & " " & ex.Status.ToString()              Throw          End Try        End Function  

However when I run the .NET code the server returns the error '403 Forbidden - protocol error' on the line: Using Response As HttpWebResponse = DirectCast(HTTPRequest.GetResponse(), HttpWebResponse) . The VB6 code runs fine. Can anyone identify any discrepancies between the two that might be causing this? It's left me stumped....


Solution:1

Doesnt look like you are setting a HOST header int he .net version, unless I am missing it. If your server is using HostHeaderResolution to host multiple domains on the same ip address, then you will get a 403.

This is just a wild guess of course.


Solution:2

Have you tried capturing the traffic from the two sources and comparing them?

I'd start by trying Fiddler http://www.fiddler2.com/fiddler2/ which is a free HTTP debugging proxy.

If that doesn't work you can try WireShark which is a free protocol analyzer (a bit lower level so there will be a lot of detail to filter out). http://www.wireshark.org/


Solution:3

I don't think you've got the Credential thing sorted correctly. You are using the authority portion of the URL as a credential domain.

Try it like this:-

Dim myCache as New CredentialCache()  myCache.Add(New Uri("http://www.xxx.com"), "Basic", New NetworkCredential("username", "password"))    HTTPRequest.Credentials = myCache  

This assumes that Basic authentication is needed, another contender would be "Digest" or "NTLM" which may require a domain. For example if the text of the username is like this "domain\username" in the old code then you would want:-

Dim myCache as New CredentialCache()  myCache.Add(New Uri("http://www.xxx.com"), "NTLM", New NetworkCredential("username", "password", "domain"))    HTTPRequest.Credentials = myCache  

BTW, I agree with steamer25, for this sort of thing you really need a tool such as fiddler.

If you have an example of the old stuff working place fiddler on the machine where this code runs. Start fiddler and use the command proxycfg -u. Now you can observe the converstation the original stuff has with the ASP server. Use proxycfg -d before closing fiddler.

Now in your .NET code place the following in the app.config:-

<system.net>      <defaultProxy enabled="false">          <proxy proxyaddress="http://127.0.0.1:8888" bypassonlocal="False"/>      </defaultProxy>  </system.net>  

Start fiddler and flick the enabled attribute to "true". Now you should see the conversation your new code is trying to have with the ASP Server. Make sure you set enabled="false" before using your new code without fiddler capturing.


Solution:4

After much pain I've finally managed to get it working. Problem was with the text encoding, I've changed it to ASCII and it all works:

Try              Dim Bytes As Byte() = Me.Encoding.GetBytes(XML)              Dim HTTPRequest As HttpWebRequest = DirectCast(WebRequest.Create(Me.PostURL), HttpWebRequest)                With HTTPRequest                  .Method = "POST"                  .ContentLength = Bytes.Length                  .ContentType = "text/xml"                  .Credentials = New NetworkCredential("user", "password") 'myCache              End With                Using RequestStream As Stream = HTTPRequest.GetRequestStream()                  RequestStream.Write(Bytes, 0, Bytes.Length)                  RequestStream.Close()              End Using                Using Response As HttpWebResponse = DirectCast(HTTPRequest.GetResponse(), HttpWebResponse)                    Return Response.StatusCode                End Using            Catch ex As WebException              Dim s As String = ex.Status.ToString              Throw          End Try  

Thanks to all who helped. Upvotes all round.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »