本节内容,涉及到6.1-6.6(P155-182),以WebApi说明为主。主要NuGet包:无

一、创建WebApi的最佳实践,综合了RPC和Restful两种风格的特点

 1 //定义Person类和ErrorInfo类
2 public record Person(int Id, string Name, int Age);
3 public record ErrorInfo(int Code, string? Message);
4
5
6 //定义控制器和一个Get方法
7 [ApiController]
8 [Route("api/[controller]/[action]")]
9 public class TestController : ControllerBase
10 {
11 //模拟一个persons数据集合
12 private List<Person> persons = new List<Person>();
13 public TestController()
14 {
15 var p1 = new Person(1, "ZS", 25);
16 var p2 = new Person(2, "LS", 18);
17 var p3 = new Person(3, "WU", 35);
18 var p4 = new Person(4, "ZL", 46);
19 persons.Add(p1);
20 persons.Add(p2);
21 persons.Add(p1);
22 persons.Add(p1);
23
24 }
25
26 [HttpGet("{id}")]
27 public ActionResult<Person> GetPersonById(int id)
28 {
29 if (id < 1)
30 {
31 return BadRequest(new ErrorInfo(1, "id必须是正数"));
32 }
33 else if(id > 4)
34 {
35 return NotFound(new ErrorInfo(2, "查无此人"));
36 }
37 else
38 {
39 return persons.FirstOrDefault(p => p.Id == id);
40 }
41 }
42 }

代码解读:

8行:统一设置控制器类的路径为[controller]/[action],控制器+方法名,前缀api可省略。这个方式倾向于RPC风格,可以直接知道API的意图

9行:因为不需要MVC中的视图功能,所以WebApi的控制器继承ControllerBase即可,ControllerBase中定义了Response、Request、HttpContext等属性成员来获取请求和响应信息,以及BadRequest、NotFound、OK等方法来快速设置响应报文。

26行:所有方法,都须加上Http方法的Attribute,主要有[HttpGet]、[HttpPost]、[HttpPut]、[HttpDelete],分别进行查询、新增、更新、删除操作。这不仅有利于明确操作方法的请求类型,也有利于使用Swagger+OpenApi来生成文档。使用Swagger时,如果没有标注,会报错,如果确定这个方法不生成Api,可以标注[ApiExplorerSettings(IgnoreApi = true)]

27行:返回值如果是普通类型,直接返回即可,会自动序列化为JSON格式,但如果返回值为复杂类型,需要使用ActionResult<T>泛型类型来包装

31,35行:使用BadRequest、NotFound、Ok等方法,快速设置响应数据,可以和ActionResult<T>很好的结合使用。其中BadRequest的响应状态码为400,NotFound为404,Ok为200。同时,方法参加为一个自定义ErrorInfo对象,包括错误码和错误信息两个属性,进一步说明具体的错误信息。方法会自动将ErrorInfo对象序列化为JSON对象

39行:直接返回对象,因为方法设置了返回值为ActionResult<T>,自动将复杂对象序列化为JSON对象。这里严谨一点,应该判断一下是否为null

补充说明:

①HTTP的四个常用请求谓词的特征:GET/Put/DELETE是幂等操作,网关或网络请求组件会对失败请求自动重试;POST是非幂等的,需要注意重复提交的情况;GET请求的响应可以被缓存,而其它请求不能被缓存;GET和DELETE不支持请求体传参,POST和PUT支持

②HTTP的常用状态码:401,需要身份认证的但是没有提供;403,需要权限的但没有权限;404,请求的资源不存在;400,请求参数错误或其它业务错误;200,请求处理成功

③如果方法中调用了异步方法,则返回值为async Task<ActionResult<T>>

二、Api方法参数的最佳实践

1、通过URL

//通过HttpGet的参数设置请求路径,其中{}内的,为路径参数
//如果方法参数的名称和{}内的不一样,则参数使用[FromRoute]指定
//如果请求参数schoolName为aaa,classNo为bbb
//则请求路径为api/Test/GetAll/school/aaa/class/bbb
[HttpGet("school/{schoolName}/class/{classNo}")]
public ActionResult<Student[]> GetAll(string schoolName, [FromRoute(Name = "classNo")] string classNum){}

2、通过QueryString

//从Query中获取实参时,就不需要在HttpGet中设置路径
//如果请求参数名称和方法行参名称不同,则要指定[FromQuery]的Name属性
//假设请求参数schoolName为aaa,classNo为bbb
//则请求地址为api/Test/GetAll?schoolName=aaa&classNum=bbb
[HttpGet]
public ActionResult<Student> GetAll(string schoolName, [FromQuery(Name = "classNo")]string classNum){}

3、通过请求体

//方法参数为复杂类型时,自动序列化为JSON,通过请求体发送
//参数中可加、可不加[FromBody]
//请求地址为api/Test/AddNew
[HttpPost]
public ActionResult<Student> AddNew(Student studentDto)
{
persons.Add(studentDto);
return Ok(studentDto);
}

4、除了FromRoute、FromQuery、FromBody之外,还有FromForm、FromHeader等

5、传递参数最佳实践:

①GET和DELETE请求,参数使用QueryString

②POST请求,参数使用请求体

③PUT请求,定位参数使用QueryString,DTO参数使用请求体

④GET请求,如果参数内容超过URL长度限制,则把请求改为PUT,并通过请求体来传递参数

⑤Restful风格,要求路径参数用于定位资源,Query参数用于传递额外参数,但使用Query更符合中文习惯,所以URL还是比较少使用

⑥注意:请求报文头的Content-Type要设置为application/JSON

