基於 .NET 6 的輕量級 Webapi 框架 FastEndpoints

大家好,我是等天黑。

FastEndpoints 是一個基於 .NET 6 開發的開源 webapi 框架,它可以很好地替代 .NET Minimal APIs 和 MVC ,專門爲開發效率而生,帶來了全新的開發模式和編碼體驗。

另外對於 .NET 的中間件、認證、授權、日誌,依賴注入這些也都是支持的,甚至有些還進行了加強,所以你很快就可以上手它。

小試牛刀

接下來,我將用 FastEndpoints 創建一個 webapi 應用,展示它是如何使用的,真的非常簡單。

創建一個新項目

dotnet new web -n MyWebApp

進入項目

cd MyWebApp

安裝 Nuget 包

dotnet add package FastEndpoints

更新 Program.cs

global using FastEndpoints;

var builder = WebApplication.CreateBuilder();
builder.Services.AddFastEndpoints();

var app = builder.Build();
app.UseAuthorization();
app.UseFastEndpoints();
app.Run(); 

添加一個 Request DTO

public class MyRequest
{
    public int Age { get; set; }

    public string Name { get; set; }
}

添加一個 Response DTO

public class MyResponse
{
    public int Id { get; set; }
    public int Age { get; set; }

    public string Name { get; set; }

    public DateTime CreateTime { get; set; }
}

添加一個 Endpoint Class

然後添加下面的代碼, 這是處理業務邏輯的地方

public class MyEndpoint : Endpoint<MyRequest>
{
    public override void Configure()
    {
        Post("/api/user/create");
        AllowAnonymous();
    }

    public override async Task HandleAsync(MyRequest req, CancellationToken ct)
    {
        var response = new MyResponse()
        {
            Id = 1,
            Age = req.Age,
            Name = req.Name,
            CreateTime = DateTime.Now 
                
        };

        await SendAsync(response);
    }
}

準備工作都好了,直接啓動我們的 webapi 項目。

然後用 Postman 或者其他工具,向 /api/user/create 端點發送 POST 請求。

創建了一個用戶,並返回了用戶信息,就是這麼簡潔,這就是 FastEndpoints。

你可能注意到了上面的 Configure()方法,指定了 Http 動詞和端點。 當然,你也可以使用 .NET 原生的特性的方式,這也是支持的。

[HttpPost("/my-endpoint")]
[Authorize(Roles = "Admin,Manager")]
public class UpdateAddress : Endpoint<MyRequest, MyResponse>
{
    public override async Task HandleAsync(MyRequest req, CancellationToken ct)
    {
        await SendAsync(new MyResponse { });
    }
}

依賴注入

在 FastEndpoints 中,可以使用三種方式來訪問 IOC 容器中註冊的服務。

假設我們有一個 HelloWorldService 。

public interface IHelloWorldService
{
    string SayHello();
}

public class HelloWorldService : IHelloWorldService
{
    public string SayHello() => "hello world!";
}

並且註冊到 IOC 容器中。

builder.Services.AddScoped<IHelloWorldService, HelloWorldService>();

1. 構造函數注入

這是我們最熟悉的也是使用最多的方式。

public class MyEndpoint : EndpointWithoutRequest
{
    private IHelloWorldService _helloService;

    public MyEndpoint(IHelloWorldService helloScv)
    {
        _helloService = helloScv;
    }

    public override void Configure()
    {
        Get("/api/hello-world");
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        await SendAsync(_helloService.SayHello());
    }
}

2. 屬性注入

服務實例可以通過屬性的方式進行自動注入。

public class MyEndpoint : EndpointWithoutRequest
{
    public IHelloWorldService HelloService { get; set; }

    public override void Configure()
    {
        Get("/api/hello-world");
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        await SendAsync(HelloService.SayHello());
    }
}

3. 手動解析

也可以像下面這樣,直接手動獲取服務。

使用 TryResolveResolve() 方法。

public override async Task HandleAsync(CancellationToken ct)
{
    IHelloWorldService? helloSvc = TryResolve<IHelloWorldService>();

    if (helloSvc is null)
        ThrowError("service not resolved!");

    var logger = Resolve<ILogger<MyEndpoint>>();

    logger.LogInformation("hello service is resolved...");

    await SendAsync(helloSvc.SayHello());
}

預先解析的服務

下面的三個服務已經預先解析過,我們可以直接在處理程序中使用。

property: Config
service : IConfiguration

property: Env
service : IWebHostEnvironment

property: Logger
service : ILogger

非常方便地使用它們。

public override async Task HandleAsync(CancellationToken ct)
{
    Logger.LogInformation("this is a log message");
    var isProduction = Env.IsProduction();
    var smtpServer = Config["SMTP:HostName"];
    ...
}

架構模式

如果你寫過 Go Web,你會發現這是何等的相似。

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
    })

    http.ListenAndServe(":80", nil)
}

FastEndpoints 遵循了 REPR 設計 (Request-Endpoint-Response),這和我們常說的 MVC 模式是不一樣的。

思考一下,如果後端只是一個 webapi 應用,沒有 View, 那它就變成了 MC 架構 。是不是很奇怪,那爲什麼不用 REPR 模式呢?

從另外一個角度上說,“分層架構” 是我們很熟悉和經常使用的,代碼被分成不同的層。

這樣的好處也是顯而易見的。它們以解耦的方式組合在一起,在需要時,我們可以很方便的替換其中的層。

還有一種架構稱爲 “垂直切片架構", 系統的每個組件都是單獨的一塊,彼此並不影響,就像微服務那樣。

而 FastEndpoints 正是使用了下面的 “垂直切片架構"。

總結

如您所見,FastEndpoints 是一個靈活高效的 webapi 框架。另外它還有其他的功能,比如異常處理,集成和單元測試,限流,API 版本控制等等。

掃碼關注【半棧程序員】,獲取最新文章。

文檔: https://fast-endpoints.com/

Github: https://github.com/FastEndpoints

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章