.NET 6,微軟稱為“最快的.NET”,帶有了許多令人興奮的新功能、語言和效能改進。這是自 .NET Core 3.1 以來的第一個 LTS 版本,將支援三年。
本次大版本釋出,增加了一個新特性:Minimal APIs,這是什麼技術?
.NET6 使編寫具有最小依賴性的 REST API 變得非常簡單。
乍一看,Minimal APIs 似乎是微軟對 NodeJS(使用 ExpressJS)HTTP 伺服器的回應,它提供了最小的 API。
但是微軟也對這項技術增加了幾個關鍵詞
- LightWeight,Single file,Cloud Native API
- Low ceremony,Top-Level C# programs
- Easy to get started
- Path to MVC
總結一句話:.NET 6 Minimal APIs 簡化了HTTP Rest API的設計和實現,讓開發者快速高效實現HTTP Rest API。
今天,我們花點時間,研究併科普一下.NET 6 Minimal APIs。
一、先看一下.NET 6 Minimal APIs的示例程式碼
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
在上面的示例中,app.MapGet 方法使用了內聯 lambda 表示式,完成一個Controller Action的業務邏輯,真的是超簡單。
超簡單完成一個HTTP WebAPI的定義:不再有 Startup.cs、API 控制器、額外依賴項等。
只需要這 4 行程式碼即可生成以下輸出:
二、探究一下這段程式碼背後的一些技術
上面的程式碼,微軟官方文件上,建議大家使用VS2022,其實用VS Code也可以
Tutorial: Create a minimal web API with ASP.NET Core
但是本機得先安裝.NET 6 SDK
安裝完成後,開啟VS Code,新建終端,建立一個Web Project
dotnet new web -o MyMinimalAPI
程式碼工程中,我們可以看到:
Program.cs這個類中沒有using了,當然也沒有main函式了,這裡跟大家解釋一下:
① .NET5 引入了Top-Level Class,可以沒有main函式,程式碼作為直接入口執行
② .NET 6 新增了一個很棒的新特性——“隱式全域性使用”
自動生成不可見的 using 語句並在全域性範圍內宣告它們,因此不必處理在每個檔案中重複宣告名稱空間的混亂。
我們開啟MyMinimalAPI.csproj 看看裡面的內容,有一個配置:
dotnet build後,找到obj/Debug/net6.0 資料夾以檢視隱藏的自動生成檔案 - [ProjectName].GlobalUsings.g.cs。您可以定義一個單獨的類來將所有 using 語句儲存在一個地方。
這個功能,讓我們不需要在每個檔案中重複宣告名稱空間的using引用了。的確很方便、簡單了。
當然,如果不想使用此功能,可以禁用 .csproj 檔案中的ImplicitUsings標誌。
在上面的示例中,app.MapGet 方法使用了內聯 lambda 表示式。同時還提供了:
app.MapPost()
app.MapPut()
app.MapDelete()
接下來,我們用一個簡單的示例,完成一個demo;
三、完成一個Minimal APIs完整的Demo
我們以一個簡單Order訂單為例,通過Minimal APIs實現CRUD設計和實現:
3.1 先準備好Order類和IOrderService介面以及OrderServiceRepository
Order類:
namespace NET6 { public class Order { public int ID {get;set;} public decimal Price {get;set;} public string CustomAddress {get;set;} public int State{get;set;} } }
IOrderService介面:
namespace NET6 { public interface IOrderService { Order GetOrder(int id); void CreateOrder(Order order); void DeleteOrder(int id); void UpdateOrder(Order order); } }
OrderServiceRepository類,使用記憶體集合模擬實現資料儲存層。
namespace NET6 { public class OrderServiceRepository : IOrderService { static List<Order> orders = new List<Order>(); public Order GetOrder(int id) { return orders.FirstOrDefault(i=>i.ID == id)?? null; } public void CreateOrder(Order order) { orders.Add(order); } public void DeleteOrder(int id) { var order = orders.FirstOrDefault(i=>i.ID == id); if(order!=null) orders.Remove(order); } public void UpdateOrder(Order order) { DeleteOrder(order.ID); CreateOrder(order); } } }
3.2 在Program.cs類中,註冊IOrderService服務,新增AddOrder和GetOrder Http Web API
using NET6; var builder = WebApplication.CreateBuilder(args); //registe IOrderService service builder.Services.AddScoped<IOrderService, OrderServiceRepository>(); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); //add order save API app.MapPost("/add",(Order order,IOrderService service)=> { service.CreateOrder(order); }).WithName("addorder"); //add order query API app.MapGet("/getorder",(int id, IOrderService service)=> { return service.GetOrder(id); }).WithName("getorder"); app.Run();
上面的低碼中,首先增加一個檔案級別的namespace,這個地方為了和大家示意Global Namespace的區別
//registe IOrderService service
builder.Services.AddScoped<IOrderService, OrderServiceRepository>();
新增訂單Order 儲存API服務:
//add order save API app.MapPost("/add",(Order order,IOrderService service)=> { service.CreateOrder(order); }).WithName("addorder");
上面這個HttpWebAPI,我們採用了Post方式,請求是必須傳入order引數。
這個程式碼中,我們看到儲存訂單方法有2個引數,一個是Order,另一個是IOrderService,第二個引數,原生支援依賴注入,不需要顯式宣告建立。
類似的,繼續新增查詢訂單API服務
//add order query API app.MapGet("/getorder",(int id, IOrderService service)=> { return service.GetOrder(id); }).WithName("getorder");
3.3 執行除錯
在終端中輸入dotnet run指令,啟動執行除錯
dotnet run
除錯這3個API,建議大家使用PostMan工具
先說一個小坑,一開始使用PostMan工具除錯儲存訂單介面,將order顯式地引數放到Headers中請求,結果一直不通:
看了微軟的示例文件後,建議直接將order json物件,http請求體中以raw的方式發起請求
其他的API介面則沒有這個問題:
好了,以上是.NET 6 Minimal APIs的一些簡單介紹和實踐,希望能幫助大家。
周國慶
2022/2/28