這里介紹在ASP.NET Core中使用Web API創建 RESTful 服務,本文使用VSCode + NET Core3.0
- 創建簡單Rest API
- 格式化輸出
- JSON Patch請求
- Open API(Swagger)集成
創建簡單Rest API
在終端輸入
dotnet new webapi -n WebAPI1. 創建Order模型,然后初始化資料

public class OrderStore{ public List<Order> Orders { get; } = new List<Order>(); public OrderStore() { var random = new Random(); foreach (var item in Enumerable.Range(1, 10)) { Orders.Add(new Order { Id = item, OrderNo = DateTime.Now.AddSeconds(random.Next(100, 200)).AddMilliseconds(random.Next(20, 50)).Ticks.ToString(), Quantity = random.Next(1, 10), Amount = Math.Round(((decimal)random.Next(100, 500) / random.Next(2, 6)), 2) }); } }}View Code
2. 簡單REST API介面

/// <summary>/// 訂單模塊/// </summary>[ApiController][Route("[controller]")][FormatFilter]public class OrderController : ControllerBase{ readonly Models.OrderStore _orderStore = null; public OrderController(Models.OrderStore orderStore) { _orderStore = orderStore; } /// <summary> /// 查詢所有訂單 /// </summary> [HttpGet] public ActionResult<List<Models.Order>> GetAll() => _orderStore.Orders; /// <summary> /// 獲取訂單 /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpGet("{id:int}.{format?}")] public ActionResult<Models.Order> GetById(int id) { var order = _orderStore.Orders.FirstOrDefault(m => m.Id == id); if (order == null) { return NotFound(); } return order; } /// <summary> /// 創建訂單 /// </summary> /// <param name="order"></param> /// <returns>成功回傳訂單Id,失敗回傳-1</returns> [HttpPost] public ActionResult<int> Create(Models.Order order) { if (_orderStore.Orders.Any(m => m.OrderNo == order.OrderNo)) { return -1; } order.Id = _orderStore.Orders.Max(m => m.Id) + 1; _orderStore.Orders.Add(order); return order.Id; } /// <summary> /// 更新訂單 /// </summary> /// <returns></returns> [HttpPut] public ActionResult<bool> Update(Models.Order model) { Console.WriteLine($"OrderNo:{model.OrderNo}"); var order = _orderStore.Orders.FirstOrDefault(m => m.OrderNo == model.OrderNo); if (order == null) { return NotFound(); } order.Amount = model.Amount; order.Quantity = model.Quantity; return true; } /// <summary> /// 更新訂單指定資訊 /// </summary> /// <remarks> /// Sample request: /// /// PATCH /Order/{orderNo} /// [ /// { /// "op": "test", /// "path": "/quantity", /// "value": "2" /// }, /// { /// "op": "test", /// "path": "/amount", /// "value": "38.28" /// }, /// { /// "op": "add", /// "path": "/isComplete", /// "value": "true" /// }, /// ] /// </remarks> /// <returns>回傳是否成功</returns> /// <response code="200">提交成功</response> /// <response code="400">提交引數例外</response> /// <response code="404">訂單號不存在</response> [HttpPatch("{orderNo:length(18)}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult<bool> Update([FromBody] JsonPatchDocument<Models.Order> patchDoc, [FromRoute] string orderNo) { var order = _orderStore.Orders.FirstOrDefault(m => m.OrderNo == orderNo); if (order == null) { return NotFound(); } patchDoc.ApplyTo(order, ModelState); if (!ModelState.IsValid) { return BadRequest(ModelState); } return Ok(true); }}View Code
3. 推薦一個VS Code插件(REST Client)測驗介面,官方介紹

