.Net Minimal Api 介紹

Minimal API是.Net 6中新增的模板,藉助C# 10的一些特性以最少的程式碼運行一個Web服務。本文脫離VS通過VS Code,完成一個簡單的Minimal Api項目的開發。

創建項目

隨便新建一個文件夾,用來管理我們的項目文件,文件夾內啟動命令行,通過`dotnet new web`創建項目。

 還是一堆文件,什麼時候一個Program.cs文件就能跑起一個Web項目沒準哪天也可以了

運行項目

項目目錄下執行`dotnet run`,運行項目。

嘗試玩點花的用網頁版VS Code (//vscode.dev/)運行項目,不過並沒有我想像中那麼強,還不支援。

 Coding

builder實例提供了Services屬性,可以完成原本Startup類ConfigureServices方法中註冊服務的工作,Configure方法的一些Use操作則通過app來完成。

builder.Services.AddMemoryCache();

//todo
 app.UseStaticFiles();
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", $"{builder.Environment.ApplicationName} v1"));
}

MapGet變種

通過Build出來的app實例的MapGet方法實現路由的映射。

app.MapGet("/", () => "Hello World!");
//app.Map("/",[HttpGet] () => "Hello World!");
//app.MapMethods("/", new List<string>() { HttpMethod.Get.ToString() }, () => "Hello World!");

可以看到通過Delegate的方式可以直接在Delegate前加上對應的特性。async關鍵字同樣可以直接標記在Delegate前。

路由映射感覺還差點意思。不能像其它語言框架一樣進行不同版本的管理,如:

var api = app.Part("v1",middleware);
api.MapGet("", () =>{ return ""; });

Application

程式碼內直接修改應用程式配置,如修改監聽埠

app.Urls.Add("//localhost:3000");
//app.Urls.Add("//localhost:4000");
//app.Run();
app.Run("//localhost:4000");

 優先順序 app.Run > app.Urls.Add > launchSettings

Dependency Injection

Minimal API中無法使用構造函數注入,可以通過參數方式注入,可以忽略掉FromServices特性的標記。

Context

一些Http請求的上下文資訊也可以通過參數直接指定,方法體內直接使用,代替MVC中的Request等。如:

  • HttpContext
  • HttpRequest
  • HttpResponse
  • ClaimsPrincipal
  • CancellationToken
app.MapGet("/context", (HttpContext httpContext) => new 
{
    Data = httpContext.Connection.Id
});

更多類型參考:github

Responses

通過靜態類Results返回標準的相應類型,實現和ControllerBase提供對應方法相同的效果。

app.MapGet("/ok/{id}", (int id) =>
{
    return Results.Ok($"ok:{id}");
});

通過擴展方法WithXXX等可以對路由進行一些配置,如通過WithName指定名稱,再通過LinkGenerator生產對應Uri,避免硬編碼

app.MapGet("/context", (HttpContext httpContext) => new
{
    Data = httpContext.Connection.Id
}).WithName("hi");
app.MapGet("hello", (LinkGenerator linker) =>
        $"The link to the hello route is {linker.GetPathByName("hi", values: null)}");

除了WithXXX等一些列RoutingEndpointConvention擴展方法外,還提供了AuthorizationEndpointConvention相關擴展方法RequireAuthorization、AllowAnonymous代替MVC模式中的相關特性(特性也還可以用只是多了一個支援方式)。

本文只列出Minimal API的一些簡單用法,集成Swagger等用法內容參考://minimal-apis.github.io/hello-minimal/

介面的返回狀態碼和類型等可以通過擴展方法Produces說明,如:Produces<ResponseMode>(contentType:”application/xml”); ,但是介面備註貌似還不支援,我嘗試了很多方式都不能正確顯示。

Code Format

Minimal API上面示例存在的問題是Program文件中會有太多的編碼,所有路由的映射和響應都在一起,雖然可以通過如下方式使用靜態方法抽離響應方法,但所有的Route Map還是列在一起,不能像Controller一下分離。

var handler = new HelloHandler();

app.MapGet("/", handler.Hello);

class HelloHandler
{
    public string Hello() 
    {
        return "Hello World";
    }
}

可以藉助開源框架MASA.Contrib提供的MASA.Contrib.Service.MinimalAPIs完成程式碼封裝。

詳細用法參考MASA.EShop