How to make an HTTP POST web request

2,105,039

Solution 1

There are several ways to perform HTTP GET and POST requests:


Method A: HttpClient (Preferred)

Available in: .NET Framework 4.5+, .NET Standard 1.1+, .NET Core 1.0+ .

It is currently the preferred approach, and is asynchronous and high performance. Use the built-in version in most cases, but for very old platforms there is a NuGet package.

using System.Net.Http;

Setup

It is recommended to instantiate one HttpClient for your application's lifetime and share it unless you have a specific reason not to.

private static readonly HttpClient client = new HttpClient();

See HttpClientFactory for a dependency injection solution.


  • POST

      var values = new Dictionary<string, string>
      {
          { "thing1", "hello" },
          { "thing2", "world" }
      };
    
      var content = new FormUrlEncodedContent(values);
    
      var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content);
    
      var responseString = await response.Content.ReadAsStringAsync();
    
  • GET

      var responseString = await client.GetStringAsync("http://www.example.com/recepticle.aspx");
    

Method B: Third-Party Libraries

RestSharp

  • POST

       var client = new RestClient("http://example.com");
       // client.Authenticator = new HttpBasicAuthenticator(username, password);
       var request = new RestRequest("resource/{id}");
       request.AddParameter("thing1", "Hello");
       request.AddParameter("thing2", "world");
       request.AddHeader("header", "value");
       request.AddFile("file", path);
       var response = client.Post(request);
       var content = response.Content; // Raw content as string
       var response2 = client.Post<Person>(request);
       var name = response2.Data.Name;
    

Flurl.Http

It is a newer library sporting a fluent API, testing helpers, uses HttpClient under the hood, and is portable. It is available via NuGet.

    using Flurl.Http;

  • POST

      var responseString = await "http://www.example.com/recepticle.aspx"
          .PostUrlEncodedAsync(new { thing1 = "hello", thing2 = "world" })
          .ReceiveString();
    
  • GET

      var responseString = await "http://www.example.com/recepticle.aspx"
          .GetStringAsync();
    

Method C: HttpWebRequest (not recommended for new work)

Available in: .NET Framework 1.1+, .NET Standard 2.0+, .NET Core 1.0+. In .NET Core, it is mostly for compatibility -- it wraps HttpClient, is less performant, and won't get new features.

using System.Net;
using System.Text;  // For class Encoding
using System.IO;    // For StreamReader

  • POST

      var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx");
    
      var postData = "thing1=" + Uri.EscapeDataString("hello");
          postData += "&thing2=" + Uri.EscapeDataString("world");
      var data = Encoding.ASCII.GetBytes(postData);
    
      request.Method = "POST";
      request.ContentType = "application/x-www-form-urlencoded";
      request.ContentLength = data.Length;
    
      using (var stream = request.GetRequestStream())
      {
          stream.Write(data, 0, data.Length);
      }
    
      var response = (HttpWebResponse)request.GetResponse();
    
      var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
    
  • GET

      var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx");
    
      var response = (HttpWebResponse)request.GetResponse();
    
      var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
    

Method D: WebClient (Not recommended for new work)

This is a wrapper around HttpWebRequest. Compare with HttpClient.

Available in: .NET Framework 1.1+, NET Standard 2.0+, .NET Core 2.0+.

In some circumstances (.NET Framework 4.5-4.8), if you need to do a http request synchronously, WebClient can still be used.

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

  • POST

      using (var client = new WebClient())
      {
          var values = new NameValueCollection();
          values["thing1"] = "hello";
          values["thing2"] = "world";
    
          var response = client.UploadValues("http://www.example.com/recepticle.aspx", values);
    
          var responseString = Encoding.Default.GetString(response);
      }
    
  • GET

      using (var client = new WebClient())
      {
          var responseString = client.DownloadString("http://www.example.com/recepticle.aspx");
      }
    

Solution 2

Simple GET request

using System.Net;

...

using (var wb = new WebClient())
{
    var response = wb.DownloadString(url);
}

