.NET: moyen le plus simple d'envoyer POST avec des données et lire la réponse

180

À ma grande surprise, je ne peux rien faire d'aussi simple que cela, d'après ce que je peux dire, dans le .NET BCL:

byte[] response = Http.Post
(
    url: "http://dork.com/service",
    contentType: "application/x-www-form-urlencoded",
    contentLength: 32,
    content: "home=Cosby&favorite+flavor=flies"
);

Ce code hypothétique ci-dessus crée un HTTP POST, avec des données, et renvoie la réponse d'une Postméthode sur une classe statique Http.

Puisque nous nous retrouvons sans quelque chose d'aussi simple, quelle est la prochaine meilleure solution?

Comment envoyer un HTTP POST avec des données ET obtenir le contenu de la réponse?

AgileMeansDoAsLittleAsPossible
la source
En fait, cela a parfaitement fonctionné pour moi ... stickler.de/en/information/code-snippets
Jamie Tabone

Réponses:

289
   using (WebClient client = new WebClient())
   {

       byte[] response =
       client.UploadValues("http://dork.com/service", new NameValueCollection()
       {
           { "home", "Cosby" },
           { "favorite+flavor", "flies" }
       });

       string result = System.Text.Encoding.UTF8.GetString(response);
   }

Vous aurez besoin de ces éléments:

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

Si vous insistez sur l'utilisation d'une méthode / classe statique:

public static class Http
{
    public static byte[] Post(string uri, NameValueCollection pairs)
    {
        byte[] response = null;
        using (WebClient client = new WebClient())
        {
            response = client.UploadValues(uri, pairs);
        }
        return response;
    }
}

Puis simplement:

var response = Http.Post("http://dork.com/service", new NameValueCollection() {
    { "home", "Cosby" },
    { "favorite+flavor", "flies" }
});
Chris Hutchinson
la source
3
Si vous voulez plus de contrôle sur les en-têtes HTTP, vous pouvez essayer la même chose en utilisant HttpWebRequest et référence RFC2616 ( w3.org/Protocols/rfc2616/rfc2616.txt ). Les réponses de jball et BFree suivent cette tentative.
Chris Hutchinson
9
Cet exemple ne lit pas réellement la réponse, qui était une partie importante de la question originale!
Jon Watte
4
Pour lire la réponse, vous pouvez le faire string result = System.Text.Encoding.UTF8.GetString(response). C'est la question où j'ai trouvé la réponse.
jporcenaluk
Cette méthode ne fonctionnera plus si vous essayez de créer une application Windows Store pour Windows 8.1, car WebClient n'est pas trouvé dans System.Net. Au lieu de cela, utilisez la réponse de Ramesh et examinez l'utilisation de «attendre».
Stephen Wylie
2
Je vais ajouter ceci, mais vous devriez inclure le commentaire de @jporcenaluk sur la lecture de la réponse pour améliorer votre réponse.
Corgalore
78

En utilisant HttpClient: en ce qui concerne le développement d'applications Windows 8, je suis tombé sur ceci.

var client = new HttpClient();

var pairs = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("pqpUserName", "admin"),
        new KeyValuePair<string, string>("password", "test@123")
    };

var content = new FormUrlEncodedContent(pairs);

var response = client.PostAsync("youruri", content).Result;

if (response.IsSuccessStatusCode)
{


}
Ramesh
la source
6
Fonctionne également avec un Dictionary <String, String>, ce qui le rend plus propre.
Peter Hedberg
23
MEILLEURE RÉPONSE JAMAIS .. Oh merci les seigneurs, merci je vous aime. J'ai eu du mal .. 2 SEMAINES FREAKNG .. vous devriez voir tous mes messages. ARGHH ITS WORKING, YEHAAA <hugs>
Jimmyt1988
1
Notez que, si possible, vous ne devez pas utiliser .Resultavec les Asyncappels - utilisez awaitpour vous assurer que votre thread d'interface utilisateur ne sera pas bloqué. En outre, un simple new[]fonctionnera aussi bien que la liste; Le dictionnaire peut nettoyer le code, mais réduira certaines fonctionnalités HTTP.
Matt DeKrey
1
Aujourd'hui (2016), celle-ci est la meilleure réponse. HttpClient est plus récent que WebClient (la réponse la plus votée) et présente certains avantages: 1) Il a un bon modèle de programmation asynchrone sur lequel travaille Henrik F Nielson, qui est fondamentalement l'un des inventeurs de HTTP, et il a conçu l'API pour qu'il est facile pour vous de suivre la norme HTTP; 2) Il est pris en charge par le framework .Net 4.5, il a donc un certain niveau de prise en charge garanti pour l'avenir prévisible; 3) Il a également la version xcopyable / portable-framework de la bibliothèque si vous souhaitez l'utiliser sur d'autres plates-formes - .Net 4.0, Windows Phone etc ...
Luis Gouveia
comment envoyer des fichiers avec httpclient
Darshan Dave
47

