我如何能使一个HTTP POST请求和发送数据的主体?


当前回答

在. net Core中,你可以用下面的代码进行POST调用。在这里,我为这段代码添加了一些额外的特性,这样您就可以让您的代码在代理后工作,如果有网络凭据的话。

在这里我还提到,您可以更改消息的编码。

HttpClient client = GetHttpClient(_config);

if (headers != null)
{
    foreach (var header in headers)
    {
        client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value);
    }
}

client.BaseAddress = new Uri(baseAddress);

Encoding encoding = Encoding.UTF8;

var result = await client.PostAsync(url, new StringContent(body, encoding, "application/json")).ConfigureAwait(false);
if (result.IsSuccessStatusCode)
{
    return new RequestResponse { severity = "Success", httpResponse = result.Content.ReadAsStringAsync().Result, StatusCode = result.StatusCode };
}
else
{
    return new RequestResponse { severity = "failure", httpResponse = result.Content.ReadAsStringAsync().Result, StatusCode = result.StatusCode };
}


public HttpClient GetHttpClient(IConfiguration _config)
{
    bool ProxyEnable = Convert.ToBoolean(_config["GlobalSettings:ProxyEnable"]);

    HttpClient client = null;
    if (!ProxyEnable)
    {
        client = new HttpClient();
    }
    else
    {
        string ProxyURL = _config["GlobalSettings:ProxyURL"];
        string ProxyUserName = _config["GlobalSettings:ProxyUserName"];
        string ProxyPassword = _config["GlobalSettings:ProxyPassword"];
        string[] ExceptionURL = _config["GlobalSettings:ExceptionURL"].Split(';');
        bool BypassProxyOnLocal = Convert.ToBoolean(_config["GlobalSettings:BypassProxyOnLocal"]);
        bool UseDefaultCredentials = Convert.ToBoolean(_config["GlobalSettings:UseDefaultCredentials"]);

        WebProxy proxy = new WebProxy
        {
            Address = new Uri(ProxyURL),
            BypassProxyOnLocal = BypassProxyOnLocal,
            UseDefaultCredentials = UseDefaultCredentials,
            BypassList = ExceptionURL,
            Credentials = new NetworkCredential(ProxyUserName, ProxyPassword)
        };

        HttpClientHandler handler = new HttpClientHandler { Proxy = proxy };
        client = new HttpClient(handler, true);
    }
    return client;
}

其他回答

简单的GET请求

using System.Net;

...

using (var wb = new WebClient())
{
    var response = wb.DownloadString(url);
}

简单的POST请求

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

...

using (var wb = new WebClient())
{
    var data = new NameValueCollection();
    data["username"] = "myUser";
    data["password"] = "myPassword";

    var response = wb.UploadValues(url, "POST", data);
    string responseInString = Encoding.UTF8.GetString(response);
}

c# . net

    using System.Net.Http;
    
    private static readonly HttpClient httpClient = new HttpClient();

//POST    
    var values = new Object();
    values[0] = "Value1";
    values[2] = "Value2";
    values[n] = "ValueN";

    var content = new FormUrlEncodedContent(values);
    var response = await httpClient.PostAsync("URL", content);
    var responseString = await response.Content.ReadAsStringAsync();

    

//GET
 var response = await httpClient.GetStringAsync("URL");

到目前为止,我找到了简单的解决方案(一行程序,没有错误检查,没有等待响应):

(new WebClient()).UploadStringAsync(new Uri(Address), dataString);‏

请谨慎使用!

这是一个完整的JSON格式发送/接收数据的工作示例,我使用Visual Studio 2013 Express Edition:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;

namespace ConsoleApplication1
{
    class Customer
    {
        public string Name { get; set; }
        public string Address { get; set; }
        public string Phone { get; set; }
    }

    public class Program
    {
        private static readonly HttpClient _Client = new HttpClient();
        private static JavaScriptSerializer _Serializer = new JavaScriptSerializer();

        static void Main(string[] args)
        {
            Run().Wait();
        }

