.NET: Simplest way to send POST with data and read response
Asked Answered
B

9

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?

Bjorn answered 3/11, 2010 at 15:21 Comment(1)
This actually worked perfectly for me... stickler.de/en/information/code-snippets/…Outofdoor
A
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" }
});
Ardyce answered 3/11, 2010 at 15:28 Comment(6)
If you want more control over the HTTP headers, you could attempt the same using HttpWebRequest and reference RFC2616 (w3.org/Protocols/rfc2616/rfc2616.txt). Answers from jball and BFree follow that attempt.Ardyce
This example doesn't actually read the response, which was an important part of the original question!Mehala
To read the response, you can do string result = System.Text.Encoding.UTF8.GetString(response). This is the question where I found the answer.Fritter
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."Gatling
I'm gonna plus-one this, but you should include @Fritter comment about reading the response to improve your answer.Testicle
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.Melon
P
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)
{


}
Paucity answered 28/2, 2013 at 7:15 Comment(6)
Also works with a Dictionary<String, String>, which makes it cleaner.Sanative
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 <hugs>Ablate
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.Elongation
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...Melon
how to send files with httpclientYoko
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.Dianetics
W
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();
}
Wolfy answered 3/11, 2010 at 15:25 Comment(0)
G
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();
}
Gnash answered 3/11, 2010 at 15:27 Comment(0)
H
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

Hernandes answered 3/11, 2010 at 15:27 Comment(1)
+1 I suspect there's a bunch of ways to do this in the framework.Wolfy
S
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);
Solanaceous answered 8/10, 2018 at 16:33 Comment(0)
U
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);
}
Unanimous answered 18/10, 2013 at 11:51 Comment(1)
What is httpRequest? Its giving me an error "Does not exist".Southerly
F
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
Farro answered 3/11, 2010 at 15:31 Comment(0)
J
0

Here is an example from .net 7:

Note that httpClient.PostAsJsonAsync is an extension method. This means you must add System.Net.Http.Json to your project, and then use it using System.Text.Json; or you will get a compile error.

Also note that this example instantiates an httpClient for every request. This is NOT recommended. This practice forces a new connection on every call, which requires a new https handshake. Instead, use a singleton or static instance. See the docs for full details on how to correctly implement this, or see my video here: https://youtu.be/BA1e_ez8fwI?si=Tt0ppiIxoVOX57mA

var roomRequest = new RoomRequest() { EndDate = DateTime.Now.AddHours(2) };
RoomRequestResponse roomRequestResponse;

var apiKey = await this.DataStore.GetAppSetting("whereby-api");
HttpClient client = new HttpClient();

client.DefaultRequestHeaders.Authorization
             = new AuthenticationHeaderValue("Bearer", apiKey.Value);
var response = await client.PostAsJsonAsync("https://api.whereby.dev/v1/meetings", roomRequest);

string jsonString = await response.Content.ReadAsStringAsync();


RoomRequestResponse? returnValue=
    JsonSerializer.Deserialize<RoomRequestResponse>(jsonString);
Janssen answered 19/11, 2023 at 5:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.