.NET: maneira mais simples de enviar POST com dados e resposta de leitura

179

Para minha surpresa, não posso fazer nada tão simples quanto isso, pelo que posso dizer, no .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 acima cria um HTTP POST, com dados e retorna a resposta de um Postmétodo em uma classe estática Http.

Como ficamos sem algo tão fácil, qual é a próxima melhor solução?

Como envio um HTTP POST com dados E obtenho o conteúdo da resposta?

AgileMeansDoAsLittleAsPossible
fonte
Na verdade, isso funcionou perfeitamente para mim ... stickler.de/en/information/code-snippets/… #
9338 Jamie Tabone

Respostas:

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

Você precisará destes itens:

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

Se você insistir em usar um método / classe 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;
    }
}

Então simplesmente:

var response = Http.Post("http://dork.com/service", new NameValueCollection() {
    { "home", "Cosby" },
    { "favorite+flavor", "flies" }
});
Chris Hutchinson
fonte
3
Se você deseja ter mais controle sobre os cabeçalhos HTTP, tente o mesmo usando HttpWebRequest e faça referência à RFC2616 ( w3.org/Protocols/rfc2616/rfc2616.txt ). As respostas do jball e do BFree seguem essa tentativa.
Chris Hutchinson
9
Este exemplo não lê a resposta, que foi uma parte importante da pergunta original!
23913 Jon Watte
4
Para ler a resposta, você pode fazer string result = System.Text.Encoding.UTF8.GetString(response). Esta é a pergunta onde eu encontrei a resposta.
jporcenaluk
Esse método não funcionará mais se você estiver tentando criar um aplicativo da Windows Store para Windows 8.1, pois o WebClient não é encontrado no System.Net. Em vez disso, use a resposta de Ramesh e verifique o uso de "aguardar".
Stephen Wylie
2
Vou acrescentar mais um, mas você deve incluir o comentário @jporcenaluk sobre a leitura da resposta para melhorar sua resposta.
Corgalore 26/08/14
78

Usando o HttpClient: no que diz respeito ao desenvolvimento de aplicativos do Windows 8, deparei-me com isso.

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
fonte
6
Também funciona com um dicionário <String, String>, que o torna mais limpo.
Peter Hedberg
23
MELHOR RESPOSTA DE SEMPRE .. Oh, obrigado aos senhores, obrigado, eu te amo. Eu tenho lutado .. 2 SEMANAS FREAKNG .. você deve ver todas as minhas postagens. Arghh seu trabalho, YEHAAA <abraços>
Jimmyt1988
1
Observe que, quando possível, você não deve usar .Resultcom Asyncchamadas - use awaitpara garantir que o encadeamento da interface do usuário não seja bloqueado. Além disso, um simples new[]funcionará tão bem quanto a Lista; O dicionário pode limpar o código, mas reduzirá algumas funcionalidades HTTP.
precisa saber é o seguinte
1
Atualmente (2016) essa é a melhor resposta. O HttpClient é mais recente que o WebClient (resposta mais votada) e possui alguns benefícios: 1) Ele possui um bom modelo de programação assíncrona sendo trabalhado por Henrik F Nielson, que é basicamente um dos inventores do HTTP, e ele projetou a API para é fácil seguir o padrão HTTP; 2) É suportado pelo .Net framework 4.5, portanto, possui algum nível garantido de suporte no futuro próximo; 3) Ele também tem a versão xcopyable /-estrutura portátil da biblioteca se você quiser usá-lo em outras plataformas - .Net 4.0, Windows Phone etc ...
Luis Gouveia
como enviar arquivos com 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
fonte
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
fonte
12

Pessoalmente, acho que a abordagem mais simples para fazer uma postagem http e obter a resposta é usar a classe WebClient. Esta classe abstrai bem os detalhes. Existe até um exemplo de código completo na documentação do MSDN.

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

No seu caso, você deseja o método UploadData (). (Novamente, um exemplo de código está incluído na documentação)

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

O UploadString () provavelmente também funcionará e o abstrai por mais um nível.

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

David
fonte
+1 Suspeito que haja várias maneiras de fazer isso na estrutura.
jball
7

Eu sei que esse é um tópico antigo, mas espero que ajude alguém.

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
fonte
O que é httpRequest? Está me dando um erro "Não existe".
Rahul Khandelwal
6

Dado que outras respostas têm alguns anos, atualmente, aqui estão meus pensamentos que podem ser úteis:

Maneira mais simples

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
}

Um exemplo mais prático

Muitas vezes, estamos lidando com tipos conhecidos e JSON, para que você possa estender ainda mais essa ideia com qualquer número de implementações, 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
}

Um exemplo de como isso pode ser chamado:

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

Você pode usar algo como este pseudo-có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
fonte