        static async Task Run()
        {
            string url = "http://www.example.com/api/Customer";
            Customer cust = new Customer() { Name = "Example Customer", Address = "Some example address", Phone = "Some phone number" };
            var json = _Serializer.Serialize(cust);
            var response = await Request(HttpMethod.Post, url, json, new Dictionary<string, string>());
            string responseText = await response.Content.ReadAsStringAsync();

            List<YourCustomClassModel> serializedResult = _Serializer.Deserialize<List<YourCustomClassModel>>(responseText);

            Console.WriteLine(responseText);
            Console.ReadLine();
        }

        /// <summary>
        /// Makes an async HTTP Request
        /// </summary>
        /// <param name="pMethod">Those methods you know: GET, POST, HEAD, etc...</param>
        /// <param name="pUrl">Very predictable...</param>
        /// <param name="pJsonContent">String data to POST on the server</param>
        /// <param name="pHeaders">If you use some kind of Authorization you should use this</param>
        /// <returns></returns>
        static async Task<HttpResponseMessage> Request(HttpMethod pMethod, string pUrl, string pJsonContent, Dictionary<string, string> pHeaders)
        {
            var httpRequestMessage = new HttpRequestMessage();
            httpRequestMessage.Method = pMethod;
            httpRequestMessage.RequestUri = new Uri(pUrl);
            foreach (var head in pHeaders)
            {
                httpRequestMessage.Headers.Add(head.Key, head.Value);
            }
            switch (pMethod.Method)
            {
                case "POST":
                    HttpContent httpContent = new StringContent(pJsonContent, Encoding.UTF8, "application/json");
                    httpRequestMessage.Content = httpContent;
                    break;

            }

            return await _Client.SendAsync(httpRequestMessage);
        }
    }
}

为什么这不是完全无关紧要的?执行请求并不是处理结果。而且似乎还涉及到一些。net Bug——参见HttpClient中的Bug。GetAsync应该抛出WebException,而不是TaskCanceledException

我最终得到了这样的代码:

static async Task<(bool Success, WebExceptionStatus WebExceptionStatus, HttpStatusCode? HttpStatusCode, string ResponseAsString)> HttpRequestAsync(HttpClient httpClient, string url, string postBuffer = null, CancellationTokenSource cts = null) {
    try {
        HttpResponseMessage resp = null;

        if (postBuffer is null) {
            resp = cts is null ? await httpClient.GetAsync(url) : await httpClient.GetAsync(url, cts.Token);

        } else {
            using (var httpContent = new StringContent(postBuffer)) {
                resp = cts is null ? await httpClient.PostAsync(url, httpContent) : await httpClient.PostAsync(url, httpContent, cts.Token);
            }
        }

        var respString = await resp.Content.ReadAsStringAsync();
        return (resp.IsSuccessStatusCode, WebExceptionStatus.Success, resp.StatusCode, respString);

    } catch (WebException ex) {
        WebExceptionStatus status = ex.Status;
        if (status == WebExceptionStatus.ProtocolError) {
            // Get HttpWebResponse so that you can check the HTTP status code.
            using (HttpWebResponse httpResponse = (HttpWebResponse)ex.Response) {
                return (false, status, httpResponse.StatusCode, httpResponse.StatusDescription);
            }
        } else {
            return (false, status, null, ex.ToString());
        }

    // https://devblogs.microsoft.com/dotnet/net-5-new-networking-improvements/
    } catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) {
        return (false, ex.ToString(), null, WebExceptionStatus.Timeout);

    } catch (TaskCanceledException ex) {
        return (false, ex.ToString(), null, WebExceptionStatus.RequestCanceled);

    } catch (Exception ex) {
        return (false, WebExceptionStatus.UnknownError, null, ex.ToString());
    }
}

这将根据postBuffer是否为空来执行GET或POST操作。

如果Success为true,响应将在ResponseAsString中。

如果Success为false,你可以检查WebExceptionStatus, HttpStatusCode和ResponseAsString,看看哪里出了问题。