Come pubblicare dati su URL specifico utilizzando WebClient in C #


319

Devo utilizzare "HTTP Post" con WebClient per pubblicare alcuni dati su un URL specifico che possiedo.

Ora, so che questo può essere realizzato con WebRequest, ma per alcuni motivi voglio invece utilizzare WebClient. È possibile? In tal caso, qualcuno può mostrarmi qualche esempio o indicarmi la giusta direzione?

Risposte:


374

Ho appena trovato la soluzione e sì, è stato più facile di quanto pensassi :)

quindi ecco la soluzione:

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);
}

funziona come un incanto :)


28
A nitpick: è meglio usare il HttpRequestHeader.ContentTypemembro di enumerazione qui in questo modo web.Headers[HttpRequestHeader.ContentType]: p
Alex

12
Un altro pignolo, dovresti smaltire correttamente il client web usando .dispose o il linguaggio "using": using (WebClient wc = new WebClient ()) {// qui il tuo codice}
Mikey Hogarth

1
@RobinVanPersi Penso che ShikataGanai (Rafik bari) significasse che l'altra risposta ( stackoverflow.com/a/13061805/1160796 ) è migliore perché gestisce la codifica per te.
basher

3
@ alpsystems.com Gli oggetti IDisposable devono essere correttamente disposti dal programmatore, avvolgendo all'interno di un utilizzo o invocando esplicitamente .Dispose (). Garbage Collector non è in grado di tenere traccia delle risorse non gestite, come i gestori di file, le connessioni al database e così via
ccalboni,

1
Per estendere la spiegazione di @ccalboni. In alcuni casi il Garbage Collector pulirà risorse non gestite e simili chiamando il distruttore (ad esempio, WebClienteredita da Component, che contiene ~Component() {Dispose(false);}). Il problema è che il garbage collector potrebbe impiegare un tempo arbitrariamente lungo per farlo, poiché non tiene conto delle risorse non gestite quando si prendono decisioni sulla raccolta. Le risorse di alto valore devono essere ripulite il prima possibile. Ad esempio, lasciare aperto un handle di file non necessario potrebbe impedire che il file venga eliminato o scritto da un altro codice.
Brian

362

Esiste un metodo integrato chiamato UploadValues che può inviare HTTP POST (o qualsiasi tipo di metodo HTTP) E gestisce la costruzione del corpo della richiesta (concatenando i parametri con "&" e sfuggendo ai caratteri mediante la codifica dell'URL) nel formato di dati del modulo appropriato:

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);
}

1
Cosa succede se desidero pubblicare un modello sul controller? Posso ancora usare reqparm.Add (stringa, stringa)?
Burak Karakuş,

6
@ BurakKarakuş vuoi dire che vuoi inviare JSON nel corpo? Quindi potresti voler usare WebClient.UploadString . Non dimenticare di aggiungere Content-Type: application / json nell'intestazione.
Endy Tjahjono,

@EndyTjahjono: come posso pubblicare i valori dei pulsanti di opzione. Supponiamo che io abbia 3 pulsanti di opzione appartenenti allo stesso gruppo.
Asad Refai,

Come ottengo il codice di risposta? Header di risposta? Devo analizzare la risposta? C'è un modo semplice per farlo?
Jay Sullivan,

AVVERTIMENTO . namevalueCollection donest consentire la stessa chiave .thus può condurre a begaiviour strano
bh_earth0

40

Utilizzando WebClient.UploadStringo WebClient.UploadDataè possibile inviare facilmente i dati al server. Mostrerò un esempio usando UploadData, poiché UploadString viene utilizzato allo stesso modo di 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);

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


5
meglio usare: client.Encoding = System.Text.UTF8Encoding.UTF8; string varValue = Uri.EscapeDataString (valore);
Yuriy Vikulov,

23
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));
}

21
//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());            
  }
}

L'utilizzo della versione asincrona è positivo e tutte le operazioni precedenti inviano e bloccano l'esecuzione.
Juan,

rimuovi doppio __ per correggere wc__UploadStringCompleted
Joel Davis

1
Tutte le risposte sopra funzioneranno bene nei test, ma in una situazione di vita reale con Internet scadente questa è una risposta migliore.
Joel Davis,

2

L'utilizzo di simple client.UploadString(adress, content);normalmente funziona WebExceptioncorrettamente, ma penso che dovrebbe essere ricordato che verrà lanciato a se non viene restituito un codice di stato HTTP riuscito. Di solito lo gestisco in questo modo per stampare qualsiasi messaggio di eccezione restituito dal server remoto:

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;
}

grazie Ogglas. Ho impiegato molto tempo a trovare l'errore e il tuo codice mi fornisce ulteriori informazioni da correggere.
Kate,

1

Utilizzando webapiclient con il modello invia serializzare la richiesta di parametro json.

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);
        }
    }
}

Metodo di chiamata aziendale

    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);
        }

    }

0

Ecco la risposta chiara:

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.