快讀《ASP.NET Core技術內幕與專案實戰》WebApi3.1:WebApi最佳實踐

2022-10-30 06:02:52

本節內容,涉及到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倍