C#HttpClient教程展示了如何在C#中使用HttpClient创建HTTP请求。在示例中,我们创建了简单的GET和POST请求。
超文本传输协议(HTTP)是分布式协作超媒体信息系统的应用协议。HTTP是万维网数据通信的基础。
HttpClient
是一个基类,用于从URI标识的资源发送HTTP请求和接收HTTP响应。
HTTP请求方式
HTTP定义了一组请求方法来指示要对给定资源执行的所需操作。
- GET-请求指定资源的表示
- HEAD-与GET请求相同,但没有响应主体
- POST-将数据发送到资源,通常会导致状态更改或副作用
- PUT-创建资源或更新现有资源
- DELETE-删除指定资源
- CONNECT-双向启动与请求资源的通信
- OPTION-描述目标资源的通信选项
- TRACE-返回完整的HTTP请求用于调试目的
- PATCH-执行对资源的部分修改
C#HttpClient状态码
HTTP响应状态代码指示特定HTTP请求是否已成功完成。响应分为五类:
- 信息响应(100-199)
- 成功响应(200-299)
- 重定向(300-399)
- 客户端错误(400-499)
- 服务器错误(500-599)
namespace HttpClientStatus; class Program { static async Task Main(string[] args) { using var client = new HttpClient(); var result = await client.GetAsync("http://webcode.me"); Console.WriteLine(result.StatusCode); } }
该示例创建了一个对小型网站的GET请求。我们得到请求的状态码。
using var client = new HttpClient();
创建了一个新的HttpClient
。
var result = await client.GetAsync("http://webcode.me");
GetAsync
方法将GET请求作为异步操作发送到指定的Uri。await
运算符暂停对封闭异步方法的计算,直到异步操作完成。当异步操作完成时,await
运算符返回操作结果(如果有)。
$ dotnet run OK
我们得到200OK状态码;网站上线了。
C#HttpClientGET请求
GET方法请求指定资源的表示。
using var client = new HttpClient(); var content = await client.GetStringAsync("http://webcode.me"); Console.WriteLine(content);
该示例向webcode.me
网站发出GET请求。输出首页的简单HTML代码。
var content = await client.GetStringAsync("http://webcode.me");
GetStringAsync
向指定的Uri发送GET请求,并在异步操作中将响应主体作为字符串返回。
$ dotnet run <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="format.css"> <title>My html page</title> </head> <body> <p> Today is a beautiful day. We go swimming and fishing. </p> <p> Hello there. How are you? </p> </body> </html>
C#HttpClientHEAD请求
如果使用HTTPGET方法请求指定的资源,HTTPHEAD方法请求返回的标头。
var url = "http://webcode.me"; using var client = new HttpClient(); var result = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url)); Console.WriteLine(result);
该示例发出HEAD请求。
$ dotnet run StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: { Server: nginx/1.6.2 Date: Tue, 12 Jan 2021 12:01:07 GMT Connection: keep-alive ETag: "5d32ffc5-15c" Accept-Ranges: bytes Content-Type: text/html Content-Length: 348 Last-Modified: Sat, 20 Jul 2019 11:49:25 GMT }
这些是响应的标头字段。
C#HttpClient用户代理
User-Agent
请求标头是一个字符串,它让服务器和网络对等体识别请求用户代理的应用程序、操作系统、供应商和/或版本。
var url = "http://webcode.me/ua.php"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("User-Agent", "C# program"); var res = await client.GetStringAsync(url); Console.WriteLine(res);
该示例为其GET请求设置了一个User-Agent标头。请求的资源仅返回客户端的用户代理字符串。
C#HttpClientHttpRequestMessage
HttpRequestMessage
表示请求消息。
var url = "http://webcode.me"; using var client = new HttpClient(); var msg = new HttpRequestMessage(HttpMethod.Get, url); msg.Headers.Add("User-Agent", "C# Program"); var res = await client.SendAsync(msg); var content = await res.Content.ReadAsStringAsync(); Console.WriteLine(content);
在示例中,我们手动构建请求消息。
var msg = new HttpRequestMessage(HttpMethod.Get, url); msg.Headers.Add("User-Agent", "C# Program"); var res = await client.SendAsync(msg);
GET请求消息使用HttpRequestMessage
创建并使用SendAsync
发送。
var content = await res.Content.ReadAsStringAsync();
我们使用ReadAsStringAsync
读取响应的内容。
C#HttpClient查询字符串
查询字符串是URL的一部分,用于向资源请求添加一些数据。它通常是一系列键/值对。它遵循路径并以?特点。
var u = "http://webcode.me/qs.php"; using var client = new HttpClient(); var builder = new UriBuilder(u); builder.Query = "name=John Doe&occupation=gardener"; var url = builder.ToString(); var res = await client.GetAsync(url); var content = await res.Content.ReadAsStringAsync(); Console.WriteLine(content);
查询字符串是使用UriBuilder
构建的。
$ dotnet run {"name":"John Doe","occupation":"gardener"}
C#HttpClient超时
目前,http请求在100秒后超时。要设置不同的超时,我们可以使用TimeOut
属性。
using var httpClient = new HttpClient(); httpClient.Timeout = TimeSpan.FromMinutes(3);
在此代码段中,我们将超时设置为3分钟。
C#HttpClient多个异步请求
在下面的示例中,我们生成多个异步GET请求。
using System.Text.RegularExpressions; var urls = new string[] { "http://webcode.me", "http://example.com", "http://httpbin.org", "https://ifconfig.me", "http://termbin.com", "https://github.com" }; var rx = new Regex(@"<title>\s*(.+?)\s*</title>", RegexOptions.Compiled); using var client = new HttpClient(); var tasks = new List<Task<string>>(); foreach (var url in urls) { tasks.Add(client.GetStringAsync(url)); } Task.WaitAll(tasks.ToArray()); var data = new List<string>(); foreach (var task in tasks) { data.Add(await task); } foreach (var content in data) { var matches = rx.Matches(content); foreach (var match in matches) { Console.WriteLine(match); } }
我们异步下载给定的网页并打印它们的HTML标题标签。
tasks.Add(client.GetStringAsync(url));
GetStringAsync
向指定的url发送GET请求,并在异步操作中将响应正文作为字符串返回。它返回一个新任务;在C#中,任务表示异步操作。
Task.WaitAll(tasks.ToArray());
Task.WaitAll
等待所有提供的任务完成执行。
data.Add(await task);
await
解包结果值。
$ dotnet run <title>My html page</title> <title>Example Domain</title> <title>httpbin.org</title> <title>termbin.com - terminal pastebin</title> <title>GitHub: Where the world builds software · GitHub</title>
C#HttpClientPOST请求
HTTPPOST方法向服务器发送数据。请求正文的类型由Content-Type
标头指示。
$ dotnet add package Newtonsoft.Json
我们需要添加Newtonsoft.Json
包来处理JSON数据。
using System.Text; using Newtonsoft.Json; var person = new Person("John Doe", "gardener"); var json = JsonConvert.SerializeObject(person); var data = new StringContent(json, Encoding.UTF8, "application/json"); var url = "https://httpbin.org/post"; using var client = new HttpClient(); var response = await client.PostAsync(url, data); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); record Person(string Name, string Occupation);
在示例中,我们向https://httpbin.org/post
网站发送一个POST请求,这是一个为开发者提供的在线测试服务。
var person = new Person("John Doe", "gardener"); var json = JsonConvert.SerializeObject(person); var data = new StringContent(json, Encoding.UTF8, "application/json");
我们借助Newtonsoft.Json
包将对象转换为JSON数据。
var response = await client.PostAsync(url, data);
我们使用PostAsync
方法发送异步POST请求。
var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result);
我们读取返回的数据并将其打印到控制台。
$ dotnet run { "args": {}, "data": "{\"Name\":\"John Doe\",\"Occupation\":\"gardener\"}", "files": {}, "form": {}, "headers": { "Content-Length": "43", "Content-Type": "application/json; charset=utf-8", "Host": "httpbin.org", "X-Amzn-Trace-Id": "Root=1-5ffd917e-349220186065913c2544d3ba" }, "json": { "Name": "John Doe", "Occupation": "gardener" }, ... "url": "https://httpbin.org/post" }
C#HttpClientJSON请求
JSON(JavaScript对象表示法)是一种轻量级数据交换格式。这种格式易于人类阅读和编写,也易于机器解析和生成。它是XML的一种更简洁、更易读的替代方法。JSON的官方互联网媒体类型是application/json
。
using System.Net.Http.Headers; using Newtonsoft.Json; using var client = new HttpClient(); client.BaseAddress = new Uri("https://api.github.com"); client.DefaultRequestHeaders.Add("User-Agent", "C# console program"); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); var url = "repos/symfony/symfony/contributors"; HttpResponseMessage response = await client.GetAsync(url); response.EnsureSuccessStatusCode(); var resp = await response.Content.ReadAsStringAsync(); List<Contributor> contributors = JsonConvert.DeserializeObject<List<Contributor>>(resp); contributors.ForEach(Console.WriteLine); record Contributor(string Login, short Contributions);
该示例向Github生成GET请求。它找出Symfony框架的顶级贡献者。它使用Newtonsoft.Json
来处理JSON。
client.DefaultRequestHeaders.Add("User-Agent", "C# console program");
在请求标头中,我们指定用户代理。
client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json"));
在接受标头值中,我们告知JSON是可接受的响应类型。
var url = "repos/symfony/symfony/contributors"; HttpResponseMessage response = await client.GetAsync(url); var resp = await response.Content.ReadAsStringAsync();
我们生成请求并异步读取内容。
List<Contributor> contributors = JsonConvert.DeserializeObject<List<Contributor>>(resp); contributors.ForEach(Console.WriteLine);
我们使用JsonConvert.DeserializeObject
方法将JSON响应转换为Contributor
对象列表。
C#HttpClientPOST表单数据
POST请求通常通过post表单发送。请求正文的类型由Content-Type
标头指示。FormUrlEncodedContent
是使用application/x-www-form-urlencoded
MIME类型编码的名称/值元组的容器。
var url = "https://httpbin.org/post"; using var client = new HttpClient(); var data = new Dictionary<string, string> { {"name", "John Doe"}, {"occupation", "gardener"} }; var res = await client.PostAsync(url, new FormUrlEncodedContent(data)); var content = await res.Content.ReadAsStringAsync(); Console.WriteLine(content);
该示例使用FormUrlEncodedContent
发送表单POST请求。
$ dotnet run { "args": {}, "data": "", "files": {}, "form": { "name": "John Doe", "occupation": "gardener" }, "headers": { "Content-Length": "33", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "X-Amzn-Trace-Id": "Root=1-6218d376-03e6c2f004520f2f2e504f37" }, "json": null, ... "url": "https://httpbin.org/post" }
C#HttpClient代理
代理是请求资源的客户端和提供该资源的服务器之间的中介。
using System.Net; var port = 7302; var proxy = "example.com"; var url = "http://webcode.me"; var handler = new HttpClientHandler() { Proxy = new WebProxy(new Uri($"socks5://{proxy}:{port}")), UseProxy = true, }; using var client = new HttpClient(handler); var res = await client.GetAsync(url); var content = await res.Content.ReadAsStringAsync(); Console.WriteLine(content);
该示例通过代理创建网络请求。C#使用WebProxy
设置代理服务器。
C#HttpClient下载图片
GetByteArrayAsync
向指定的Uriand发送GET请求,并在异步操作中将响应主体作为字节数组返回。
using var httpClient = new HttpClient(); var url = "http://webcode.me/favicon.ico"; byte[] imageBytes = await httpClient.GetByteArrayAsync(url); string documentsPath = System.Environment.GetFolderPath( System.Environment.SpecialFolder.Personal); string localFilename = "favicon.ico"; string localPath = Path.Combine(documentsPath, localFilename); Console.WriteLine(localPath); File.WriteAllBytes(localPath, imageBytes);
在示例中,我们从webcode.me
网站下载图像。该图像被写入用户的Documents
文件夹。
byte[] imageBytes = await httpClient.GetByteArrayAsync(url);
GetByteArrayAsync
将图像作为字节数组返回。
string documentsPath = System.Environment.GetFolderPath( System.Environment.SpecialFolder.Personal);
我们使用GetFolderPath
方法确定Documents
文件夹。
File.WriteAllBytes(localPath, imageBytes);
使用File.WriteAllBytes
方法将字节写入磁盘。
C#HttpClient流
流式传输是一种以连续流的形式传输数据的方法,在整个文件发送完毕之前,接收计算机可以对其进行处理。
using var httpClient = new HttpClient(); var url = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.2/images/NetBSD-9.2-amd64-install.img.gz"; var fname = Path.GetFileName(url); var resp = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); resp.EnsureSuccessStatusCode(); using Stream ms = await resp.Content.ReadAsStreamAsync(); using FileStream fs = File.Create(fname); await ms.CopyToAsync(fs); Console.WriteLine("file downloaded");
在示例中,我们使用流下载NetBSDUSB映像。
var resp = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
使用HttpCompletionOption.ResponseHeadersRead
选项,异步操作应该在响应可用并且标头被读取时立即完成。内容尚未阅读。该方法将只读取标头并将控件返回。
using Stream ms = await resp.Content.ReadAsStreamAsync();
ReadAsStreamAsync
方法序列化HTTP内容并返回表示内容为异步操作的流。
using FileStream fs = File.Create(fname); await ms.CopyToAsync(fs);
数据不断复制到文件流中。
C#HttpClient基本认证
在HTTP协议中,基本访问认证是HTTP用户代理(如网络浏览器或控制台应用程序)在发出请求时提供用户名和密码的一种方法。在基本的HTTP身份验证中,请求包含一个头字段,形式为Authorization:Basic
,其中credentials是id和password的base64编码,由单个冒号连接:
.
HTTP基本身份验证是对Web资源实施访问控制的最简单技术。它不需要cookie、会话标识符或登录页面;相反,HTTP基本身份验证使用HTTP标头中的标准字段。
using System.Text; using System.Net.Http.Headers; var userName = "user7"; var passwd = "passwd"; var url = "https://httpbin.org/basic-auth/user7/passwd"; using var client = new HttpClient(); var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken)); var result = await client.GetAsync(url); var content = await result.Content.ReadAsStringAsync(); Console.WriteLine(content);
该示例将凭据发送到httpbin.org
网站。
var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));
这里我们构建身份验证标头。
var url = "https://httpbin.org/basic-auth/user7/passwd";
该URL包含身份验证详细信息,因为我们使用httpbin.org
网站对其进行了测试。这样我们就不需要设置自己的服务器了。当然,身份验证详细信息永远不会放入URL中。
$ dotnet run { "authenticated": true, "user": "user7" }
在本文中,我们使用C#HttpClient
创建HTTP请求。
列出所有C#教程。