183

To my surprise, I can't do anything nearly as simple as this, from what I can tell, in the .NET BCL:

byte[] response = Http.Post
(
    url: "http://dork.com/service",
    contentType: "application/x-www-form-urlencoded",
    contentLength: 32,
    content: "home=Cosby&favorite+flavor=flies"
);

This hypothetical code above makes an HTTP POST, with data, and returns the response from a Post method on a static class Http.

Since we're left without something this easy, what's the next best solution?

How do I send an HTTP POST with data AND get the response's content?

ocean4dream
  • 5,082
  • 1
  • 15
  • 17
  • This actually worked perfectly for me... http://www.stickler.de/en/information/code-snippets/httpwebrequest-post-data.aspx – Jamie Tabone Dec 13 '14 at 11:38

8 Answers8

291
   using (WebClient client = new WebClient())
   {

       byte[] response =
       client.UploadValues("http://dork.com/service", new NameValueCollection()
       {
           { "home", "Cosby" },
           { "favorite+flavor", "flies" }
       });

       string result = System.Text.Encoding.UTF8.GetString(response);
   }

You will need these includes:

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

If you're insistent on using a static method/class:

public static class Http
{
    public static byte[] Post(string uri, NameValueCollection pairs)
    {
        byte[] response = null;
        using (WebClient client = new WebClient())
        {
            response = client.UploadValues(uri, pairs);
        }
        return response;
    }
}

Then simply:

var response = Http.Post("http://dork.com/service", new NameValueCollection() {
    { "home", "Cosby" },
    { "favorite+flavor", "flies" }
});
HasanG
  • 12,734
  • 29
  • 100
  • 154
Chris Hutchinson
  • 9,082
  • 3
  • 27
  • 33
  • 3
    If you want more control over the HTTP headers, you could attempt the same using HttpWebRequest and reference RFC2616 (http://www.w3.org/Protocols/rfc2616/rfc2616.txt). Answers from jball and BFree follow that attempt. – Chris Hutchinson Nov 03 '10 at 15:30
  • 9
    This example doesn't actually read the response, which was an important part of the original question! – Jon Watte Jul 23 '13 at 18:55
  • 4
    To read the response, you can do `string result = System.Text.Encoding.UTF8.GetString(response)`. [This is the question where I found the answer.](http://stackoverflow.com/questions/1003275/converting-byte-to-string-in-c-sharp) – jporcenaluk Mar 26 '14 at 20:09
  • This method will no longer work if you're trying to build a Windows Store app for Windows 8.1, as WebClient isn't found in System.Net. Instead, use Ramesh's answer and look into the usage of "await." – Stephen Wylie Jun 10 '14 at 15:24
  • 2
    I'm gonna plus-one this, but you should include @jporcenaluk comment about reading the response to improve your answer. – Corgalore Aug 26 '14 at 13:07
  • Nice working solution, but I would like to add that Microsoft implemented the HttpClient class, a newer api that has some benefits over the WebClient class. – Luis Gouveia Jun 09 '16 at 10:43
81

Using HttpClient: as far as Windows 8 app development concerns, I came across this.

var client = new HttpClient();

var pairs = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("pqpUserName", "admin"),
        new KeyValuePair<string, string>("password", "test@123")
    };

var content = new FormUrlEncodedContent(pairs);

var response = client.PostAsync("youruri", content).Result;

if (response.IsSuccessStatusCode)
{


}
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Ramesh
  • 392
  • 1
  • 12
  • 39
  • 6
    Also works with a Dictionary, which makes it cleaner. – Peter Hedberg Mar 17 '13 at 19:50
  • 24
    BEST ANSWER EVER.. Oh thank the lords, thank you I love you. I have been struggling.. 2 FREAKNG WEEKS.. you should see all my posts. ARGHH ITS WORKING, YEHAAA – Jimmyt1988 Sep 25 '13 at 22:39
  • 1
    Note that, when possible, you should not use `.Result` with `Async` calls - use `await` to ensure your UI thread will not block. Also, a simple `new[]` will work as well as the List; Dictionary may clean up the code, but will reduce some HTTP functionality. – Matt DeKrey Jul 03 '14 at 13:04
  • 2
    Nowadays (2016) this one is the best answer. HttpClient is newer than WebClient (most voted answer) and has some benefits over it: 1) It has a good async programming model being worked on by Henrik F Nielson who is basically one of the inventors of HTTP, and he designed the API so it is easy for you to follow the HTTP standard; 2) It is supported by the .Net framework 4.5, so it has some guaranteed level of support for the forseeable future; 3) It also has the xcopyable/portable-framework version of the library if you want to use it on other platforms - .Net 4.0, Windows Phone etc... – Luis Gouveia Jun 09 '16 at 10:57
  • how to send files with httpclient – Darshan Dave Aug 31 '17 at 00:33
  • Thanks dude, I've literally never worked with APIs in Dotnet before with backend C# code anyway. I literally sat down tried this, because it looked simple, accurate and concise. Worked first time(having never touched Web APIs in Dotnet before). You're a star! Much better than any documentation I can find out there. – Lee Aug 12 '18 at 13:43