Utilisez WebRequest . De Scott Hanselman :

public static string HttpPost(string URI, string Parameters) 
{
   System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
   req.Proxy = new System.Net.WebProxy(ProxyString, true);
   //Add these, as we're doing a POST
   req.ContentType = "application/x-www-form-urlencoded";
   req.Method = "POST";
   //We need to count how many bytes we're sending. 
   //Post'ed Faked Forms should be name=value&
   byte [] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
   req.ContentLength = bytes.Length;
   System.IO.Stream os = req.GetRequestStream ();
   os.Write (bytes, 0, bytes.Length); //Push it out there
   os.Close ();
   System.Net.WebResponse resp = req.GetResponse();
   if (resp== null) return null;
   System.IO.StreamReader sr = 
         new System.IO.StreamReader(resp.GetResponseStream());
   return sr.ReadToEnd().Trim();
}
jball
la source
32
private void PostForm()
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://dork.com/service");
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    string postData ="home=Cosby&favorite+flavor=flies";
    byte[] bytes = Encoding.UTF8.GetBytes(postData);
    request.ContentLength = bytes.Length;

    Stream requestStream = request.GetRequestStream();
    requestStream.Write(bytes, 0, bytes.Length);

    WebResponse response = request.GetResponse();
    Stream stream = response.GetResponseStream();
    StreamReader reader = new StreamReader(stream);

    var result = reader.ReadToEnd();
    stream.Dispose();
    reader.Dispose();
}
BGratuit
la source
12

Personnellement, je pense que l'approche la plus simple pour faire un message http et obtenir la réponse est d'utiliser la classe WebClient. Cette classe résume joliment les détails. Il y a même un exemple de code complet dans la documentation MSDN.

http://msdn.microsoft.com/en-us/library/system.net.webclient(VS.80).aspx

Dans votre cas, vous voulez la méthode UploadData (). (Encore une fois, un exemple de code est inclus dans la documentation)

http://msdn.microsoft.com/en-us/library/tdbbwh0a(VS.80).aspx

UploadString () fonctionnera probablement aussi, et il l'abstraction d'un niveau de plus.

http://msdn.microsoft.com/en-us/library/system.net.webclient.uploadstring(VS.80).aspx

David
la source
+1 Je soupçonne qu'il existe un tas de façons de faire cela dans le cadre.
jball
7

Je sais que c'est un vieux fil, mais j'espère que cela aidera quelqu'un.

public static void SetRequest(string mXml)
{
    HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp("http://dork.com/service");
    webRequest.Method = "POST";
    webRequest.Headers["SOURCE"] = "WinApp";

    // Decide your encoding here

    //webRequest.ContentType = "application/x-www-form-urlencoded";
    webRequest.ContentType = "text/xml; charset=utf-8";

    // You should setContentLength
    byte[] content = System.Text.Encoding.UTF8.GetBytes(mXml);
    webRequest.ContentLength = content.Length;

    var reqStream = await webRequest.GetRequestStreamAsync();
    reqStream.Write(content, 0, content.Length);

    var res = await httpRequest(webRequest);
}
Murali
la source
Qu'est-ce que httpRequest? Cela me donne une erreur "n'existe pas".
Rahul Khandelwal
6

Étant donné que d'autres réponses datent de quelques années, voici actuellement mes réflexions qui pourraient être utiles:

Le moyen le plus simple

private async Task<string> PostAsync(Uri uri, HttpContent dataOut)
{
    var client = new HttpClient();
    var response = await client.PostAsync(uri, dataOut);
    return await response.Content.ReadAsStringAsync();
    // For non strings you can use other Content.ReadAs...() method variations
}

Un exemple plus pratique

Souvent, nous avons affaire à des types connus et JSON, vous pouvez donc étendre cette idée avec un nombre illimité d'implémentations, telles que:

public async Task<T> PostJsonAsync<T>(Uri uri, object dtoOut)
{
    var content = new StringContent(JsonConvert.SerializeObject(dtoOut));
    content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

    var results = await PostAsync(uri, content); // from previous block of code

    return JsonConvert.DeserializeObject<T>(results); // using Newtonsoft.Json
}

Un exemple de la façon dont cela pourrait être appelé:

var dataToSendOutToApi = new MyDtoOut();
var uri = new Uri("https://example.com");
var dataFromApi = await PostJsonAsync<MyDtoIn>(uri, dataToSendOutToApi);
ToddBFisher
la source
5

Vous pouvez utiliser quelque chose comme ce pseudo code:

request = System.Net.HttpWebRequest.Create(your url)
request.Method = WebRequestMethods.Http.Post

writer = New System.IO.StreamWriter(request.GetRequestStream())
writer.Write("your data")
writer.Close()

response = request.GetResponse()
reader = New System.IO.StreamReader(response.GetResponseStream())
responseText = reader.ReadToEnd
paludarium
la source