特别说明:
1、本系列内容主要基于杨中科老师的书籍《ASP.NET Core技术内幕与项目实战》及配套的B站视频视频教程,同时会增加极少部分的小知识点
2、本系列教程主要目的是提炼知识点,追求快准狠,以求快速复习,如果说书籍学习的效率是视频的2倍,那么“简读系列”应该做到再快3-5倍

快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践的更多相关文章

  1. 快读《ASP.NET Core技术内幕与项目实战》EFCore2.5:集合查询原理揭秘(IQueryable和IEnumerable)

    本节内容,涉及4.6(P116-P130).主要NuGet包:如前述章节 一.LINQ和EFCore的集合查询扩展方法的区别 1.LINQ和EFCore中的集合查询扩展方法,虽然命名和使用完全一样,都 ...

  2. 简读《ASP.NET Core技术内幕与项目实战》之3:配置

    特别说明:1.本系列内容主要基于杨中科老师的书籍<ASP.NET Core技术内幕与项目实战>及配套的B站视频视频教程,同时会增加极少部分的小知识点2.本系列教程主要目的是提炼知识点,追求 ...

  3. 《ASP.NET Core技术内幕与项目实战》精简集-目录

    本系列是杨中科2022年最新作品<ASP.NET Core技术内幕与项目实战>及B站配套视频(强插点赞)的精简集,是一个读书笔记.总结和提炼了主要知识点,遵守代码优先原则,以利于快速复习和 ...

  4. ASP.NET Core 2.0 MVC项目实战

    一.前言 毕业后入职现在的公司快有一个月了,公司主要的产品用的是C/S架构,再加上自己现在还在学习维护很老的delphi项目,还是有很多不情愿的.之前实习时主要是做.NET的B/S架构的项目,主要还是 ...

  5. ASP.NET CORE MVC 2.0 项目中引用第三方DLL报错的解决办法 - InvalidOperationException: Cannot find compilation library location for package

    目前在学习ASP.NET CORE MVC中,今天看到微软在ASP.NET CORE MVC 2.0中又恢复了允许开发人员引用第三方DLL程序集的功能,感到甚是高兴!于是我急忙写了个Demo想试试,我 ...

  6. ASP.NET Core 2.0 : 三. 项目结构

    本章我们一起来对比着ASP.NET Framework版本看一下ASP.NET Core 2.0的项目结构.(此后的文章也尽量这样对比着, 方便学习理解.) 关注差异, 也为项目迁移做准备. 新建项目 ...

  7. ASP.NET Core Web多语言项目

    公司效益好了,准备和国外做生意,这个时候就需要多语言了. > 1. 这是一个ASP.NET Core Web多语言项目,主要展示项目的不同: > 2. 第一种:www.xxx.com/en ...

  8. Taurus.MVC 微服务框架 入门开发教程:项目集成:2、客户端:ASP.NET Core(C#)项目集成:应用中心。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

  9. ASP.NET Core技术研究-探秘Host主机启动过程

    当我们将原有ASP.NET 应用程序升级迁移到ASP.NET Core之后,我们发现代码工程中多了两个类Program类和Startup类. 接下来我们详细探秘一下通用主机Host的启动过程. 一.P ...

随机推荐

  1. ARC120F Wine Thief (组合数学)

    题面 有一个长为 N N N 的序列,相邻的两个数中只能选一个,总共选 k k k 个数,一种方案的价值为选的 k k k 个数的和,问所有合法方案的价值总和,答案对 998244353 取模. 1 ...

  2. Usmjeri(COCI2017.2)题解

    题意 给一棵N个节点的树,编号从1到N,再给定m对点(u,v),你要将树上的每条无向边变为有向边,使得给定的点对都满足u能到达v或v能到达u.问有多少种不同的方案,答案对(1e9+7)求余. 1 ≤ ...

  3. 第二十二篇:有关插槽solt的使用

    1.什么是插槽? 插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示, 父组件可以在这个占位符中填充任何模板代码,如 HTML.组件等,填充的内 ...

  4. MFRC522学习笔记

    MFRC522主要特性 容量为8K位(bits)=1K字节(bytes)EEPROM 分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位 每个扇区有独立的一组密码及访问控制 每张卡有唯一序 ...

  5. KingbbaseES V8R6集群维护案例之---集群之间数据迁移

    案例说明: 生产环境是集群环境,测试环境是集群,现需要将生产环境的数据迁移到测试集群中运行,本文档详细介绍了从集群环境迁移数据的操作步骤,可以作为生产环境迁移数据的参考. 适用版本: Kingbase ...

  6. KingbaseES R6 集群物理copy方式手工添加新备库节点

    案例说明: 对于主库数据量比较大的环境,在添加新节点是可以采用在线clone方式创建新的备库节点,也可以在离线的状态下,直接拷贝其中一个备库的所有集群相关目录来创建新的备库节点.本案例介绍了通过离线物 ...

  7. GIN 索引

    GIN(Generalized Inverted Index, 通用倒排索引) 是一个存储对(key, posting list)集合的索引结构,其中key是一个键值,而posting list 是一 ...

  8. 常用的工具函数助力JavaScript高效开发

    前言 日常开发中,面对各种不同的需求,我们经常会用到以前开发过的一些工具函数,把这些工具函数收集起来,将大大提高我们的开发效率. 1.校验数据类型 export const typeOf = func ...

  9. [Python]-opencv-python模块(cv2)-图片读取和格式转换

    python常常用opencv模块来处理图像. import cv2 as cv 读取图片:imread() 默认按照彩色三通道读取: img = cv2.imread(path) 读取灰度图: im ...

  10. null和undefined的区别、数组和伪数组的区别

    null和undefined的区别 undefined: 字面意思是未定义的值,语义是希望表示一个变量最原始的状态,而非人为操作的结果.这种原始状态会在以下四个场景中出现: 声明了一个变量但没有赋值 ...