31

I'm new at using the the libraries WebClient, HttpResponse and HttpRequest in C#, so bear with me, if my question is confusing to read.

I need to build a WinForm based on C# which can open a URL, which is secured with the basic authorization. I did this with adding this to the header, like this:

using (WebClient wc = new WebClient())
{
    wc.Headers.Add(HttpRequestHeader.Authorization, "Basic " +
    Convert.ToBase64String(
    Encoding.ASCII.GetBytes(username + ":" + password)));
}

So far, so good! Now I would like to fill a form with a number, and I find the source-code from the site, and discover that the name is "number". So I write this:

NameValueCollection formData = new NameValueCollection();  
formData["number"] = number
byte[] responseBytes = wc.UploadValues(theurl, "POST", formData);
string response = Encoding.ASCII.GetString(responseBytes);
textBox_HTML.Text = response; 

But how do I submit this? I will like to receive my "search-results"...

full-stack
  • 553
  • 5
  • 20
  • (reply to your question added) – Marc Gravell Apr 28 '09 at 06:52
  • So can I clarify - is is "response" that you want to treat as an HTML form and do a POST from? It would be easier to use knowledge of the form instead - is that possible? (using things like Fiddler). If you *must* use the actual form, you might be best using something like `WebBrowser` to use an actual browser/DOM session (rather than http, which doesn't know anything about html). – Marc Gravell Apr 28 '09 at 07:52

6 Answers6

53

You should probably be using HttpWebRequest for this. Here's a simple example:

var strId = UserId_TextBox.Text;
var strName = Name_TextBox.Text;

var encoding=new ASCIIEncoding();
var postData="userid="+strId;
postData += ("&username="+strName);
byte[]  data = encoding.GetBytes(postData);

var myRequest =
  (HttpWebRequest)WebRequest.Create("http://localhost/MyIdentity/Default.aspx");
myRequest.Method = "POST";
myRequest.ContentType="application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
var newStream=myRequest.GetRequestStream();
newStream.Write(data,0,data.Length);
newStream.Close();

var response = myRequest.GetResponse();
var responseStream = response.GetResponseStream();
var responseReader = new StreamReader(responseStream);
var result = responseReader.ReadToEnd();

responseReader.Close();
response.Close();
Community
  • 1
  • 1
BFree
  • 102,548
  • 21
  • 159
  • 201
  • Hungarian Notation and over use of var. Reminds me of the old Visual Basic days. – George Stocker Apr 27 '09 at 14:41
  • 62
    So downvoting someone who took the time to write out a code sample using a coding style you don't like is *more* helpful than actually providing an answer. Interesting.... – BFree Apr 27 '09 at 14:46
  • 4
    I disagree with you guys. I can look at every one of those vars and tell you what they are without an IDE. – Samuel Apr 27 '09 at 14:48
  • 3
    Thanks for the answer. I have no problem using the HttpWebrequest, but the way I see it, nothing in the code fills out a search-form and submits this.This is my main problem. –  Apr 28 '09 at 06:16
  • Just replace the postData variable with the names of the form fields you need in your case. I believe you said it's number. So it would be something like "&number="+number; Then, if everything works correctly, the "result" variable will have the entire HTML of the search results page. At that point you can use Regex to parse the page and get what u neeed. – BFree Apr 28 '09 at 11:23
  • using var with polymorphic classes and constructors can be confusing to people who are not intimate with the API – rick schott Apr 28 '09 at 12:33
  • 5
    I don't usually use Hungarian Notation either, I must have copied and pasted that code when I answered this. As for var, I use it alot, and I will defend it!!! – BFree Oct 09 '09 at 16:43
  • 2
    @GeorgeStocker var in C# is not the same as var in Visual Basic. In C# the variable declared with var keyword is strongly typed, the compiler replaces var with a concrete type. https://msdn.microsoft.com/en-us/library/bb383973.aspx – user3285954 Apr 18 '15 at 21:08
  • rather than using ASCIIEncoding, you might want to try UT8Encoding. The Asciiencoding did not work for me. – Sync Mnemosyne Dec 10 '15 at 09:54
47

Try this:

using System.Net;
using System.Collections.Specialized;  

NameValueCollection values = new NameValueCollection();
values.Add("TextBox1", "value1");
values.Add("TextBox2", "value2");
values.Add("TextBox3", "value3");
string Url = urlvalue.ToLower();

using (WebClient client = new WebClient())
{
    client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
    byte[] result = client.UploadValues(Url, "POST", values);
    string ResultAuthTicket = System.Text.Encoding.UTF8.GetString(result);
}
mrlingam
  • 481
  • 4
  • 8
3

I have found a solution to my problem. First of all I was confused about some of the basics in http-communication. This was caused by a python-script i wrote, which have a different approach with the communication.

I solved it with generating the POST-data from scratch and open the uri, which was contained in the form-action.

2

Posting a form with System.Net.Http.HttpClient and reading the response as string:

var formData = new Dictionary<string, string>();
formData.Add("number", number);

var content = new FormUrlEncodedContent(formData);

using (var httpClient = new HttpClient())
{
    var httpResponse = await httpClient.PostAsync(theurl, content);

    var responseString = await httpResponse.Content.ReadAsStringAsync();
}
user3285954
  • 4,499
  • 2
  • 27
  • 19
1

BFree's answer works great. One thing I would note, though, is that the data concatenation should really be url-encoded, otherwise you'd have trouble with things like "=" and "&" signs within the data.

The VB.NET version, urlencoded and with UTF-8 support, is below (note that url-encoding requires a reference to System.Web.dll, which only worked for me after I switched from .NET 4 Compact Framework to the regular .NET 4 Framework).

Imports System.Web
Imports System.Net
Imports System.IO

Public Class WebFormSubmitter

    Public Shared Function submit(ByVal address As String,
                                  ByVal values As Dictionary(Of String, String)) As String
        Dim encoding As New UTF8Encoding
        Dim postData As String = getPostData(values:=values)
        Dim data() As Byte = encoding.GetBytes(postData)

        Dim request = CType(WebRequest.Create(address), HttpWebRequest)
        request.Method = "POST"
        request.ContentType = "application/x-www-form-urlencoded"
        request.ContentLength = data.Length
        Dim newStream = request.GetRequestStream()
        newStream.Write(data, 0, data.Length)
        newStream.Close()

        Dim response = request.GetResponse()
        Dim responseStream = response.GetResponseStream()
        Dim responseReader = New StreamReader(responseStream)
        Return responseReader.ReadToEnd()
    End Function

    Private Shared Function getPostData(ByVal values As Dictionary(Of String, String)) As String
        Dim postDataPairList As New List(Of String)
        For Each anEntry In values
            postDataPairList.Add(anEntry.Key & "=" & HttpUtility.UrlEncode(anEntry.Value))
        Next
        Return String.Join(separator:="&", values:=postDataPairList)
    End Function

End Class
0

You submitted it already with UploadValues. The question is: what is your "result-search"? What does the page return? HTML? If so - the HTML Agility Pack is the easiest way to parse html.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    If I already have submitted with UploadValues, why does the "response" contain the exactly same code, as if don't use UploadValues? And how does the code know, what button the HTML-page is designed to submit with? –  Apr 28 '09 at 06:23
  • I would guess that there are other required form elements. Use Fiddler to trace the actual request from the server and inspect the form contents. Re "what button"... there *is* no button in a request; that is a UI device, that the browser translates into a GET/POST/etc. – Marc Gravell Apr 28 '09 at 06:52
  • 1
    Sorry, I'm confused about the problem, because I have a hard time figuring out, how I fill out a simple form on a page. The resulting page returns a cgi-page, which contains simpel up table which infomation. –  Apr 28 '09 at 07:26