快讀《ASP.NET Core技術內幕與項目實戰》WebApi3.1:WebApi最佳實踐
- 2022 年 10 月 30 日
- 筆記
- aspnetcore, AspNetCore/ABP/MASA/Harmony, 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倍