通俗理解.NET 6 Minimal APIs

微軟技術棧發表於2022-02-28

.NET 6,微軟稱為“最快的.NET”,帶有了許多令人興奮的新功能、語言和效能改進。這是自 .NET Core 3.1 以來的第一個 LTS 版本,將支援三年。本次大版本釋出,增加了一個新特性:Minimal APIs,這是什麼技術?

.NET6 使編寫具有最小依賴性的 REST API 變得非常簡單。

Minimal APIs 似乎是微軟對 NodeJS(使用 ExpressJS)HTTP 伺服器的回應,它提供了最小的 API。但是微軟也對這項技術增加了幾個關鍵詞:

總結一句話:.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 看看裡面的內容,有一個配置:

<ImplicitUsings>enable</ImplicitUsings>

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 設計和實現:

▌先準備好 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);
        }
    }
}

▌在 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 的區別

using NET6;

然後,在 ASP.NET DI 依賴注入框架中新增 IOrderService 服務:​​​​​​​

//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");

▌執行除錯

在終端中輸入 dotnet run 指令,啟動執行除錯

dotnet run

除錯這3個 API,建議大家使用 PostMan 工具

先說一個小坑,一開始使用 PostMan 工具除錯儲存訂單介面,將 order 顯式地引數放到 Headers 中請求,結果一直不通:

看了微軟的示例文件後,建議直接將 order json 物件,http 請求體中以 raw 的方式發起請求

其他的 API 介面則沒有這個問題:

以上是.NET 6 Minimal APIs 的一些簡單介紹和實踐,希望能幫助大家。

點選檢視使用ASP.NET Core建立Minimal Web API教程

相關文章