47

Use WebRequest. From Scott Hanselman:

public static string HttpPost(string URI, string Parameters) 
{
   System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
   req.Proxy = new System.Net.WebProxy(ProxyString, true);
   //Add these, as we're doing a POST
   req.ContentType = "application/x-www-form-urlencoded";
   req.Method = "POST";
   //We need to count how many bytes we're sending. 
   //Post'ed Faked Forms should be name=value&
   byte [] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
   req.ContentLength = bytes.Length;
   System.IO.Stream os = req.GetRequestStream ();
   os.Write (bytes, 0, bytes.Length); //Push it out there
   os.Close ();
   System.Net.WebResponse resp = req.GetResponse();
   if (resp== null) return null;
   System.IO.StreamReader sr = 
         new System.IO.StreamReader(resp.GetResponseStream());
   return sr.ReadToEnd().Trim();
}
jball
  • 24,791
  • 9
  • 70
  • 92
32
private void PostForm()
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://dork.com/service");
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    string postData ="home=Cosby&favorite+flavor=flies";
    byte[] bytes = Encoding.UTF8.GetBytes(postData);
    request.ContentLength = bytes.Length;

    Stream requestStream = request.GetRequestStream();
    requestStream.Write(bytes, 0, bytes.Length);

    WebResponse response = request.GetResponse();
    Stream stream = response.GetResponseStream();
    StreamReader reader = new StreamReader(stream);

    var result = reader.ReadToEnd();
    stream.Dispose();
    reader.Dispose();
}
Gericke
  • 2,109
  • 9
  • 42
  • 71
BFree
  • 102,548
  • 21
  • 159
  • 201
12

Personally, I think the simplest approach to do an http post and get the response is to use the WebClient class. This class nicely abstracts the details. There's even a full code example in the MSDN documentation.

http://msdn.microsoft.com/en-us/library/system.net.webclient(VS.80).aspx

In your case, you want the UploadData() method. (Again, a code sample is included in the documentation)

http://msdn.microsoft.com/en-us/library/tdbbwh0a(VS.80).aspx

UploadString() will probably work as well, and it abstracts it away one more level.

http://msdn.microsoft.com/en-us/library/system.net.webclient.uploadstring(VS.80).aspx

David
  • 72,686
  • 18
  • 132
  • 173
8

Given other answers are a few years old, currently here are my thoughts that may be helpful:

Simplest way

private async Task<string> PostAsync(Uri uri, HttpContent dataOut)
{
    var client = new HttpClient();
    var response = await client.PostAsync(uri, dataOut);
    return await response.Content.ReadAsStringAsync();
    // For non strings you can use other Content.ReadAs...() method variations
}

A More Practical Example

Often we are dealing with known types and JSON, so you can further extend this idea with any number of implementations, such as:

public async Task<T> PostJsonAsync<T>(Uri uri, object dtoOut)
{
    var content = new StringContent(JsonConvert.SerializeObject(dtoOut));
    content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

    var results = await PostAsync(uri, content); // from previous block of code

    return JsonConvert.DeserializeObject<T>(results); // using Newtonsoft.Json
}

An example of how this could be called:

var dataToSendOutToApi = new MyDtoOut();
var uri = new Uri("https://example.com");
var dataFromApi = await PostJsonAsync<MyDtoIn>(uri, dataToSendOutToApi);
ToddBFisher
  • 11,370
  • 8
  • 38
  • 54
7

I know this is an old thread, but hope it helps some one.

public static void SetRequest(string mXml)
{
    HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp("http://dork.com/service");
    webRequest.Method = "POST";
    webRequest.Headers["SOURCE"] = "WinApp";

    // Decide your encoding here

    //webRequest.ContentType = "application/x-www-form-urlencoded";
    webRequest.ContentType = "text/xml; charset=utf-8";

    // You should setContentLength
    byte[] content = System.Text.Encoding.UTF8.GetBytes(mXml);
    webRequest.ContentLength = content.Length;

    var reqStream = await webRequest.GetRequestStreamAsync();
    reqStream.Write(content, 0, content.Length);

    var res = await httpRequest(webRequest);
}
Murali
  • 500
  • 5
  • 22
5

You can use something like this pseudo code:

request = System.Net.HttpWebRequest.Create(your url)
request.Method = WebRequestMethods.Http.Post

writer = New System.IO.StreamWriter(request.GetRequestStream())
writer.Write("your data")
writer.Close()

response = request.GetResponse()
reader = New System.IO.StreamReader(response.GetResponseStream())
responseText = reader.ReadToEnd
paludarium
  • 190
  • 2