2

快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践 - functionMC

 1 year ago
source link: https://www.cnblogs.com/functionMC/p/16840281.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践

本节内容,涉及到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倍


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK