Преобразование HTTP-запроса VB6 в VB.Net 2.0 - PullRequest
2 голосов
/ 02 июня 2009

Я пытаюсь обновить устаревший компонент 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 работает нормально. Может ли кто-нибудь определить какие-либо несоответствия между этими двумя причинами? Это оставило меня в тупике ....

Ответы [ 4 ]

2 голосов
/ 02 июня 2009

Вы пытались захватить трафик из двух источников и сравнить их?

Я бы начал с попытки Fiddler http://www.fiddler2.com/fiddler2/, который является бесплатным прокси-сервером отладки HTTP.

Если это не сработает, вы можете попробовать WireShark, который является бесплатным анализатором протоколов (немного ниже, поэтому будет много деталей для фильтрации). http://www.wireshark.org/

2 голосов
/ 02 июня 2009

Не похоже, что вы устанавливаете заголовок HOST в версии .net, если я не пропускаю его. Если ваш сервер использует HostHeaderResolution для размещения нескольких доменов по одному и тому же IP-адресу, вы получите 403.

Это просто дикое предположение, конечно.

1 голос
/ 24 июня 2009

После большой боли мне наконец-то удалось заставить его работать. Проблема была с кодировкой текста, я изменил его на 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

Спасибо всем, кто помог. Проголосует со всех сторон.

1 голос
/ 02 июня 2009

Я не думаю, что у вас есть учетные данные, отсортированные правильно. Вы используете авторитетную часть 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. Используйте proxycfg -d перед закрытием фиддлера.

Теперь в вашем .NET-коде поместите в приложение .config следующее: -

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

Запустите fiddler и установите для включенного атрибута значение «true». Теперь вы должны увидеть разговор вашего нового кода с ASP-сервером. Убедитесь, что вы установили enabled = "false" перед использованием нового кода без захвата скрипача.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...