百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

.Net Core HttpClient 全面教程系列-发送Http请求

bigegpt 2024-09-22 00:42 3 浏览

0、初始化与全局设置

In [1]:

//全局设置,行运行一次,为后续准备
#r "nuget:System.Net.Http.Json"
#r "nuget:Microsoft.Net.Http.Headers"
#r "nuget:Microsoft.Extensions.Http"
#r "nuget:Microsoft.Extensions.DependencyInjection"
#r "./Publish/HttpClientStudy.Model/HttpClientStudy.Model.dll"
#r "./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll"

global using System;
global using System.Collections;
global using System.Collections.Concurrent;
global using System.Linq;
global using System.Linq.Expressions;
global using System.Threading;
global using System.Threading.Tasks;
global using System.Net.Http;
//System.Net.Http.Json 包含处理json的扩展方法,方便处理请求和影响中的json数据
global using System.Net.Http.Json;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.DependencyInjection.Extensions;

global using HttpClientStudy.Config;
global using HttpClientStudy.Model;
global using HttpClientStudy.Core;
global using HttpClientStudy.Core.Utilities;

//全局变量
var webApiBaseUrl = WebApiConfigManager.GetWebApiConfig().BaseUrl;
var workDir = Environment.CurrentDirectory;
var fullPath = System.IO.Path.GetFullPath("./Publish/HttpClientStudy.WebApp/HttpClientStudy.WebApp.exe", workDir);

//全局共享静态 HttpClient 对象
public static HttpClient SharedClient = new HttpClient(new SocketsHttpHandler(){ PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30)})
{
    BaseAddress = new Uri(WebApiConfigManager.GetWebApiConfig().BaseUrl),
};

//启动已发布的WebApi项目
{
    Console.WriteLine("启动WebApi项目");
    var startMessage = AppUtility.RunWebApiExeFile(fullPath);
    Console.WriteLine(startMessage);
}

Installed Packages

  • Microsoft.Extensions.DependencyInjection, 8.0.0
  • Microsoft.Extensions.Http, 8.0.0
  • Microsoft.Net.Http.Headers, 8.0.8
  • System.Net.Http.Json, 8.0.0
