【问题标题】:Posting small bits of data in VB.NET在 VB.NET 中发布少量数据
【发布时间】:2023-10-07 08:28:01
【问题描述】:

除了 WebRequest 类之外,还有其他方法可以轻松在 .NET 中发出 POST 请求吗?我有一个非常非常小的数据需要发布:

密码=密码

...但是 WebRequest 随机(我的意思是随机)在发布到我的服务器时丢弃数据。我已经通过使用服务器中将请求转储到控制台的一大块代码对其进行了测试,我可以发现客户端有时会发送,有时不会发送 POST 数据。

在与 IIS 通信时,我使用的使用 WebRequest 的代码在另一个项目中工作。每次我通过 Firefox 向其发送数据时,与之交谈的服务器(另一个系统中的最小 Web 服务器)都会正确响应。我在同一个项目中有一个函数可以触发 GET 请求,并且可以正常工作。看起来我的 POST 函数没有完成交易......我过去在要求 WebRequest 处理小字符串时注意到了这一点。

这是让我非常满意的代码。如果有任何 .NET 专家可以指出我的错误或建议另一个 Web 客户端,我将不胜感激。谢谢!

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

----更新---

我不得不降低修复它,但幸运的是我过去曾涉足过 .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

【问题讨论】:

    标签: vb.net httpwebrequest webrequest


    【解决方案1】:

    如果您收到“分块”响应怎么办?你是怎么解码的?

    这就是我今天一整天都在努力解决的问题。如果我处理的是普通的 Web 服务,我不会太费劲,但是我正在制作一个读取 eBay 的 API 数据的应用程序,并且 eBay 有时会发送错误的块大小,这会使解码器破坏响应(即使你的解码器通过 HTTP 1.1 规则对其进行解码)。在尝试解码 eBay 的 BAD API 这么多小时后,我终于在 VB.net 中创建了一个解码分块 http 响应的函数,并且可以使用众多在线工具之一轻松将其转换为 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
    

    我只是希望它可以帮助一些人节省大量时间和精力。

    【讨论】:

      【解决方案2】:

      您说“.net 丢弃数据”是什么意思?

      如果你只想发布一个名称值对,你可以这样做:

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

      请注意,您可能需要检查传递给 UploadValues 的参数的顺序,我不确定这个顺序是否正确,现在懒得查找 MSDN。

      【讨论】: