15

I've seen so many implementations of sending an http post, and admittedly I don't fully understand the underlying details to know what's required.

What is the succinct/correct/canonical code to send an HTTP POST in C# .NET 3.5?

I want a generic method like

public string SendPost(string url, string data)

that can be added to a library and always used for posting data and will return the server response.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
User
  • 62,498
  • 72
  • 186
  • 247

3 Answers3

10

I believe that the simple version of this would be

var client = new WebClient();
return client.UploadString(url, data);

The System.Net.WebClient class has other useful methods that let you download or upload strings or a file, or bytes.

Unfortunately there are (quite often) situations where you have to do more work. The above for example doesn't take care of situations where you need to authenticate against a proxy server (although it will use the default proxy configuration for IE).

Also the WebClient doesn't support uploading of multiple files or setting (some specific) headers and sometimes you will have to go deeper and use the

System.Web.HttpWebRequest and System.Net.HttpWebResponse instead.

Patrick Klug
  • 14,056
  • 13
  • 71
  • 118
  • +1 for WebClient.UploadString ! regarding the limitations of WebClient, there's an easy workaround, see my answer – Thomas Levesque Sep 25 '09 at 00:33
  • A common thing I find myself doing is posting xml to a webservice. Is UploadString a good option for this scenario? What about the encoding? is it UTF-16? – User Sep 25 '09 at 07:07
  • you can set the Encoding to UFT-16 using the Encoding property of the WebClient. – Patrick Klug Sep 28 '09 at 02:47
  • I had some confusion about the fact that all strings in .NET are UTF-16. So you're saying that even though strings in .NET are UTF-16, when you set the encoding to, let's say UTF-7, it encodes the string into UTF-7 byte sequence before sending it to the server? – User Sep 28 '09 at 03:51
  • documentation on WebClient.Encoding property: "Gets and sets the Encoding used to upload and download strings." --- UploadString will internally upload bytes (what else!) and you will have to decide what Encoding you want to use for that. If you don't specify it it will use the Encoding.Default encoding – Patrick Klug Sep 28 '09 at 04:07
  • ok self, rtfm. From the method page (http://msdn.microsoft.com/en-us/library/0645045y.aspx) "Before uploading the string, this method converts it to a Byte array using the encoding specified in the Encoding property." – User Sep 28 '09 at 04:10
  • didn't see your comment when I was posting mine. Thanks – User Sep 28 '09 at 04:11
3

As others have said, WebClient.UploadString (or UploadData) is the way to go.

However the built-in WebClient has a major drawback : you have almost no control over the WebRequest that is used behind the scene (cookies, authentication, custom headers...). A simple way to solve that issue is to create your custom WebClient and override the GetWebRequest method. You can then customize the request before it is sent (you can do the same for the response by overridingGetWebResponse). Here is an example of a cookie-aware WebClient. It's so simple it makes me wonder why the built-in WebClient doesn't handle it out-of-the-box...

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
0

Compare:

// create a client object
using(System.Net.WebClient client = new System.Net.WebClient()) {
    // performs an HTTP POST
    client.UploadString(url, xml);  

}

to

string HttpPost (string uri, string parameters)
{ 
   // parameters: name1=value1&name2=value2 
   WebRequest webRequest = WebRequest.Create (uri);
   webRequest.ContentType = "application/x-www-form-urlencoded";
   webRequest.Method = "POST";
   byte[] bytes = Encoding.ASCII.GetBytes (parameters);
   Stream os = null;
   try
   { // send the Post
      webRequest.ContentLength = bytes.Length;   //Count bytes to send
      os = webRequest.GetRequestStream();
      os.Write (bytes, 0, bytes.Length);         //Send it
   }
   catch (WebException ex)
   {
      MessageBox.Show ( ex.Message, "HttpPost: Request error", 
         MessageBoxButtons.OK, MessageBoxIcon.Error );
   }
   finally
   {
      if (os != null)
      {
         os.Close();
      }
   }

   try
   { // get the response
      WebResponse webResponse = webRequest.GetResponse();
      if (webResponse == null) 
         { return null; }
      StreamReader sr = new StreamReader (webResponse.GetResponseStream());
      return sr.ReadToEnd ().Trim ();
   }
   catch (WebException ex)
   {
      MessageBox.Show ( ex.Message, "HttpPost: Response error", 
         MessageBoxButtons.OK, MessageBoxIcon.Error );
   }
   return null;
} // end HttpPost 

Why are people using/writing the latter?

User
  • 62,498
  • 72
  • 186
  • 247
  • 3
    Typically because we need to actually modify the request beyond what the WebClient class allows, in particular if you wish to change certain headers WebClient restricts the ability to do so, see http://msdn.microsoft.com/en-us/library/system.net.webclient.headers.aspx – RobV Sep 24 '09 at 15:55