Размещение небольших кусочков данных в VB.NET - PullRequest
0 голосов
/ 23 февраля 2010

Есть ли другой способ легко сделать запрос POST в .NET, отличный от класса WebRequest? У меня есть очень, ОЧЕНЬ маленький кусочек данных, который мне нужно опубликовать:

пароль = theword

... но WebRequest случайно, а я имею в виду случайным образом, отбрасывает данные при публикации на моем сервере. Я проверил это, используя кусок кода с моего сервера, который выводит запрос на консоль, и я могу сказать, что клиент иногда отправляет, а иногда не отправляет данные POST.

Код, который я использую, который использует WebRequest, работает в другом проекте, когда общается с IIS. Обсуждаемый сервер (минимальный веб-сервер в другой системе) правильно реагирует каждый раз, когда я отправляю на него данные через Firefox. У меня есть функция в том же проекте, которая запускает запрос GET, и это работает. Просто кажется, что моя функция POST не завершает транзакцию ... то, что я заметил в прошлом, когда просил WebRequest обрабатывать небольшие строки.

Вот код, который мне подходит. Если какой-нибудь гуру .NET сможет указать мне на мою ошибку или предложить другой веб-клиент, я буду очень признателен. Спасибо!

Private Function PostRequest(ByVal url As String, ByVal data As String) As String
    Return ControlFunctions.PostRequest(url, data, 0)
End Function

Private Function PostRequest(ByVal url As String, ByVal data As String, ByVal times As Integer) As String
    Dim req As HttpWebRequest = WebRequest.Create(url)
    Dim retval As String = ""

    req.Method = "POST"
    req.UserAgent = "TSControl"
    req.ContentType = "application/x-www-form-urlencoded"
    req.ContentLength = data.Length
    req.Headers.Add("Keep-Alive", "300")
    req.KeepAlive = True
    req.Timeout = 5000

    Try
        Dim DataStream As StreamWriter = New StreamWriter(req.GetRequestStream())
        DataStream.AutoFlush = True
        DataStream.Write(data)
        DataStream.Close()

        Dim sr As StreamReader = New StreamReader(req.GetResponse().GetResponseStream())
        retval = sr.ReadToEnd()
        sr.Close()
    Catch x As Exception
        If times < 5 Then
            Threading.Thread.Sleep(1000)
            times = times + 1
            ControlFunctions.PostRequest(url, data, times)
        Else
            ErrorMsg.Show("Could not post to server" + vbCrLf + x.Message + vbCrLf + x.StackTrace)
        End If
    End Try

    Return retval
End Function

---- UPDATE ---

Мне пришлось опускаться ниже, чтобы исправить это, но, к счастью, в прошлые времена я баловался с библиотеками сокетов .NET:

Private Function PostRequest(ByVal url As String, ByVal data As String) As String
    Dim uri As New Uri(url)
    Dim read(16) As Byte
    Dim FullTime As New StringBuilder
    Dim PostReq As New StringBuilder
    Dim WebConn As New TcpClient

    PostReq.Append("POST ").Append(uri.PathAndQuery).Append(" HTTP/1.1").Append(vbCrLf)
    PostReq.Append("User-Agent: TSControl").Append(vbCrLf)
    PostReq.Append("Content-Type: application/x-www-form-urlencoded").Append(vbCrLf)
    PostReq.Append("Content-Length: ").Append(data.Length.ToString).Append(vbCrLf)
    PostReq.Append("Host: ").Append(uri.Host).Append(vbCrLf).Append(vbCrLf)
    PostReq.Append(data)

    WebConn.Connect(uri.Host, uri.Port)
    Dim WebStream As NetworkStream = WebConn.GetStream()
    Dim WebWrite As New StreamWriter(WebStream)

    WebWrite.Write(PostReq.ToString)
    WebWrite.Flush()

    Dim bytes As Integer = WebStream.Read(read, 0, read.Length)

    While bytes > 0
        FullTime.Append(Encoding.UTF8.GetString(read))
        read.Clear(read, 0, read.Length)
        bytes = WebStream.Read(read, 0, read.Length)
    End While

    ' Closes all the connections
    WebWrite.Close()
    WebStream.Close()
    WebConn.Close()

    Dim temp As String = FullTime.ToString()

    If Not temp.Length <= 0 Then
        Return temp
    Else
        Return "No page"
    End If
End Function

Ответы [ 2 ]

2 голосов
/ 26 августа 2011

Что делать, если вы получите «чанкированный» ответ? как вы это расшифровываете?

Это то, с чем я боролся сегодня весь день. Я бы не слишком много боролся, если бы имел дело с обычным веб-сервисом, но я делаю приложение, которое читает данные API eBay, и eBay иногда отправляет неправильные размеры порций, что делает декодер искажающим ответ (даже если ваш декодер декодирует его по правилам HTTP 1.1). После стольких часов попыток декодировать BAD API eBay я наконец-то создал функцию, которая декодирует фрагментированный HTTP-ответ в VB.net, и его можно легко преобразовать в C # с помощью одного из многих онлайн-инструментов. Сначала вы проверяете заголовок ответа HTTP, если тип содержимого ответа разбит на части, и если это так, просто передайте тело ответа этой функции, которая берет переменную по ссылке и манипулирует ею:

Public Shared Sub DechunkString(ByRef strString As String)
        Dim intChunkSize As Integer = 0
        Dim strSeperator(0) As String
        strSeperator(0) = vbCrLf

        Dim strChunks As String() = strString.Split(strSeperator, StringSplitOptions.RemoveEmptyEntries)

        strString = ""

        For Each strChunk As String In strChunks
            If strChunk.Length = intChunkSize Then ' for normal behaviour this would be enough
                strString &= strChunk
                intChunkSize = 0
                Continue For
            End If

            ' because of sometimes wrong chunk sizes let's check if the next chunk size is a valid hex, and if not, treat it as part chunk
            If strChunk.Length <= 4 Then ' this is probably a valid hex, but could have invalid characters
                Try
                    intChunkSize = CInt("&H" & strChunk.Trim())

                    If intChunkSize = 0 Then
                        Exit For
                    End If

                    Continue For
                Catch ex As Exception

                End Try
            End If

            ' if got to this point, then add the chunk to output and reset chunk size
            strString &= strChunk
            intChunkSize = 0
        Next
    End Sub

Я просто надеюсь, что это поможет кому-то сэкономить много времени и нервов.

0 голосов
/ 24 февраля 2010

Что вы имеете в виду, когда говорите, что «.net отбрасывает данные»?

если все, что вы хотите сделать, это опубликовать пару имя-значение, вы можете сделать это следующим образом:

WebClient client = new WebClient();
NameValueCollection nv = new NameValueCollection();
nv.Add("password", "theword");
client.UploadValues(url, "POST", nv);

Обратите внимание, что вам, возможно, придется проверить порядок параметров, передаваемых в UploadValues, я не уверен, верна ли эта последовательность, и сейчас мне лень искать MSDN.

...