Simple POST request

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

...

using (var wb = new WebClient())
{
    var data = new NameValueCollection();
    data["username"] = "myUser";
    data["password"] = "myPassword";

    var response = wb.UploadValues(url, "POST", data);
    string responseInString = Encoding.UTF8.GetString(response);
}

Solution 3

MSDN has a sample.

using System;
using System.IO;
using System.Net;
using System.Text;

namespace Examples.System.Net
{
    public class WebRequestPostExample
    {
        public static void Main()
        {
            // Create a request using a URL that can receive a post. 
            WebRequest request = WebRequest.Create("http://www.contoso.com/PostAccepter.aspx");
            // Set the Method property of the request to POST.
            request.Method = "POST";
            // Create POST data and convert it to a byte array.
            string postData = "This is a test that posts this string to a Web server.";
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            // Set the ContentType property of the WebRequest.
            request.ContentType = "application/x-www-form-urlencoded";
            // Set the ContentLength property of the WebRequest.
            request.ContentLength = byteArray.Length;
            // Get the request stream.
            Stream dataStream = request.GetRequestStream();
            // Write the data to the request stream.
            dataStream.Write(byteArray, 0, byteArray.Length);
            // Close the Stream object.
            dataStream.Close();
            // Get the response.
            WebResponse response = request.GetResponse();
            // Display the status.
            Console.WriteLine(((HttpWebResponse)response).StatusDescription);
            // Get the stream containing content returned by the server.
            dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string responseFromServer = reader.ReadToEnd();
            // Display the content.
            Console.WriteLine(responseFromServer);
            // Clean up the streams.
            reader.Close();
            dataStream.Close();
            response.Close();
        }
    }
}

Solution 4

This is a complete working example of sending/receiving data in JSON format, I used Visual Studio 2013 Express Edition:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;

namespace ConsoleApplication1
{
    class Customer
    {
        public string Name { get; set; }
        public string Address { get; set; }
        public string Phone { get; set; }
    }

    public class Program
    {
        private static readonly HttpClient _Client = new HttpClient();
        private static JavaScriptSerializer _Serializer = new JavaScriptSerializer();

        static void Main(string[] args)
        {
            Run().Wait();
        }

        static async Task Run()
        {
            string url = "http://www.example.com/api/Customer";
            Customer cust = new Customer() { Name = "Example Customer", Address = "Some example address", Phone = "Some phone number" };
            var json = _Serializer.Serialize(cust);
            var response = await Request(HttpMethod.Post, url, json, new Dictionary<string, string>());
            string responseText = await response.Content.ReadAsStringAsync();

            List<YourCustomClassModel> serializedResult = _Serializer.Deserialize<List<YourCustomClassModel>>(responseText);

            Console.WriteLine(responseText);
            Console.ReadLine();
        }

        /// <summary>
        /// Makes an async HTTP Request
        /// </summary>
        /// <param name="pMethod">Those methods you know: GET, POST, HEAD, etc...</param>
        /// <param name="pUrl">Very predictable...</param>
        /// <param name="pJsonContent">String data to POST on the server</param>
        /// <param name="pHeaders">If you use some kind of Authorization you should use this</param>
        /// <returns></returns>
        static async Task<HttpResponseMessage> Request(HttpMethod pMethod, string pUrl, string pJsonContent, Dictionary<string, string> pHeaders)
        {
            var httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = pMethod;
            httpRequestMessage.RequestUri = new Uri(pUrl);
            foreach (var head in pHeaders)
            {
                httpRequestMessage.Headers.Add(head.Key, head.Value);
            }
            switch (pMethod.Method)
            {
                case "POST":
                    HttpContent httpContent = new StringContent(pJsonContent, Encoding.UTF8, "application/json");
                    httpRequestMessage.Content = httpContent;
                    break;

            }

            return await _Client.SendAsync(httpRequestMessage);
        }
    }
}

Solution 5

