views:

131

answers:

1

Is there another way to easily make a POST request in .NET other than the WebRequest class? I have a very, VERY small piece of data I need to post:

password=theword

...but WebRequest randomly, and I mean randomly, drops the data when posting to my server. I've tested it by using a chunk of code from my server that dumps the request to a console, and I can that the client is sometimes sending and sometimes not sending the POST data.

The code that I'm using that uses WebRequest works in another project, when talking to IIS. The server being talked to (a minimal web server in another system) responds properly every time I POST data to it through Firefox. I've got a function in the same project that fires off a GET request, and that works. It just seems like my POST function isn't completing the transaction...something I've noticed in the past when asking WebRequest to handle small strings.

Here's the code that's giving me fits. If any .NET gurus out there can point me at my mistake or suggest another web client, I'd be most appreciative. Thanks!

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---

I had to go lower to fix it, but fortunately I'd dabbled with .NET's socket libraries in times past:

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
A: 

What do you mean when you say that ".net drops the data"?

if all you want to do is post a namevalue pair, you can do it as follows:

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

Note that you might have to check the order of parameters passed to UploadValues, I am not sure if this sequence is right, and am too lazy right now to look up MSDN.

feroze