我正在尝试将旧版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
我已将此更新为:
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
但是当我运行.NET代码时,服务器返回错误'403 Forbidden - protocol error':
Using Response As HttpWebResponse = DirectCast(HTTPRequest.GetResponse(), HttpWebResponse)
。 VB6代码运行正常。任何人都可以发现两者之间可能造成这种差异的任何差异吗?这让我很难过......
答案 0 :(得分:2)
看起来你没有在.net版本中设置HOST标头,除非我错过它。如果您的服务器使用HostHeaderResolution在同一个IP地址上托管多个域,那么您将获得403.
这当然是一个疯狂的猜测。
答案 1 :(得分:2)
您是否尝试从两个来源捕获流量并进行比较?
我首先尝试Fiddler http://www.fiddler2.com/fiddler2/这是一个免费的HTTP调试代理。
如果这不起作用,你可以尝试使用WireShark这是一个免费的协议分析器(稍低一点,所以会有很多细节要过滤掉)。 http://www.wireshark.org/
答案 2 :(得分:1)
我认为您没有正确排序凭据。您正在使用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的例子。启动fiddler并使用命令proxycfg -u。现在,您可以观察原始内容与ASP服务器的对话。在关闭fiddler之前使用proxycfg -d。
现在,在您的.NET代码中,将以下内容放在 app .config中: -
<system.net>
<defaultProxy enabled="false">
<proxy proxyaddress="http://127.0.0.1:8888" bypassonlocal="False"/>
</defaultProxy>
</system.net>
启动fiddler并将enabled属性设置为“true”。现在您应该看到新代码尝试与ASP Server进行的对话。在使用没有fiddler捕获的新代码之前,请确保设置enabled =“false”。
答案 3 :(得分:1)
经过多次痛苦,我终于成功了。问题在于文本编码,我已将其更改为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
感谢所有帮助过的人。全面提升。