配置文件根目录:d:\软件项目\学习项目\HttpClientStudy\Docs\Publish\HttpClientStudy.Core
启动WebApi项目
程序[d:\软件项目\学习项目\HttpClientStudy\Docs\Publish\HttpClientStudy.WebApp\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!

1、创建HttpClient

根据 系列教程的 管理客户端 一章, 创建的HttpClient对象,有非常多的方式。 为方便演示,本节使用两种:一种是全局共享对象(SharedClient, 在初始化时创建), 符合共享的使用原则; 一种是临时实例化对象。

2、发出 Http请求

Http 简介

http是无状态的请求/响应模式。

客户端请求: 请求行(方法 URL 协议版本 回车换行符)、请求头、空行及可选的请求体;

服务器响应:状态行(协议版本 状态码 状态码描述 回车换行符)、响应头及可选的响应体。

Http 请求方法

Http请求方法可通过多种特性区分:

  1. 谓词:也就是请求方法,Post、Get、Put、Delete、Options、Head等;
  2. 幂等性:如果可多次成功处理某个请求方法而不改变结果,则该请求方法是幂等的;
  3. 可缓存性:如果可以存储请求方法的相应响应以供重复使用,则该请求方法是可缓存的;
  4. 安全性:如果请求方法不会修改资源的状态,则被视为安全方法。所有安全方法也都是幂等方法,但并非所有幂等方法都是安全方法;
  5. | HTTP 方法 | 是否是幂等的 | 是否可缓存 | 是否安全 | | ------------- | ---------------- | -------------- | ------------ | | GET | ?? 是 | ?? 是 | ?? 是 | | POST | ? 否 | ?? ?很少 | ? 否 | | PUT | ?? 是 | ? 否 | ? 否 | | PATCH | ? 否 | ? 否 | ? 否 | | DELETE | ?? 是 | ? 否 | ? 否 | | HEAD | ?? 是 | ?? 是 | ?? 是 | | OPTIONS | ?? 是 | ? 否 | ?? 是 | | TRACE | ?? 是 | ? 否 | ?? 是 | | CONNECT | ? 否 | ? 否 | ? 否 |

?仅当存在相应的 Cache-Control 或 Expires 响应标头时,POST 方法才可缓存。 这在实践中非常罕见。

Http 状态码

Http 状态码是响应的首要标识,指定响应的不同结果,分为以下几类:

  1. 1xx:信息,表示临时响应,大多数临时响应 (例如 HttpStatusCode.Continue) 使用 HttpClient 在内部处理,并且永远不会显示给用户;
  2. 2xx:成功,表示请求已被成功接收、理解、并接受;
  3. 3xx:重定向,表示需要完成一个或多个附加步骤才能完成请求,自动重定向默认处于打开状态,可以使用 HttpClientHandler.AllowAutoRedirect 或 SocketsHttpHandler.AllowAutoRedirect 进行更改;
  4. 4xx:客户端错误,表示客户端的请求无效(请求包含语法错误或无法完成请求);
  5. 5xx:服务器错误,表示服务器在处理请求的过程中发生了错误。

使用 HttpClient 发出请求

要发出 HTTP 请求,请调用以下任一 API:

HTTP 方法

API

GET

HttpClient.GetAsync

GET

HttpClient.GetByteArrayAsync

GET

HttpClient.GetStreamAsync

GET

HttpClient.GetStringAsync

POST

HttpClient.PostAsync

PUT

HttpClient.PutAsync

PATCH

HttpClient.PatchAsync

DELETE

HttpClient.DeleteAsync

?USER SPECIFIED

HttpClient.SendAsync


?USER SPECIFIED 请求指示 SendAsync 方法接受任何有效的 HttpMethod。

Http 内容

HttpContent 类型用于表示 HTTP 实体正文和相应的内容标头。 对于需要正文的 HTTP 方法(或请求方法)POST、PUT 和 PATCH,可使用 HttpContent 类来指定请求的正文。 大多数示例演示如何使用 JSON 有效负载准备 StringContent 子类,但还有针对其他内容 (MIME) 类型的其他子类。

  • ByteArrayContent:提供基于字节数组的 HTTP 内容;
  • FormUrlEncodedContent:为使用 "application/x-www-form-urlencoded" MIME 类型编码的名称/值元组提供 HTTP 内容;
  • JsonContent:提供基于 JSON 的 HTTP 内容;
  • MultipartContent:提供使用 "multipart/*" MIME 类型规范进行序列化的 HttpContent 对象的集合;
  • MultipartFormDataContent:为使用 "multipart/form-data" MIME 类型进行编码的内容提供容器;
  • ReadOnlyMemoryContent:提供基于 ReadOnlyMemory 的 HTTP 内容;
  • StreamContent:提供基于流的 HTTP 内容;
  • StringContent:提供基于字符串的 HTTP 内容

Http Get

GET 请求不应发送正文,而是用于从资源检索数据。 要在给定 HttpClient 和 URI 的情况下发出 HTTP GET 请求,推荐使用 HttpClient.GetAsync 方法。

Get 请求,一般不会发送数据(服务器支持的话,也能带),最大特点是:可以缓存请求结果,减少服务器压力。

In [2]:

//Get 请求
{
    //使用共享客户端发送Get请求
    var response = await SharedClient.GetAsync("/api/hello/index");

    //确保请求成功
    response.EnsureSuccessStatusCode();

    //读取响应内容
    var content = await response.Content.ReadAsStringAsync();

    //输出 响应内容
    Console.WriteLine(content);
}
配置文件根目录:d:\软件项目\学习项目\HttpClientStudy\Docs\Publish\HttpClientStudy.Core
Index

Http Get Json

System.Net.Http.Json 库,为请求Json格式数据和接受json格式数据提供了很多扩展方法,使用 HttpClient 发送和请求Json格式数据非常方便;
后面单独章节讲解,这里只是一个例子.

In [3]:

/*
    方式一:使用 System.Net.Http.Json
    Get Json
    需要先引入 System.Net.Http.Json 和 命名空间(全局设置里已完成)
*/
{

    //使用共享客户端发送Get请求
    var content = await SharedClient.GetFromJsonAsync<HttpClientStudy.Model.Account>("/api/hello/GetAccount");

    //框架显示方法
    content.Display();
}

/*
    方式二:ReadFromJsonAsync 方法,读取响应内容(HttpResonseMessage.Content)
*/
{
    var response = await SharedClient.GetAsync("/api/hello/GetAccount");
    response.EnsureSuccessStatusCode();

    var content = await response.Content.ReadFromJsonAsync<HttpClientStudy.Model.Account>();
    content.Display();
}

/*
    方式三:手动序列化读取的响应内容
*/
{
    var response = await SharedClient.GetAsync("/api/hello/GetAccount");
    response.EnsureSuccessStatusCode();

    var content = await response.Content.ReadAsStringAsync();
    
    var account =  System.Text.Json.JsonSerializer.Deserialize<HttpClientStudy.Model.Account>(content);
    account.Display();
}

HttpClientStudy.Model.Account



Id

1

Name

Hello

Password

pwd

Role

Devlopment

HttpClientStudy.Model.Account



Id

1

Name

Hello

Password

pwd

Role

Devlopment

HttpClientStudy.Model.Account



Id

0

Name

<null>

Password

<null>

Role

Dev

HTTP Post

POST 请求将数据发送到服务器进行处理。 请求的 Content-Type 标头表示正文发送的 MIME 类型。 要在给定 HttpClient 和 Uri 的情况下发出 HTTP POST 请求,请使用 HttpClient.PostAsync 方法. 请求数据可选:包括 请求URL、路由、请求头、请求体(包括多种方式,后面详解)

In [4]:

//不带请求体
{
    var response = await SharedClient.PostAsync("/api/hello/Post",null);
    response.EnsureSuccessStatusCode();

    var context = await response.Content.ReadAsStringAsync();

    Console.WriteLine(context);
}

//带请求体
{
    var account = new Account()
    {
        Id =0,
        Name = "小王",
    };

    //请求体有很多:后面专门章节讲解
    var requestContent = new StringContent(System.Text.Json.JsonSerializer.Serialize(account), System.Text.Encoding.UTF8, System.Net.Mime.MediaTypeNames.Application.Json);

    var response = await SharedClient.PostAsync("/api/hello/AddAccount", requestContent);
    response.EnsureSuccessStatusCode();

    var context = await response.Content.ReadAsStringAsync();

    Console.WriteLine(context);
}
Post Success
添加成功

HTTP Put

PUT 请求方法会替换现有资源,或使用请求正文有效负载创建一个新资源。 要在给定 HttpClient 和 URI 的情况下发出 HTTP PUT 请求,请使用 HttpClient.PutAsync 方法。

In [5]:

/* Put请求, 一般是添加或修改资源:需要数据。
   这里故意使用查询,没有资源:
   意在说明:Get、Post、Put等谓词的使用,只是行业规范(有些服务器做了特殊处理),不具有强制性。并且,从http协议上说,没有本质区别。      
*/
{
    var response = await SharedClient.PutAsync("/api/Normal/PutDemo?id=2", null);

    response.EnsureSuccessStatusCode();

    var content = await response.Content.ReadAsStringAsync();
    Console.WriteLine(content);

    //或者直接获取对象
    var result = await response.Content.ReadFromJsonAsync<BaseResult<Account>>();
    result.Display();
}
{"data":{"id":2,"name":"管理员02","password":"123456","role":"Admin"},"code":1,"message":"成功"}

HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]



Data

HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]

Code

1

Message

成功

Data

HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]

HTTP Head

HEAD 请求类似于请求 GET。 它只返回与资源关联的标头,而不返回资源。 对 HEAD 请求的响应不会返回正文。
要在给定 HttpClient 和 URI 的情况下发出 HTTP HEAD 请求,请使用 HttpClient.SendAsync 方法并将 HttpMethod 设置为 HttpMethod.Head 注意:系统没有提供单独的Head方法,要使用通用的Send或者SendAsync

In [6]:

//Head请求,借助SendAsync方法
{
    var requestMessage = new HttpRequestMessage(HttpMethod.Head, "/api/Normal/HeadDemo?id=2");

    var response = await SharedClient.SendAsync(requestMessage);

    response.EnsureSuccessStatusCode();

    //Head请求,没有响应内容。
    var content = await response.Content.ReadAsStringAsync();
    Console.WriteLine(response.Content.Headers.ContentLength > 0 ? "有响应体":"无响应体");
}
无响应体

HTTP Patch

PATCH 请求是对现有资源执行部分更新。 它不会创建新资源,也不会替换现有资源。 而是只更新部分资源。 要在给定 HttpClient 和 URI 的情况下发出 HTTP PATCH 请求,请使用 HttpClient.PatchAsync 方法

In [7]:

//Patch请求
{
    var account = new Account()
    {
        Id = 1,
        Name = "Patch更新"
    };

    StringContent jsonContent = new(System.Text.Json.JsonSerializer.Serialize(account), Encoding.UTF8, System.Net.Mime.MediaTypeNames.Application.JsonPatch);

    HttpResponseMessage response = await SharedClient.PatchAsync( "api/Normal/PatchDemo", jsonContent);

    response.EnsureSuccessStatusCode();

    var context = await response.Content.ReadAsStringAsync();
    Console.WriteLine(#34;{context}");
}
{"data":{"id":1,"name":"Patch更新","password":"123456","role":"Admin"},"code":1,"message":"成功"}

HTTP Delete

DELETE 请求会删除现有资源。 DELETE 请求是幂等的但不是安全的,这意味着对同一资源发出的多个 DELETE 请求会产生相同的结果,但该请求会影响资源的状态。 要在给定 HttpClient 和 URI 的情况下发出 HTTP DELETE 请求,请使用 HttpClient.DeleteAsync 方法.

In [8]:

//Delete 删除资源
{
    HttpResponseMessage response = await SharedClient.DeleteAsync( "api/Normal/Delete?id=1");

    response.EnsureSuccessStatusCode();

    var context = await response.Content.ReadAsStringAsync();
    Console.WriteLine(#34;{context}");
}
{"data":1,"code":1,"message":"成功"}

HTTP Options

OPTIONS 请求用于标识服务器或终结点支持哪些 HTTP 方法。 要在给定 HttpClient 和 URI 的情况下发出 HTTP OPTIONS 请求,请使用 HttpClient.SendAsync 方法并将 HttpMethod 设置为 HttpMethod.Options

In [9]:

//Options 预检请求
{
    var requestMessage = new HttpRequestMessage(HttpMethod.Options, "api/Normal/OptionsSimple");

    HttpResponseMessage response = await SharedClient.SendAsync(requestMessage);

    response.EnsureSuccessStatusCode();

    var context = await response.Content.ReadAsStringAsync();
    Console.WriteLine(#34;{context}");
}
{"data":"简单OPTIONS请求","code":1,"message":"成功"}

HTTP Trace

TRACE 请求可用于调试,因为它提供请求消息的应用程序级环回。 要发出 HTTP TRACE 请求,请使用 HttpMethod.Trace 创建 HttpRequestMessage 特别注意:ASP.NET WebApi 并不直接支持 Trace 请求;一个简单方法是使用一个专用的中间件,来支持所有接口的Trace请求.(需要服务器支持)

In [10]:

//trace 服务器已设置专门中间件支持所有接口的Trace请求
{
    var requestMessage = new HttpRequestMessage(HttpMethod.Trace,"api/Normal/TraceDemo?accountId=1");
    requestMessage.Content = new StringContent("我是请求内容",Encoding.UTF8,System.Net.Mime.MediaTypeNames.Text.Plain);

    var response = await SharedClient.SendAsync(requestMessage);

    response.EnsureSuccessStatusCode();

    var context = await response.Content.ReadAsStringAsync();

    Console.WriteLine(context);
}
我是请求内容

相关推荐

Dify「模板转换」节点终极指南:动态文本生成进阶技巧(附代码)Jinja2引擎解析

这篇文章是关于Dify「模板转换」节点的终极指南,解析了基于Jinja2模板引擎的动态文本生成技巧,涵盖多源文本整合、知识检索结构化、动态API构建及个性化内容生成等六大应用场景,助力开发者高效利用模...

我用C#造了个AI程序员:自动调试+重构代码实战

在软件开发的世界里,调试和重构代码往往占据了程序员大量的时间。我一直梦想着能有一个智能助手,帮我处理这些繁琐的工作。于是,我决定用C#打造一个AI程序员,让它具备自动调试和重构代码的能力。系统架构设计...

公文自动排版vba代码(公文自动排版vba代码)

Sub公文自动排版()'设置页面参数(单位:厘米)WithActiveDocument.PageSetup.TopMargin=CentimetersToPoints(3.7)&#...

Anthropic最强代码神器:Claude Code系统提示词

最近,在融合Opus-4之后,ClaudeCode的整体能力直线飙升.甚至一度把曾经的最强开发工具——Cursor打的抬不起头来。无论是代码生成的准确度,还是智能补全的丝滑体验,都让人印象深...

使用 Ruff 进行 Python 代码格式化与静态检查

随着Python项目的规模增大,保持一致的代码风格和高质量的代码变得尤为重要。Ruff是一个现代、高性能、支持lint和格式化的Python工具,能帮助你快速发现并修复常见代码问题。本文...

基础语法篇:格式化输出 含完整示例代码

所谓格式化输出就是按照一定格式来输出对应的内容,在Python的语法中格式化输出包含两种:格式化符号、格式化字符串一、格式化符号常用的格式化符号包括%s(将内容转换为字符串,放入占位位置)、%d(将内...

代码整洁如诗!Keil 插件上线,一键格式化代码,告别风格混乱!

引言:代码格式不统一?你的团队还在为“括号位置”吵架吗?嵌入式开发者们,你是否经历过这些抓狂瞬间?代码风格“百花齐放”:同事的代码缩进用空格,你的用Tab,合并时冲突频发!手动调整耗时费力:为了通过C...

[信捷PLC] 信捷PLC之C函数编程(一)

前言写PLC程序,越来越觉得结构化文本编程语言(ST)给PC编程带来的便利,在处理一些数据上,可以写的更加灵活。所以,在项目PLC选型上,我都会优先选择支持结构化文本的PLC。国内有些厂商推出了一些较...

C语言-HelloWorld解析(c语言的helloworld怎么写)

使用VisualStudio2017开发工具新创建一个项目,编写第一个C语言程序。#include<stdio.h>voidmain(){printf("HelloW...

VSCode 配置 C++ 开发环境!教程详解

第一步、安装VSCode应用程序打开VSCode官网,下载对应安装包并默认安装(这里指明:安装路径可以修改)第二步、安装相关插件此时的VSCode仅仅是一个英文文本编辑器,还称不上开发工具,所以需要...

C语言进阶教程:C语言与汇编语言交互

C语言和汇编语言的交互是底层编程和性能优化中的一个重要方面。理解它们如何协同工作,可以帮助开发者更好地控制硬件、优化关键代码段以及理解编译器的行为。为什么需要在C语言中嵌入汇编?尽管C语言已经提供了相...

C语言如何处理平台相关代码(c语言的开发平台)

在进行跨平台C编程时,不可避免地会遇到需要针对不同操作系统或硬件架构编写特定代码的情况。C语言通过预处理器指令,特别是条件编译指令,为我们提供了处理平台相关代码的有效机制。最常用的就是利用预定义的宏(...

C语言:hello world(c语言helloworld代码)

环境:a.初学者建议用“啊哈C”,这款软件简单易装;b.devc.visualstdiod.Vc6.0第一行代码:#include<stdio.h>#<stdio.h&g...

C语言之编译器集合(编写c语言编译器)

C语言有多种不同的编译器,以下是常见的编译工具及其特点:一、主流C语言编译器1.GCC(GNUCompilerCollection)特点:开源、跨平台,支持多种语言(C、C++、Fortran...

适合零基础初学者学习C语言第一课教程,揭开C语言的神秘面纱

一、C语言简介我刚接触编程,首先想要学习的就是C语言,这次我就把我的感悟用我自己理解的文字表述出来,这样对刚学C语言的人来说,才是比较友好的。因为我们都没有C语言的基础,不懂啥是编程,啥事代码。我们...