.NET: Самый простой способ отправить POST с данными и прочитать ответ

179

К моему удивлению, я не могу сделать что-то почти такое же простое, как это, насколько я могу судить, в .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"
);

Этот гипотетический код выше создает HTTP POST с данными и возвращает ответ от Postметода статического класса Http.

Поскольку мы остались без чего-то такого простого, каково следующее лучшее решение?

Как отправить HTTP-сообщение с данными и получить ответ?

AgileMeansDoAsLittleAsPossible
источник
Это на самом деле отлично сработало для меня ... stickler.de/en/information/code-snippets/…
Джейми Табоне

Ответы:

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

Вам понадобится это включает в себя:

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

Если вы настаиваете на использовании статического метода / класса:

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

Тогда просто:

var response = Http.Post("http://dork.com/service", new NameValueCollection() {
    { "home", "Cosby" },
    { "favorite+flavor", "flies" }
});
Крис Хатчинсон
источник
3
Если вам нужен больший контроль над заголовками HTTP, вы можете попробовать это сделать, используя HttpWebRequest и ссылку RFC2616 ( w3.org/Protocols/rfc2616/rfc2616.txt ). Ответы от jball и BFree следуют этой попытке.
Крис Хатчинсон
9
Этот пример фактически не читает ответ, который был важной частью исходного вопроса!
Джон Уотт
4
Чтобы прочитать ответ, вы можете сделать string result = System.Text.Encoding.UTF8.GetString(response). Это вопрос, где я нашел ответ.
jporcenaluk
Этот метод больше не будет работать, если вы пытаетесь создать приложение для Магазина Windows для Windows 8.1, так как WebClient не найден в System.Net. Вместо этого используйте ответ Рамеша и посмотрите на использование «ожидайте».
Стивен Уайли
2
Я собираюсь добавить еще один, но вы должны добавить комментарий @jporcenaluk о прочтении ответа, чтобы улучшить свой ответ.
Corgalore
78

Использование HttpClient: с разработкой приложений для Windows 8 я столкнулся с этим.

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)
{


}
Рамеш
источник
6
Также работает со словарем <String, String>, что делает его чище.
Питер Хедберг
23
ЛУЧШИЙ ОТВЕТ. КОГДА-ЛИБО О, господа, спасибо, я люблю тебя. Я изо всех сил .. 2 FREAKNG НЕДЕЛИ .. вы должны увидеть все мои сообщения. ARGHH это работает, YEHAAA <обнимает>
Jimmyt1988
1
Обратите внимание, что, по возможности, вы не должны использовать .Resultс Asyncвызовами - используйте, awaitчтобы гарантировать, что ваш поток пользовательского интерфейса не будет блокироваться. Кроме того, простой new[]будет работать так же, как список; Словарь может очистить код, но уменьшит некоторые функции HTTP.
Matt DeKrey
1
В настоящее время (2016) это лучший ответ. HttpClient является более новым, чем WebClient (ответ с наибольшим количеством голосов) и имеет некоторые преимущества по сравнению с ним: 1) У него есть хорошая модель асинхронного программирования, над которой работает Хенрик Ф. Нильсон, который является одним из изобретателей HTTP, и он разработал API, чтобы он Вам легко следовать стандарту HTTP; 2) Он поддерживается .Net Framework 4.5, поэтому он имеет некоторый гарантированный уровень поддержки на обозримое будущее; 3) Он также имеет версию библиотеки xcopyable / portable-framework, если вы хотите использовать ее на других платформах - .Net 4.0, Windows Phone и т. Д.
Луис Гувейя,
как отправлять файлы с httpclient
Даршан Дэйв
47

Используйте WebRequest . Из Скотта Хансельмана :

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
источник
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
источник
12

Лично я думаю, что самый простой подход к созданию http-сообщения и получению ответа - использовать класс WebClient. Этот класс хорошо абстрагирует детали. В документации MSDN есть даже полный пример кода.

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

В вашем случае вам нужен метод UploadData (). (Опять же, пример кода включен в документацию)

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

UploadString (), вероятно, также будет работать и абстрагирует его от еще одного уровня.

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

Дэвид
источник
+1 Я подозреваю, что есть несколько способов сделать это в рамках.
Jball
7

Я знаю, что это старая тема, но надеюсь, что это поможет кому-то.

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
источник
Что такое httpRequest? Это дает мне ошибку "Не существует".
Рахул Хандельвал
6

С учетом того, что другим ответам уже несколько лет, в настоящее время здесь приведены мои мысли, которые могут быть полезны:

Самый простой способ

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
}

Более практичный пример

Часто мы имеем дело с известными типами и JSON, поэтому вы можете расширить эту идею с помощью любого числа реализаций, таких как:

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
}

Пример того, как это можно назвать:

var dataToSendOutToApi = new MyDtoOut();
var uri = new Uri("https://example.com");
var dataFromApi = await PostJsonAsync<MyDtoIn>(uri, dataToSendOutToApi);
ToddBFisher
источник
5

Вы можете использовать что-то вроде этого псевдокода:

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
ПАЛЮДАРИУМ
источник