Comment publier des données vers une URL spécifique à l'aide de WebClient en C #

319

Je dois utiliser "HTTP Post" avec WebClient pour publier des données sur une URL spécifique que j'ai.

Maintenant, je sais que cela peut être accompli avec WebRequest mais pour certaines raisons, je veux plutôt utiliser WebClient. Est-ce possible? Si oui, quelqu'un peut-il me montrer un exemple ou me diriger dans la bonne direction?

SolidSnake
la source

Réponses:

374

Je viens de trouver la solution et oui, c'était plus facile que je ne le pensais :)

voici donc la 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);
}

ça marche comme du charme :)

SolidSnake
la source
28
Un nitpick: il est préférable d'utiliser le HttpRequestHeader.ContentTypemembre d'énumération ici comme ceci web.Headers[HttpRequestHeader.ContentType]: p
Alex
12
Autre astuce, vous devez disposer du client Web correctement en utilisant .dispose ou l'idiome "using": using (WebClient wc = new WebClient ()) {// votre code ici}
Mikey Hogarth
1
@RobinVanPersi Je pense que ShikataGanai (Rafik bari) signifiait que l'autre réponse ( stackoverflow.com/a/13061805/1160796 ) est meilleure car elle gère l'encodage pour vous.
basher
3
@ alpsystems.com Les objets IDisposables doivent être correctement éliminés par le programmeur, soit en les encapsulant dans un using, soit en invoquant explicitement .Dispose (). Le garbage collector ne peut pas suivre les ressources non gérées, comme les gestionnaires de fichiers, les connexions aux bases de données, etc.
ccalboni
1
Pour étendre l'explication de @ ccalboni. Dans certains cas, le garbage collector nettoiera les ressources non gérées et similaires en appelant le destructeur (par exemple, WebClienthérite de Component, qui contient ~Component() {Dispose(false);}). Le problème est que le garbage collector peut prendre un temps arbitraire pour le faire, car il ne prend pas en compte les ressources non gérées lors des décisions de collecte. Les ressources de grande valeur doivent être nettoyées dès que possible. Par exemple, laisser ouvert un descripteur de fichier inutile pourrait empêcher le fichier d'être supprimé ou écrit par un autre code.
Brian
362

Il existe une méthode intégrée appelée UploadValues qui peut envoyer HTTP POST (ou tout type de méthodes HTTP) ET gère la construction du corps de la demande (concaténation des paramètres avec "&" et échappement des caractères par codage url) au format de données de formulaire approprié:

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);
}
Endy Tjahjono
la source
1
Et si je veux publier un modèle sur le contrôleur? Puis-je toujours utiliser reqparm.Add (chaîne, chaîne)?
Burak Karakuş
6
@ BurakKarakuş voulez-vous dire que vous voulez envoyer JSON dans le corps? Ensuite, vous souhaiterez peut-être utiliser WebClient.UploadString . N'oubliez pas d'ajouter Content-Type: application / json dans l'en-tête.
Endy Tjahjono
@EndyTjahjono: Comment puis-je publier des valeurs de bouton radio. Supposons que j'ai 3 boutons radio appartenant au même groupe.
Asad Refai
Comment obtenir le code de réponse? En-têtes de réponse? Dois-je analyser la réponse? Existe-t-il un moyen simple de le faire?
Jay Sullivan
AVERTISSEMENT . NameValueCollection donest permettent même .Ainsi clés peuvent conduire begaiviour bizarre
bh_earth0
40

En utilisant WebClient.UploadStringou WebClient.UploadDatavous pouvez POSTER facilement des données sur le serveur. Je vais montrer un exemple utilisant UploadData, puisque UploadString est utilisé de la même manière que 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);

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

Pranay Rana
la source
5
préférable d'utiliser: client.Encoding = System.Text.UTF8Encoding.UTF8; string varValue = Uri.EscapeDataString (valeur);
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));
}
Andrew
la source
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());            
  }
}
TeJ
la source
L'utilisation de la version asynchrone est une bonne chose, tout ce qui précède affiche et bloque l'exécution.
Juan
supprimer le double __ pour corriger wc__UploadStringCompleted
Joel Davis
1
Toutes les réponses ci-dessus fonctionneront bien dans les tests, mais dans une situation réelle avec un Internet médiocre, c'est une meilleure réponse.
Joel Davis
2

L'utilisation de simple client.UploadString(adress, content);fonctionne normalement, mais je pense qu'il ne faut pas oublier qu'un WebExceptionsera renvoyé si un code d'état HTTP réussi n'est pas renvoyé. Je le gère généralement comme ceci pour imprimer tout message d'exception renvoyé par le serveur distant:

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
la source
merci Ogglas. J'ai passé beaucoup de temps à trouver des erreurs et votre code me donne plus d'informations à corriger.
Kate
1

L'utilisation de webapiclient avec le modèle envoie une demande de paramètre json de sérialisation.

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

Méthode d'appel professionnel

    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
la source
0

Voici la réponse nette:

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
la source