.NET: la forma más sencilla de enviar POST con datos y leer la respuesta

179

Para mi sorpresa, no puedo hacer nada tan simple como esto, por lo que puedo decir, en .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"
);

Este código hipotético anterior realiza una POST HTTP, con datos, y devuelve la respuesta de un Postmétodo en una clase estática Http.

Dado que nos quedamos sin algo tan fácil, ¿cuál es la siguiente mejor solución?

¿Cómo envío un HTTP POST con datos Y obtengo el contenido de la respuesta?

AgileMeansDoAsLittleAsPossible
fuente
Esto realmente funcionó perfectamente para mí ... stickler.de/en/information/code-snippets/…
Jamie Tabone

Respuestas:

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

Necesitará estos incluye:

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

Si insiste en usar un método / clase estático:

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

Entonces simplemente:

var response = Http.Post("http://dork.com/service", new NameValueCollection() {
    { "home", "Cosby" },
    { "favorite+flavor", "flies" }
});
Chris Hutchinson
fuente
3
Si desea más control sobre los encabezados HTTP, puede intentar lo mismo utilizando HttpWebRequest y hacer referencia a RFC2616 ( w3.org/Protocols/rfc2616/rfc2616.txt ). Las respuestas de jball y BFree siguen ese intento.
Chris Hutchinson el
9
¡Este ejemplo en realidad no lee la respuesta, que era una parte importante de la pregunta original!
Jon Watte
44
Para leer la respuesta, puedes hacerlo string result = System.Text.Encoding.UTF8.GetString(response). Esta es la pregunta donde encontré la respuesta.
jporcenaluk
Este método ya no funcionará si está intentando crear una aplicación de la Tienda Windows para Windows 8.1, ya que WebClient no se encuentra en System.Net. En cambio, use la respuesta de Ramesh y analice el uso de "esperar".
Stephen Wylie
2
Voy a hacer más uno, pero debes incluir un comentario de @jporcenaluk sobre leer la respuesta para mejorar tu respuesta.
Corgalore
78

Usando HttpClient: en lo que respecta al desarrollo de aplicaciones de Windows 8, me encontré con esto.

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
fuente
66
También funciona con un Dictionary <String, String>, que lo hace más limpio.
Peter Hedberg
23
MEJOR RESPUESTA NUNCA .. Oh, gracias a los señores, gracias Te amo. He estado luchando ... 2 SEMANAS FREAKNG ... deberías ver todas mis publicaciones. ARGHH SU TRABAJO, YEHAAA <abrazos>
Jimmyt1988
1
Tenga en cuenta que, cuando sea posible, no debe usarlo .Resultcon Asyncllamadas, use awaitpara asegurarse de que su hilo de UI no se bloqueará. Además, un simple new[]funcionará tan bien como la Lista; El diccionario puede limpiar el código, pero reducirá algunas funciones HTTP.
Matt DeKrey
1
Hoy en día (2016) esta es la mejor respuesta. HttpClient es más nuevo que WebClient (la respuesta más votada) y tiene algunos beneficios al respecto: 1) Tiene un buen modelo de programación asincrónica en el que trabaja Henrik F Nielson, que es básicamente uno de los inventores de HTTP, y diseñó la API para que es fácil para usted seguir el estándar HTTP; 2) Es compatible con .Net Framework 4.5, por lo que tiene cierto nivel garantizado de soporte para el futuro previsible; 3) También tiene la versión xcopyable / portable-framework de la biblioteca si desea usarla en otras plataformas - .Net 4.0, Windows Phone, etc.
Luis Gouveia
cómo enviar archivos con httpclient
Darshan Dave
47

Use 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
fuente
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();
}
BFree
fuente
12

Personalmente, creo que el enfoque más simple para hacer una publicación http y obtener la respuesta es usar la clase WebClient. Esta clase resume muy bien los detalles. Incluso hay un ejemplo de código completo en la documentación de MSDN.

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

En su caso, desea el método UploadData (). (Nuevamente, se incluye una muestra de código en la documentación)

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

UploadString () probablemente también funcionará, y lo abstrae un nivel más.

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

David
fuente
+1 Sospecho que hay muchas maneras de hacer esto en el marco.
jball el
7

Sé que este es un hilo viejo, pero espero que ayude a alguien.

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
fuente
¿Qué es httpRequest? Me está dando un error "No existe".
Rahul Khandelwal
6

Dado que otras respuestas tienen unos pocos años, actualmente aquí están mis pensamientos que pueden ser útiles:

La manera más 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 ejemplo mas practico

A menudo estamos tratando con tipos conocidos y JSON, por lo que puede ampliar aún más esta idea con cualquier cantidad de implementaciones, como:

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 ejemplo de cómo se podría llamar esto:

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

Puede usar algo como este pseudocódigo:

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
fuente