快讀《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 : ControllerBase10 {11//模擬一個persons數據集合12private List<Person> persons = new List<Person>();13public TestController()14{15var p1 = new Person(1, "ZS", 25);16var p2 = new Person(2, "LS", 18);17var p3 = new Person(3, "WU", 35);18var p4 = new Person(4, "ZL", 46);19persons.Add(p1);20persons.Add(p2);21persons.Add(p1);22persons.Add(p1);2324}2526[HttpGet("{id}")]27public ActionResult<Person> GetPersonById(int id)28{29if (id < 1)30{31return BadRequest(new ErrorInfo(1, "id必須是正數"));32}33else if(id > 4)34{35return NotFound(new ErrorInfo(2, "查無此人"));36}37else38{39return 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請求 , 參數使用請求體

推薦閱讀