There are some really good answers on here. Let me post a different way to set your headers with the WebClient(). I will also show you how to set an API key.

        var client = new WebClient();
        string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(userName + ":" + passWord));
        client.Headers[HttpRequestHeader.Authorization] = $"Basic {credentials}";
        //If you have your data stored in an object serialize it into json to pass to the webclient with Newtonsoft's JsonConvert
        var encodedJson = JsonConvert.SerializeObject(newAccount);

        client.Headers.Add($"x-api-key:{ApiKey}");
        client.Headers.Add("Content-Type:application/json");
        try
        {
            var response = client.UploadString($"{apiurl}", encodedJson);
            //if you have a model to deserialize the json into Newtonsoft will help bind the data to the model, this is an extremely useful trick for GET calls when you have a lot of data, you can strongly type a model and dump it into an instance of that class.
            Response response1 = JsonConvert.DeserializeObject<Response>(response);
Share:
2,105,039
Hooch
Author by

Hooch

Updated on April 16, 2022

Comments

  • Hooch
    Hooch about 2 years

    Canonical
    How can I make an HTTP request and send some data using the POST method?

    I can do a GET request, but I have no idea of how to make a POST request.

  • Lloyd
    Lloyd about 13 years
    How do you get the response from that?
  • Evan Mulawski
    Evan Mulawski about 13 years
    @Lloyd: HttpWebResponse response = (HttpWebResponse)HttpWReq.GetResponse();
  • Lloyd
    Lloyd about 13 years
    after the newStream is closed?
  • Evan Mulawski
    Evan Mulawski about 13 years
    @Lloyd: If you are posting data to the stream (using the last three lines) it would make sense to check the response beforehand.
  • Mathias Lykkegaard Lorenzen
    Mathias Lykkegaard Lorenzen over 10 years
    Why are you instantiating the ASCIIEncoding object instead of using the static System.Text.Encoding.ASCII?
  • Gero
    Gero over 10 years
    Why do you even use ASCII? What if someone needs an xml with UTF-8?
  • user_v
    user_v over 10 years
    +1 For regular stuff POST it is great to have such short piece of code.
  • Cameron Wilby
    Cameron Wilby over 10 years
    Tim - If you right click the literal that can't be resolved, you will find a Resolve context menu, which contains actions to add the Using statements for you. If the Resolve context menu doesn't show up, it means you need to add references first.
  • Hooch
    Hooch over 10 years
    I accepted your answer as good because it is much more simpler and clearer.
  • Sindre
    Sindre over 10 years
    I would like to add that the response variable for the POST request is a byte array. In order to get the string response you just do Encoding.ASCII.GetString(response); (using System.Text)
  • Hooch
    Hooch about 10 years
    @Sindre You can add it to the post.
  • AnKing
    AnKing almost 10 years
    For some reason it didnt work when i was sending large amount of data
  • Hooch
    Hooch over 9 years
    After so long time. I switched accepted answer to yours. As it is so much more detailed and I like that you shown old, obsolete methods.
  • David S.
    David S. over 9 years
    I hate to beat a dead horse but you should do response.Result.Content.ReadAsStringAsync()
  • Evan Mulawski
    Evan Mulawski over 9 years
    @DavidS. response should be a HttpResponseMessage - are you missing an await when calling PostAsync?
  • Hiep
    Hiep over 8 years
    why did you say WebRequest and WebClient are legacy? MSDN doesn't say that they are deprecated or anything. Am I missing something?
  • Evan Mulawski
    Evan Mulawski over 8 years
    @Hiep: They are not deprecated, there are just newer (and is most cases, better and more flexible) ways of making web requests. In my opinion, for simple, non-critical operations, the old ways are just fine - but it's up to you and whatever you are most comfortable with.
  • Bimal Poudel
    Bimal Poudel almost 8 years
    Further, you can send a bit complex array $_POST['user'] as: data["user[username]"] = "myUsername"; data["user[password]"] = "myPassword";
  • Greg A
    Greg A almost 7 years
    I know you said the preferred method is to instantiate a private readonly HttpClient but I think it is cleaner (and safer) to do a using statement instead. using (var client = new HttpClient()) { }
  • Evan Mulawski
    Evan Mulawski almost 7 years
    @GregA: It's not just me. The developers of HttpClient recommend one instantiation per application. In reality, it may be necessary to instantiate more, depending on what your application does. Just because it implements IDisposable does not mean you must put it in a using block.
  • Greg A
    Greg A almost 7 years
    @EvanMulawski Evan, in my application I am using dependency injection in a web api. In my case i believe taking advantage of the using block is the correct way to go.
  • hellboy
    hellboy almost 7 years
    RestSharp seems to be dead. Simply dead.
  • Hooch
    Hooch over 6 years
    That is quite bad. I don't recommend it as there is no error handling of any kind and debugging it is pain. Additionally there already is great answer to this question.
  • Mitulát báti
    Mitulát báti over 6 years
    @Hooch others might be interested in this type of answers, even if it's not the best one.
  • Extragorey
    Extragorey almost 5 years
    Agreed, the only context in which this would be useful is code golfing and who golfs in C# ;)
  • Wyck
    Wyck almost 5 years
    I wish this answer mentioned that it is possible to post raw byte[] content by substituting a ByteArrayContent for the example's FormUrlEncodedContent and to read raw byte[] content with response.Content.ReadAsByteArrayAsync().
  • Zeek2
    Zeek2 almost 5 years
    Useful, thanks. BTW It looks like the above technique for setting header-properties also works for the older (deprecated?), HttpWebRequest approach. e.g. myReq.Headers[HttpRequestHeader.Authorization] = $"Basic {credentials}";
  • Douglas Ferreira
    Douglas Ferreira over 4 years
    What are advantages of HttpClient over HttpWebRequest and WebClient beyond asyncronism? Why the last two has become legacy?
  • Evan Mulawski
    Evan Mulawski over 4 years
    @DouglasFerreira HttpClient and WebClient are higher-level wrappers around HttpWebRequest. The real question is when to use HttpClient as opposed to WebClient (or vice versa); this is best described in stackoverflow.com/questions/20530152/….
  • rkachach
    rkachach about 4 years
    Short and simple solution, I like it :)
  • elnaz jangi
    elnaz jangi almost 4 years
    Thank you very much for your complete and useful answer. I learned a whole new way by reading it, because I've just started learning C # programming.
  • Ohad Cohen
    Ohad Cohen almost 4 years
    I wrote this answer looking for http based logging solution, I guess some other people might find it usefull similarly.
  • Epirocks
    Epirocks over 3 years
    @AnKing there is scope for that to be server limits rather than the client sending it.
  • Danimal111
    Danimal111 over 3 years
    I have been working on this for too long. Soooo far from trivial... in Java I need about 6-8 lines.
  • kofifus
    kofifus over 3 years
  • T.Todua
    T.Todua over 2 years
  • Rony Tesler
    Rony Tesler about 2 years
    For method A - adding headers: client.DefaultRequestHeaders.Add("name", "value");
  • bbsimonbb
    bbsimonbb almost 2 years
    HttpClient has properties like BaseAddress and handy methods like CancelPendingRequests(). "Instantiat[ing] one HttpClient for your application's lifetime" would be a very brave thing to do. I believe the intention is to create 1 HttpClient per use case or group of use cases attacking a same origin, in a singleton scoped service class or something like that. So there's a whole bunch of complexity you didn't ask for and likely don't need. 3 cheers for OO.
  • obesechicken13
    obesechicken13 almost 2 years
    HttpClient is a bish to test since it has no interface stackoverflow.com/questions/36425008/… You need all kinds of workarounds to write a unit test for it, just a consideration
  • Evan Mulawski
    Evan Mulawski almost 2 years
    @obesechicken13 You would typically mock the underlying handler instead of HttpClient itself (see Moq.Contrib.HttpClient package).