349

I need to use "HTTP Post" with WebClient to post some data to a specific URL I have.

Now, I know this can be accomplished with WebRequest but for some reasons I want to use WebClient instead. Is that possible? If so, can someone show me some example or point me to the right direction?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Desolator
  • 22,411
  • 20
  • 73
  • 96

9 Answers9

401

I just found the solution and yea it was easier than I thought :)

so here is the solution:

string URI = "http://www.myurl.com/post.php";
string myParameters = "param1=value1&param2=value2&param3=value3";

using (WebClient wc = new WebClient())
{
    wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
    string HtmlResult = wc.UploadString(URI, myParameters);
}

it works like charm :)

Alberto León
  • 2,879
  • 2
  • 25
  • 24
Desolator
  • 22,411
  • 20
  • 73
  • 96
  • 30
    A nitpick: it's better to use [`HttpRequestHeader.ContentType`](http://msdn.microsoft.com/en-us/library/system.net.httprequestheader.aspx) enumeration member here like this `web.Headers[HttpRequestHeader.ContentType]` :p – Oleks Apr 12 '12 at 15:34
  • 13
    Another nitpick, you should dispose of the webclient properly using .dispose or the "using" idiom: using (WebClient wc = new WebClient()) { //your code here } – Mikey Hogarth May 16 '12 at 16:03
  • How are you saving the response into the string HtmlResult in this statement while UploadString(URI, myParameters); return type is void. string HtmlResult = wc.UploadString(URI, myParameters); – Ashish-BeJovial Feb 07 '14 at 06:47
  • @ShikataGaNai - you need to encode the values of the params and you are good to go. – Desolator Aug 13 '14 at 02:37
  • 1
    @RobinVanPersi I think ShikataGanai (Rafik bari) meant that the other answer (http://stackoverflow.com/a/13061805/1160796) is better because it handles the encoding for you. – basher Sep 04 '14 at 16:21
  • Why does it need "using"? The .NET garbage collection isn't good enough? Does the TCP-IP connection stay open or something like that? – Brian Birtle Nov 29 '15 at 10:58
  • 3
    @alpsystems.com IDisposable objects need to be properly disposed by programmer, either by wrapping within a using or by explicitly invoking .Dispose(). Garbage collector can't track unmanaged resources, like file handlers, database connections and so on – ccalboni Jun 01 '16 at 15:11
  • 1
    To extend @ccalboni's explanation. In some cases the garbage collector will clean up unmanaged resources and the like by calling the destructor (e.g., `WebClient` inherits from `Component`, which contains `~Component() {Dispose(false);}`). The problem is that the garbage collector may take an arbitrarily long time to do so, since it does not account for unmanaged resources when making collection decisions. High-value resources must be cleaned up as soon as possible. For example, leaving open an unneeded file handle could block the file from being deleted or written to by other code. – Brian Jan 10 '17 at 22:15
  • In asp.net web api, it doesn't work this way. The Post type API will not accept this request – Lali Jul 16 '18 at 08:38
  • I want to send the payload via post method, using UploadString sends that payload as content of the file. Can someone let me know what function to use to construct payload which have file properties like name etc – Susarla Nikhilesh Aug 23 '18 at 09:41
  • UploadString POSTS by default – Greg Sep 12 '18 at 19:29
  • How can i pass two different values to same parameter ? I tried something like this bit it did not work. using (WebClient wc = new WebClient()) { wc.QueryString.Add("wt", "json"); wc.QueryString.Add("fq", domain); wc.QueryString.Add("fq", orgs); wc.QueryString.Add("indent", "true"); // This line gives error - Bad Request - it appends comma after 1st parameter.how this can be resolved ? data = wc.UploadValues(uri, "POST", wc.QueryString); – Bokambo Oct 01 '18 at 04:21
  • What if the response from the server is not plain text? Like a PDF or image? – joym8 Mar 04 '20 at 15:31
  • For me, the correct way using GET was: webclient.DownloadString(string.Format("{0}?{1}", uri, parameters)); – Marcio Aug 22 '22 at 21:06
379

There is a built in method called UploadValues that can send HTTP POST (or any kind of HTTP methods) AND handles the construction of request body (concatenating parameters with "&" and escaping characters by url encoding) in proper form data format:

using(WebClient client = new WebClient())
{
    var reqparm = new System.Collections.Specialized.NameValueCollection();
    reqparm.Add("param1", "<any> kinds & of = ? strings");
    reqparm.Add("param2", "escaping is already handled");
    byte[] responsebytes = client.UploadValues("http://localhost", "POST", reqparm);
    string responsebody = Encoding.UTF8.GetString(responsebytes);
}
Samuel Katz
  • 24,066
  • 8
  • 71
  • 57
Endy Tjahjono
  • 24,120
  • 23
  • 83
  • 123
  • 1
    What if I want to post a model to controller? Can I still use reqparm.Add(string, string)? – Burak Karakuş Apr 13 '15 at 13:30
  • 8
    @BurakKarakuş do you mean you want to send JSON in the body? Then you may want to use [WebClient.UploadString](https://msdn.microsoft.com/en-us/library/d0d3595k(v=vs.110).aspx). Don't forget to add Content-Type: application/json in the header. – Endy Tjahjono Apr 17 '15 at 15:02
  • @EndyTjahjono : How can I post radio button values. Assume I have 3 radio buttons belong to same group. – Asad Refai Aug 04 '15 at 09:21
  • How do I get response code? Response headers? Do I have to parse the response? Is there an easy way to do that? – Jay Sullivan Nov 09 '16 at 19:02
  • WARNİNG . namevalueCollection donest allow same key .thus may lead weird begaiviour – bh_earth0 Jan 17 '17 at 21:49
  • I prefer this way because the parameters are **escaped automagically** – vcRobe Feb 13 '17 at 16:50
  • NameValueCollection will not work properly with arrays. If multiple parameters with the same key will be added, they will be joined and coma delimited. When posted, server will treat them as a single string. – jahu Sep 07 '18 at 15:42
  • This should be the selected answer IMHO. – MemphiZ Aug 13 '19 at 14:02
  • What if the response from the server is not plain text? Like a PDF or image? – joym8 Mar 04 '20 at 15:31
43

Using WebClient.UploadString or WebClient.UploadData you can POST data to the server easily. I’ll show an example using UploadData, since UploadString is used in the same manner as DownloadString.

byte[] bret = client.UploadData("http://www.website.com/post.php", "POST",
                System.Text.Encoding.ASCII.GetBytes("field1=value1&amp;field2=value2") );
 
string sret = System.Text.Encoding.ASCII.GetString(bret);

More: http://www.daveamenta.com/2008-05/c-webclient-usage/

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
28
string URI = "site.com/mail.php";
using (WebClient client = new WebClient())
{
    System.Collections.Specialized.NameValueCollection postData = 
        new System.Collections.Specialized.NameValueCollection()
       {
              { "to", emailTo },  
              { "subject", currentSubject },
              { "body", currentBody }
       };
    string pagesource = Encoding.UTF8.GetString(client.UploadValues(URI, postData));
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Andrew
  • 7,619
  • 13
  • 63
  • 117
23
//Making a POST request using WebClient.
Function()
{    
  WebClient wc = new WebClient();

  var URI = new Uri("http://your_uri_goes_here");

  //If any encoding is needed.
  wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";
  //Or any other encoding type.

  //If any key needed

  wc.Headers["KEY"] = "Your_Key_Goes_Here";

  wc.UploadStringCompleted += 
      new UploadStringCompletedEventHandler(wc_UploadStringCompleted);

  wc.UploadStringAsync(URI,"POST","Data_To_Be_sent");    
}

void wc__UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)    
{  
  try            
  {          
     MessageBox.Show(e.Result); 
     //e.result fetches you the response against your POST request.         
  }
  catch(Exception exc)         
  {             
     MessageBox.Show(exc.ToString());            
  }
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
TeJ
  • 450
  • 3
  • 6
5

Using simple client.UploadString(adress, content); normally works fine but I think it should be remembered that a WebException will be thrown if not a HTTP successful status code is returned. I usually handle it like this to print any exception message the remote server is returning:

try
{
    postResult = client.UploadString(address, content);
}
catch (WebException ex)
{
    String responseFromServer = ex.Message.ToString() + " ";
    if (ex.Response != null)
    {
        using (WebResponse response = ex.Response)
        {
            Stream dataRs = response.GetResponseStream();
            using (StreamReader reader = new StreamReader(dataRs))
            {
                responseFromServer += reader.ReadToEnd();
                _log.Error("Server Response: " + responseFromServer);
            }
        }
    }
    throw;
}
Ogglas
  • 62,132
  • 37
  • 328
  • 418
  • thank you, Ogglas. I spent a lot of time to find error and your code gives me more information to fix. – Kate Jul 10 '19 at 22:26
3

Using webapiclient with model send serialize json parameter request.

PostModel.cs

    public string Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public int Age { get; set; }

WebApiClient.cs

internal class WebApiClient  : IDisposable
  {

    private bool _isDispose;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public void Dispose(bool disposing)
    {
        if (!_isDispose)
        {

            if (disposing)
            {

            }
        }

        _isDispose = true;
    }

    private void SetHeaderParameters(WebClient client)
    {
        client.Headers.Clear();
        client.Headers.Add("Content-Type", "application/json");
        client.Encoding = Encoding.UTF8;
    }

    public async Task<T> PostJsonWithModelAsync<T>(string address, string data,)
    {
        using (var client = new WebClient())
        {
            SetHeaderParameters(client);
            string result = await client.UploadStringTaskAsync(address, data); //  method:
    //The HTTP method used to send the file to the resource. If null, the default is  POST 
            return JsonConvert.DeserializeObject<T>(result);
        }
    }
}

Business caller method

    public async Task<ResultDTO> GetResultAsync(PostModel model)
    {
        try
        {
            using (var client = new WebApiClient())
            {
                var serializeModel= JsonConvert.SerializeObject(model);// using Newtonsoft.Json;
                var response = await client.PostJsonWithModelAsync<ResultDTO>("http://www.website.com/api/create", serializeModel);
                return response;
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }

    }
Bora Karaca
  • 436
  • 5
  • 14
1

Most of the answers are old. Just wanted to share what worked for me. In the interest of doing things asynchronously i.e. to post data to specific URL using WebClient asynchronously in .NET 6.0 Preview 7, .NET Core and other versions can be done using WebClient.UploadStringTaskAsync Method.

Use namespace System.Net; and for a class ResponseType to capture the response from the server, we can use this method to POST data to a specific URL. Make sure to use the await keyword while calling this method

    public async Task<ResponseType> MyAsyncServiceCall()
    {
        try
        {
            var uri = new Uri("http://your_uri");
            var body= "param1=value1&param2=value2&param3=value3";

            using (var wc = new WebClient())
            {
                wc.Headers[HttpRequestHeader.Authorization] = "yourKey"; // Can be Bearer token, API Key etc.....
                wc.Headers[HttpRequestHeader.ContentType] = "application/json"; // Is about the payload/content of the current request or response. Do not use it if the request doesn't have a payload/ body.
                wc.Headers[HttpRequestHeader.Accept] = "application/json"; // Tells the server the kind of response the client will accept.
                wc.Headers[HttpRequestHeader.UserAgent] = "PostmanRuntime/7.28.3"; 
                
                string result = await wc.UploadStringTaskAsync(uri, body);
                return JsonConvert.DeserializeObject<ResponseType>(result);
            }
        }
        catch (Exception e)
        {
            throw new Exception(e.Message);
        }
    }
j4jada
  • 334
  • 1
  • 9
0

Here is the crisp answer:

public String sendSMS(String phone, String token) {
    WebClient webClient = WebClient.create(smsServiceUrl);

    SMSRequest smsRequest = new SMSRequest();
    smsRequest.setMessage(token);
    smsRequest.setPhoneNo(phone);
    smsRequest.setTokenId(smsServiceTokenId);

    Mono<String> response = webClient.post()
          .uri(smsServiceEndpoint)
          .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
          .body(Mono.just(smsRequest), SMSRequest.class)
          .retrieve().bodyToMono(String.class);

    String deliveryResponse = response.block();
    if (deliveryResponse.equalsIgnoreCase("success")) {
      return deliveryResponse;
    }
    return null;
}
KayV
  • 12,987
  • 11
  • 98
  • 148