VB6 HTTP请求到VB.Net 2.0的转换

VB6 HTTP请求到VB.Net 2.0的转换,.net,vb.net,vb6,httpwebrequest,.net,Vb.net,Vb6,Httpwebrequest,我正在尝试将旧版VB6组件(不是我编写的)更新到.NET平台。有一个函数可将XML字符串发布到URL: Function PostToUrl(ByRef psUrl, ByRef psData, Byref psResponseText, ByRef psErrorMsg, ByRef psUsername, ByRef psPassword) On Error Resume Next Dim objWinHTTP PostToUrl = False

我正在尝试将旧版VB6组件(不是我编写的)更新到.NET平台。有一个函数可将XML字符串发布到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
函数PostToUrl(ByRef psUrl、ByRef psData、ByRef psResponseText、ByRef psErrorMsg、ByRef psUsername、ByRef psPassword)
出错时继续下一步
Dim objWinHTTP
PostToUrl=假
psErrorMsg=“”
psResponseText=“”
Dim m_lhtprequest_SETCREDENTIALS_用于\u服务器
m_lhtprequest_SETCREDENTIALS_服务器=0
设置objWinHTTP=CreateObject(“WinHttp.WinHttpRequest.5.1”)
objWinHTTP.Open“POST”,psUrl
如果psUsername为“”,则
调用objWinHTTP.SetCredentials(psUsername、psPassword、m_lHTTPREQUEST_SetCredentials_FOR_服务器)
如果结束
objWinHTTP.SetRequestHeader“主机”http://www.xxx.com/CSIHTTP.asp"
objWinHTTP.SetRequestHeader“X方法”、“提交”
objWinHTTP.SetRequestHeader“内容类型”、“文本/xml”
objwinHTTP.setTimeouts 3000、15000、15000、120000
调用objWinHTTP.Send(psData)
“处理错误”
如果错误号为0,则
psErrorMsg=错误说明和“测试”
PostToUrl=假
ElseIf objWinHTTP.Status 200和objWinHTTP.Status 202
psErrorMsg=“(“&objWinHTTP.Status&”)和objWinHTTP.StatusText
PostToUrl=假
其他的
psErrorMsg=objWinHTTP.ResponseText&“(“&objWinHTTP.Status&”)和objWinHTTP.StatusText
PostToUrl=真
如果结束
设置objWinHTTP=Nothing
端函数
我已将此更新为:

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
作为布尔值的公共函数PostXml(ByVal XML作为字符串)
尝试
将URL设置为字符串=My.Settings.NTSPostURL
'TODO:提供用户名和密码!'
Dim Bytes As Byte()=Me.Encoding.GetBytes(XML)
Dim HTTPRequest作为HttpWebRequest=DirectCast(WebRequest.Create(Me.postrl),HttpWebRequest)
Dim Cred作为新的网络凭据(“用户名”、“密码”和“http://www.xxx.com")
使用HTTPRequest
.Method=“POST”
.ContentLength=字节.Length
.ContentType=“text/xml”
.Credentials=Cred
.超时=120000
.Method=“提交”
以
使用RequestStream作为Stream=HTTPRequest.GetRequestStream()
RequestStream.Write(字节、0、字节、长度)
RequestStream.Close()
终端使用
使用响应作为HttpWebResponse=DirectCast(HTTPRequest.GetResponse(),HttpWebResponse)
如果Response.StatusCode HttpStatusCode.OK,则
Dim消息为字符串=[String]。格式(“POST失败。收到HTTP{0}”,响应。状态码)
抛出新的ApplicationException(消息)
如果结束
终端使用
捕获ex作为WebException
Dim s As String=ex.Response.ToString()&“&ex.Status.ToString()
扔
结束尝试
端函数
但是,当我运行.NET代码时,服务器在以下行返回错误“403禁止-协议错误”:
使用响应作为HttpWebResponse=DirectCast(HTTPRequest.GetResponse(),HttpWebResponse)

。VB6代码运行良好。有人能找出这两者之间可能导致这种情况的任何差异吗?这让我很困惑。…

看起来你没有在.net版本中设置主机头,除非我找不到它。如果您的服务器使用HostHeaderResolution在同一ip地址上承载多个域,那么您将获得403


当然,这只是一个猜测

您是否尝试过从这两个来源捕获流量并进行比较

我首先尝试Fiddler,它是一个免费的HTTP调试代理


如果这不起作用,你可以试试WireShark,它是一个免费的协议分析器(级别稍微低一点,所以会有很多细节需要过滤掉)

我认为您没有正确处理凭证问题。您正在使用URL的授权部分作为凭据域

试着这样做:-

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

HTTPRequest.Credentials = myCache
这假设需要基本身份验证,另一个竞争者将是可能需要域的“摘要”或“NTLM”。例如,如果旧代码中的用户名文本类似于“域\用户名”,则您需要:-

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

HTTPRequest.Credentials = myCache
顺便说一句,我同意steamer25,对于这类事情,你真的需要一个像fiddler这样的工具

如果您有一个运行此代码的机器上的旧东西working place fiddler的示例。启动fiddler并使用命令proxycfg-u。现在,您可以观察原始内容与ASP服务器的对话。在关闭fiddler之前使用proxycfg-d

现在,在.NET代码中,将以下内容放在app.config中:-



启动fiddler并将enabled属性轻弹为“true”。现在,您应该看到新代码试图与ASP服务器进行的对话。在使用新代码之前,请确保设置enabled=“false”,而不使用fiddler捕获。

在经历了很多痛苦之后,我终于成功地让它工作了。问题在于文本编码,我已将其更改为ASCII,并且一切正常:

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

感谢所有帮助过我的人。向上投票。

事实上,这看起来是一个很好的猜测,因为VB6示例使用了一个完整的URL作为主机标题,这并不完全是常规的。感谢您的回复,您知道如何设置它吗?据我所知,没有设置这个属性。主机头的事情很奇怪。1.WinHTTP组件将为您添加从URL绘制的主机头,这是HTTP/1.1要求。2.主机头应该是URL的主机名部分,它不应该包含其他路径元素。@Simon:忽略主机头,它不起任何作用,您当然不应该尝试自己将主机头添加到请求中。很可能主机头在服务中不是毫无意义的
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