@baseUrl = https://localhost:5001###GET {{baseUrl}}/Order HTTP/1.1### # @name orderPOST {{baseUrl}}/Order HTTP/1.1Accept: application/jsonContent-Type: application/json{ "OrderNo": "637109312996909246", "Quantity": 2, "Amount": 38.28}### @orderId = {{order.response.body.*}}GET {{baseUrl}}/Order/{{orderId}}.json HTTP/1.1### GET {{baseUrl}}/Order/{{orderId}}.xml HTTP/1.1###GET {{baseUrl}}/Order/{{orderId}} HTTP/1.1###PUT {{baseUrl}}/Order HTTP/1.1Content-Type: application/jsonAccept: application/json{ "Id": 12, "OrderNo": "2019112235759329", "Quantity": 2, "Amount": 38.28}###GET {{baseUrl}}/Order/11###PATCH {{baseUrl}}/Order/637109312996909246 HTTP/1.1Accept: application/jsonContent-Type: application/json[ { "op": "test", "path": "/quantity", "value": "2" }, { "op": "test", "path": "/amount", "value": "38.28" }, { "op": "add", "path": "/isComplete", "value": "true" },]Sample request:PATCH /Order/{orderNo} [ { "op": "test", "path": "/quantity", "value": "2" }, { "op": "test", "path": "/amount", "value": "38.28" }, { "op": "add", "path": "/isComplete", "value": "true" },]View Code
簡單介紹一下,
檔案后綴是http 或 rest
定義全域變數:@baseUrl = https://localhost:5001 ,注意鏈接不加引號
### 分割多個請求
POST/PUT 請求緊跟Head請求資訊,換行加上請求內容
Ctrl + Alt + R 快捷鍵 / 點Send Request發起請求格式化輸出
Api介面通常會是不同客戶端呼叫,這樣會有可能出現需要不同回應格式,例如常用的Json,XML,ASPNET Core 默認情況下是忽略 Accept 標頭,JSON格式回傳一、支持XML格式1. 添加xml格式化services.AddControllers(options => { options.RespectBrowserAcceptHeader = true; //接受瀏覽器標頭 }) .AddXmlSerializerFormatters(); //添加XMl格式化}
2. 請求是添加標頭
@orderId = {{order.response.body.*}}GET {{baseUrl}}/Order/{{orderId}} HTTP/1.1Accept: text/xml若不添加標頭,默認使用JSON格式輸出
二、URL格式映射
1. 添加[FormatFilter]過濾器,它會檢查路由中格式是否存在,并且使用相應的格式化程式輸出
2. 路由規則添加{format?}

[HttpGet("{id:int}.{format?}")]public ActionResult<Models.Order> GetById(int id){ var order = _orderStore.Orders.FirstOrDefault(m => m.Id == id); if (order == null) { return NotFound(); } return order;}View Code
| Url | 回應 |
|---|---|
| GET {{baseUrl}}/Order/{{orderId}} HTTP/1.1 | JSON(若配置格式化輸出) |
| GET {{baseUrl}}/Order/{{orderId}}.xml | XML(若配置格式化輸出) |
| GET {{baseUrl}}/Order/{{orderId}}.json | JSON(若配置格式化輸出) |
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson
2. 配置Newtonsoft.Json
public void ConfigureServices(IServiceCollection services){ services.AddControllers() .AddNewtonsoftJson(options => //添加基于NewtonsoftJson格式化 { options.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat; options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; });}JSON Patch請求
PUT 和 PATCH 方法用于更新現有資源, 它們之間的區別是,PUT 會替換整個資源,而PATCH 僅指定更改,
什么是JSON Patch?
JSON Patch官網 里面有一句介紹的很清楚:JSON Patch is a format for describing changes to a JSON document. (一種描述Json的變化的格式)
什么時候需要用到JSON Patch
- 我們回傳的JSON很大,修改可能只是某些欄位
- 對性能要求比較大的地方
- 一個大的物件,好幾個地方修改,然后統一介面修改
ASPNET Core如何處理JSON Patch 請求
1. 添加包支持
dotnet add package Microsoft.AspNetCore.JsonPatch
2. 使用 HttpPatch 屬性進行批注
3. 接受 JsonPatchDocument<T>,通常帶有 [FromBody]
4. 呼叫 ApplyTo 以應用更改
假設我們現在有一個完成訂單的需求
- 檢查金額,數量是否有變更
- 更新IsComplete = true
下面附上代碼和提交的JSON
控制器代碼

[HttpPatch("{orderNo:length(18)}")][ProducesResponseType(StatusCodes.Status200OK)][ProducesResponseType(StatusCodes.Status404NotFound)][ProducesResponseType(StatusCodes.Status400BadRequest)]public ActionResult<bool> Update([FromBody] JsonPatchDocument<Models.Order> patchDoc, [FromRoute] string orderNo){ var order = _orderStore.Orders.FirstOrDefault(m => m.OrderNo == orderNo); if (order == null) { return NotFound(); } patchDoc.ApplyTo(order, ModelState); if (!ModelState.IsValid) { return BadRequest(ModelState); } return Ok(true);}View Code
失敗的JSON(金額校驗不過)

PATCH {{baseUrl}}/Order/637109312996909246 HTTP/1.1Accept: application/jsonContent-Type: application/json[ { "op": "test", "path": "/quantity", "value": "2" }, { "op": "test", "path": "/amount", "value": "38.28" }, { "op": "add", "path": "/isComplete", "value": "true" },]View Code 
會在ModelState里面列出校驗不過的資訊
成功的JSON

PATCH {{baseUrl}}/Order/637109312996909246 HTTP/1.1Accept: application/jsonContent-Type: application/json[ { "op": "test", "path": "/quantity", "value": "2" }, { "op": "test", "path": "/amount", "value": "36.8" }, { "op": "add", "path": "/isComplete", "value": "true" },]View Code
我們用Get請求重新查一下,可以看到IsComplete成功被修改了

這里只是簡單介紹JSON Patch使用,更多使用方法參考JSON Pan官網 和 微軟檔案
Open API(Swagger)集成
Api 通常需要跟客戶端,前端進行溝通,需要撰寫檔案,這需要花費大量時間,
Open Api是專門解決這種問題,它為RESTful api定義了一個標準的、與語言無關的介面,利用工具生成檔案,可以做到代碼即檔案(逼著開發者完善注釋)
ASPNET Core 可以使用Swashbuckle.AspNetCore或NSwag 生成Swagger 檔案
下面介紹如何使用Swashbuckle.AspNetCore
一、使用Swashbuckle.AspNetCore
安裝Swashbuckle.AspNetCore包
dotnet add package Swashbuckle.AspNetCore
添加并配置 Swagger 中間件
參考命名空間:using Microsoft.OpenApi.Models;services.AddSingleton<Models.OrderStore>(); services.AddSwaggerGen(c =>{ c.SwaggerDoc("v1", new OpenApiInfo { Title = "Web Api Doc", Version = "v1" });});
app.UseSwagger(); app.UseSwaggerUI(c =>{ c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");});
經過上面兩步就可以使用SwaggerUI來查看檔案和測驗,瀏覽器打開(http://{url}/swagger)
二、添加XML注釋
上面生成的Swagger檔案是不包含XML注釋,下面介紹如何添加XML注釋
專案檔案(*.csproj)添加以下
<PropertyGroup> <GenerateDocumentationFile>true</GenerateDocumentationFile> <NoWarn>$(NoWarn);1591</NoWarn></PropertyGroup>加上上面生成檔案后,未注釋的函式,屬性會發出警告,警告代碼1591,忽略警告可以添加多個,分號分割
AddSwaggerGen添加下面XML支持
services.AddSwaggerGen(c =>{ c.SwaggerDoc("v1", new OpenApiInfo { Title = "Web Api Doc", Version = "v1" }); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath);});
方法添加注釋

/// <summary>/// 更新訂單指定資訊/// </summary>/// <remarks>/// Sample request:/// /// PATCH /Order/{orderNo} /// [/// {/// "op": "test",/// "path": "/quantity",/// "value": "2"/// },/// {/// "op": "test",/// "path": "/amount",/// "value": "38.28"/// },/// {/// "op": "add",/// "path": "/isComplete",/// "value": "true"/// },/// ]/// </remarks>/// <returns>回傳是否成功</returns>/// <response code="200">提交成功</response>/// <response code="400">提交引數例外</response> /// <response code="404">訂單號不存在</response>
View CodeProducesResponseType 描述回傳型別
remarks 會生成請求說明
效果


Web Api 使用就介紹這些,如有錯漏,希望指出,
轉發請標明出處:https://www.cnblogs.com/WilsonPan/p/11945856.html
示例代碼:https://github.com/WilsonPan/AspNetCoreExamples/tree/master/WebApi
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/86540.html
標籤:.NET Core

