我如何能使一个HTTP POST请求和发送数据的主体?
当前回答
这个解决方案只使用标准的. net调用。
测试:
在企业WPF应用程序中使用。使用async/await来避免阻塞UI。 兼容。net 4.5+。 在没有参数的情况下进行测试(在幕后需要一个“GET”)。 使用参数进行测试(需要幕后的“POST”)。 使用标准的网页(如谷歌)进行测试。 使用内部基于java的web服务进行测试。
参考:
// Add a Reference to the assembly System.Web
代码:
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
private async Task<WebResponse> CallUri(string url, TimeSpan timeout)
{
var uri = new Uri(url);
NameValueCollection rawParameters = HttpUtility.ParseQueryString(uri.Query);
var parameters = new Dictionary<string, string>();
foreach (string p in rawParameters.Keys)
{
parameters[p] = rawParameters[p];
}
var client = new HttpClient { Timeout = timeout };
HttpResponseMessage response;
if (parameters.Count == 0)
{
response = await client.GetAsync(url);
}
else
{
var content = new FormUrlEncodedContent(parameters);
string urlMinusParameters = uri.OriginalString.Split('?')[0]; // Parameters always follow the '?' symbol.
response = await client.PostAsync(urlMinusParameters, content);
}
var responseString = await response.Content.ReadAsStringAsync();
return new WebResponse(response.StatusCode, responseString);
}
private class WebResponse
{
public WebResponse(HttpStatusCode httpStatusCode, string response)
{
this.HttpStatusCode = httpStatusCode;
this.Response = response;
}
public HttpStatusCode HttpStatusCode { get; }
public string Response { get; }
}
不带参数调用(在幕后使用“GET”):
var timeout = TimeSpan.FromSeconds(300);
WebResponse response = await this.CallUri("http://www.google.com/", timeout);
if (response.HttpStatusCode == HttpStatusCode.OK)
{
Console.Write(response.Response); // Print HTML.
}
使用参数调用(在幕后使用“POST”):
var timeout = TimeSpan.FromSeconds(300);
WebResponse response = await this.CallUri("http://example.com/path/to/page?name=ferret&color=purple", timeout);
if (response.HttpStatusCode == HttpStatusCode.OK)
{
Console.Write(response.Response); // Print HTML.
}
其他回答
为什么这不是完全无关紧要的?执行请求并不是处理结果。而且似乎还涉及到一些。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,看看哪里出了问题。
到目前为止,我找到了简单的解决方案(一行程序,没有错误检查,没有等待响应):
(new WebClient()).UploadStringAsync(new Uri(Address), dataString);
请谨慎使用!
执行HTTP GET和POST请求有几种方法:
方法A: HttpClient(首选)
支持。net Framework 4.5+, . net Standard 1.1+, . net Core 1.0+。
它是目前首选的方法,并且是异步的和高性能的。在大多数情况下使用内置版本,但对于非常老的平台,有一个NuGet包。
using System.Net.Http;
设置
建议为应用程序的生命周期实例化一个HttpClient并共享它,除非您有特定的理由不这样做。
private static readonly HttpClient client = new HttpClient();
请参阅HttpClientFactory以获得依赖注入解决方案。
帖子 var values = new Dictionary<string, string> { {"thing1", "hello"}, {"thing2", "world"} }; var content = new FormUrlEncodedContent(values); var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content); var responseString =等待response.Content.ReadAsStringAsync(); 得到 var responseString = await client.GetStringAsync("http://www.example.com/recepticle.aspx");
方法B:第三方库
休息夏普
帖子 var client = new RestClient("http://example.com"); / /客户端。Authenticator =新的HttpBasicAuthenticator(用户名,密码); var request = new RestRequest("resource/{id}"); 请求。AddParameter(“thing1”、“你好”); 请求。AddParameter(“事件”、“世界”); 请求。AddHeader(“标题”、“价值”); 请求。AddFile(“文件”,路径); var response = client.Post(请求); var content = response.Content;//原始内容为字符串 var response2 = client.Post<Person>(request); var name = response2.Data.Name;
Flurl。Http
它是一个更新的库,拥有一个流畅的API,测试助手,在底层使用HttpClient,并且是可移植的。它可以通过NuGet获得。
using Flurl.Http;
帖子 var responseString = await“http://www.example.com/recepticle.aspx” .PostUrlEncodedAsync(new {thing1 = "hello", thing2 = "world"}) .ReceiveString (); 得到 var responseString = await“http://www.example.com/recepticle.aspx” .GetStringAsync ();
方法C: HttpWebRequest(不推荐用于新工作)
支持。net Framework 1.1+, . net Standard 2.0+, . net Core 1.0+。在。net Core中,它主要是为了兼容性——它包装了HttpClient,性能较差,并且不会获得新的特性。
using System.Net;
using System.Text; // For class Encoding
using System.IO; // For StreamReader
发布 var request = (HttpWebRequest)WebRequest.Create(“http://www.example.com/recepticle.aspx”); var postData = “thing1=” + Uri.EscapeDataString(“hello”); postData += “&thing2=” + Uri.EscapeDataString(“world”); var data = Encoding.ASCII.GetBytes(postData); 请求。方法 =“开机自检”; 请求。ContentType = “application/x-www-form-urlencoded”; 请求。内容长度 = 数据。长度; 使用 (var 流 = 请求。GetRequestStream()) { 流。写入(数据, 0, 数据.长度); } var response = (HttpWebResponse)request.获取响应(); var responseString = new StreamReader(response.GetResponseStream())。ReadToEnd(); 获取 var request = (HttpWebRequest)WebRequest.Create(“http://www.example.com/recepticle.aspx”); var response = (HttpWebResponse)request.获取响应(); var responseString = new StreamReader(response.GetResponseStream())。ReadToEnd();
方法D: WebClient(不推荐新作品)
这是一个HttpWebRequest的包装器。与HttpClient比较。
支持。NET Framework 1.1+, NET Standard 2.0+和。NET Core 2.0+。
在某些情况下…NET Framework 4.5-4.8),如果你需要同步地做一个HTTP请求,WebClient仍然可以使用。
using System.Net;
using System.Collections.Specialized;
帖子 使用(var client = new WebClient()) { var values = new NameValueCollection(); 值["thing1"] = "hello"; Values ["thing2"] = "world"; var response = client.UploadValues("http://www.example.com/recepticle.aspx", values); var responseString = Encoding.Default.GetString(response); } 得到 使用(var client = new WebClient()) { var responseString = client.DownloadString("http://www.example.com/recepticle.aspx"); }
这里有一些非常好的答案。让我发布一种不同的方法来设置你的头部与WebClient()。我还将向您展示如何设置API键。
var client = new WebClient();
string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(userName + ":" + passWord));
client.Headers[HttpRequestHeader.Authorization] = $"Basic {credentials}";
//If you have your data stored in an object serialize it into json to pass to the webclient with Newtonsoft's JsonConvert
var encodedJson = JsonConvert.SerializeObject(newAccount);
client.Headers.Add($"x-api-key:{ApiKey}");
client.Headers.Add("Content-Type:application/json");
try
{
var response = client.UploadString($"{apiurl}", encodedJson);
//if you have a model to deserialize the json into Newtonsoft will help bind the data to the model, this is an extremely useful trick for GET calls when you have a lot of data, you can strongly type a model and dump it into an instance of that class.
Response response1 = JsonConvert.DeserializeObject<Response>(response);
简单的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);
}
推荐文章
- Linq-to-Entities Join vs GroupJoin
- 为什么字符串类型的默认值是null而不是空字符串?
- 在list中获取不同值的列表
- 组合框:向项目添加文本和值(无绑定源)
- 我如何捕捉Ajax查询后错误?
- AutoMapper:“忽略剩下的?”
- 如何为ASP.net/C#应用程序配置文件值中的值添加&号
- 从System.Drawing.Bitmap中加载WPF BitmapImage
- 如何找出一个文件存在于c# / .NET?
- 为什么更快地检查字典是否包含键,而不是捕捉异常,以防它不?
- [DataContract]的命名空间
- string. isnullorempty (string) vs. string. isnullowhitespace (string)
- 完全外部连接
- 如何使用。net 4运行时运行PowerShell ?
- 在foreach循环中编辑字典值