使用 FastEndpoints 來垂直切割Web API的控制器方法

来源:https://www.cnblogs.com/wuhuacong/archive/2023/12/15/17903114.html
-Advertisement-
Play Games

在我們開發項目的Web API的時候,隨著項目功能要求越來越多,可能我們會為控制器基類增加越來越多的基礎功能,有些功能有一定的適應性,但可能在一般的子類中用不到,而隨著對控制器控制要求越來越精細,那麼需要為基類或者子類增加更多的控制功能,這樣隨著迭代的進行,有些控制器的功能會顯得越來越笨重。這個時候... ...


在我們開發項目的Web API的時候,隨著項目功能要求越來越多,可能我們會為控制器基類增加越來越多的基礎功能,有些功能有一定的適應性,但可能在一般的子類中用不到,而隨著對控制器控制要求越來越精細,那麼需要為基類或者子類增加更多的控制功能,這樣隨著迭代的進行,有些控制器的功能會顯得越來越笨重。這個時候,一種更加靈活、輕便的Web API處理方式,對每個控制器方法的垂直切割的API框架應運而生,本篇隨筆介紹的FastEndpoints 就是其中這樣的一款框架,本篇隨筆介紹一些FastEndpoints的基礎處理方法,並通過一些基礎的案例,把我們《 SqlSugar 開發框架》的一些模塊進行遷移性測試,對比相關後端Web API的處理,一起分享給大家。

1、FastEndpoints介紹

FastEndpoints 是Minimal API和MVC的開發人員友好替代品,它是基於REPR設計模式(請求-端點-響應),以便創建方便且可維護的端點,幾乎沒有樣板文件。

FastEndpoints 的性能與Minimal API 相當,甚至它更快,使用更少的記憶體並且每秒請求數比基準測試中的MVC控制器更高。對於比如:中間件、認證、授權、日誌,依賴註入這些常用功能都支持,甚至有些還進行了加強。

設計主要是分為兩種模式

分層模式:mvc、mvp、mvvm等
垂直模式:REPR設計模式
REPR設計模式就是垂直模式,系統的每個組件都是單獨的一塊,彼此並不影響,就像微服務那樣。

MVC - 模型-視圖-控制器旨在與用戶界面配合使用。顯然,視圖是一個 UI 組件。如果您正在構建 API,則沒有視圖,因此您充其量使用的是 MC 模式,或者您可以將其稱為模型-操作-控制器並獲取 MAC 模式。關鍵是,你已經沒有將MVC用於你的API,所以考慮一個更合適的模式應該不是一個很大的問題。

API 端點是非常獨立的,每個端點都可以使用三個組件來描述:

請求(Request):終結點所需的數據形狀
終結點(Endpoint):終結點在給定請求時執行的邏輯
響應(Response):終結點返回給調用方的響應
結合這三個元素,你會得到請求-端點-響應或 REPR 模式。

並非所有終結點都需要其請求或響應的實際數據,在某些情況下,不接收任何輸入或僅返回 HTTP 狀態代碼。但是,在此模式中,空請求或響應仍然是有效的請求或響應,就像某些 MVC 操作不需要模型一樣。

使用 API 端點庫時,您可以將請求、終端節點和響應類型分組在一起,這樣就無需在某些“視圖模型”或“dtos”文件夾中四處尋找合適的類型。它減少了摩擦,使使用單個端點變得更加容易。

FastEndPoint GitHub庫:https://github.com/FastEndpoints/FastEndpoints

FastEndpoints 線上文檔:https://fast-endpoints.com 

2、簡單例子入門

參考官方的文檔介紹,我們可以很容易的創建出一個簡單的類似Hello開篇的API應用。

我創建一個基於.net core的Web API項目,先把FastEndPoint的相關引用加入項目中,如下所示。

 然後在項目中的啟動類代碼中,我們添加相關的代碼使用FastEndpoints,如下所示。

using FastEndpoints;
using FastEndpoints.Swagger;

var bld = WebApplication.CreateBuilder();
bld.Services
   .AddFastEndpoints()
   .SwaggerDocument(); 

var app = bld.Build();
app.UseFastEndpoints()
   .UseSwaggerGen(); 
app.Run();

如果需要對Swagger進行一些定製修改,可以改動如下,這裡先忽略。

    .SwaggerDocument(o =>
    {
        o.DocumentSettings = s =>
        {
            s.Title = "SqlSugar框架介面API文檔";
            s.Version = "v1";
        };
        o.TagDescriptions = t =>
        {
            t["Test"] = "測試介面";
            t["User"] = "用戶相關介面";
        };
    })

為了簡便,我們以命名控制項不同,以及目錄,來區分不同的Web API分組,如下所示,我們創建一個基於Test的相關API介面。

對於以前的控制器介面來說,一般可能一個控制(如TestController)會包含多個方法,如上面的Create、List方法,這裡使用的是FastEndpoints,它們是把一個大型的控制器切換為一個方法一個類來處理,碎片化意味著類的增加,不過我們不需要做太多的工作,可以通過它們的一些基類來簡化這個過程。

我們把WebAPI中請求的Request和Response的對象,放在一個Model類文件裡面,如下代碼所示。

namespace FastWebApi.Controllers.Test
{
    /// <summary>
    /// 測試請求信息
    /// </summary>
    public class TestRequest
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }

    /// <summary>
    /// 測試返回信息
    /// </summary>
    public class TestResponse
    {
        public string FullName { get; set; }
        public bool IsOver18 { get; set; }
    }
}

我們來看看基於FastEndPoints方式 生成一個Create的請求Web API方法,如下代碼所示

namespace FastWebApi.Controllers.Test
{
    //客戶使用標識,不用覆蓋 Configure 函數
    //[HttpPost("/api/user/create")]
    //[AllowAnonymous]

    /// <summary>
    /// 創建記錄
    /// </summary>
    public class Create : Endpoint<TestRequest, AjaxResponse>
    {
        public override void Configure()
        {
            Post("/test/create");
            AllowAnonymous();
        }

        public override async Task HandleAsync(TestRequest req, CancellationToken ct)
        {
            var result = new TestResponse()
            {
                FullName = req.FirstName + " " + req.LastName,
                IsOver18 = req.Age > 18
            };
            await SendAsync(result.ToAjaxResponse());
        }
    }
}

我們配置Web API方法的路由,可以通過在Configure函數中指定: Post("/test/create")

也可以通過Attribute屬性標識的方式,來聲明,上面的註釋代碼所示。

[HttpPost("/api/user/create")]

這兩者是等同的,任何一種方式都可以,預設的介面是需要授權才能訪問的,如果我們標識了

[AllowAnonymous]

就可以匿名訪問Web API 的方法了,Web API的方法處理邏輯,都是統一通過重寫 HandleAsync 方法進行實現的,如上面代碼所示。

其中AjaxResponse 是我定義的一個統一返回結果,這樣我們的介面模型就一致了。

如下是Web API統一封裝後返回的結果對象。

如果需要瞭解我的《SqlSugar開發框架》的統一結果返回處理,可以參考《基於SqlSugar的資料庫訪問處理的封裝,在.net6框架的Web API上開發應用 》中的 【統一結果封裝和異常處理】 部分內容即可。

如果不需要統一返回模型,則可以自定義為任何的返回類型,如下是官方的案例所示。

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

    public override async Task HandleAsync(MyRequest req, CancellationToken ct)
    {
        await SendAsync(new()
        {
            FullName = req.FirstName + " " + req.LastName,
            IsOver18 = req.Age > 18
        });
    }
}

接下來,我們檢查下.netcore項目的launchSettings.json 配置信息

確保打開的時候就啟動Swagger頁面即可。

啟動Swagger頁面,我們來看看具體的效果,可以看到有兩個Test的介面,如下所示。

我們來調試Swagger,並測試下結果返回。

測試返回的結果如下所示,由於採用了統一返回結果的處理,這裡返回的TestResponse的對象序列化信息,放在了result的裡面了,如下所示。

而List的控制器方法,這裡沒有請求輸入的對象信息,因此參數為空。具體的API方法定義如下所示。

namespace FastWebApi.Controllers.Test
{
    /// <summary>
    /// 獲取所有記錄
    /// </summary>
    [HttpGet("/test/list")]
    [AllowAnonymous]
    public class List : EndpointWithoutRequest<AjaxResponse>
    {
        /// <summary>
        /// 處理返回
        /// </summary>
        public override async Task HandleAsync(CancellationToken ct)
        {
            var result = new List<TestResponse>()
            {
                new TestResponse
                {
                     FullName= "test",
                      IsOver18 = true,
                },
                new TestResponse
                {
                    FullName= "test 2",
                      IsOver18 = false,
                }
            };
           await SendAsync(result.ToAjaxResponse());
        }
    }
}

Swagger介面展示界面效果。

正常執行返回結果如下所示。

 如果處理過程中有異常,由於我們採用了統一返回結果處理,因此異常信息也需要統一在對象裡面,返回結果如下所示。

 以上就是簡單類型的一些處理例子,結合了統一返回結果的處理,我們可以很好的定義一個通用的結果返回。

 

3、對我們SqlSugar框架常規CRUD等基類介面進行垂直切割的處理

上面我們為了更好理解FastEndpoints的碎片化介面的處理,我們做了兩個簡單的方法來測試。

下麵我們通過對我們《SqlSugar開發框架》中的基類介面進行功能上的拆分,並結合實際業務的需要介面,進行擴展的處理,從而也實現了常規CRUD的操作介面,並實現特殊業務類的API介面處理。

關於Web API的常規介面處理 ,我們為了簡化代碼,往往抽象一些常規的CRUD方法在控制器基類中,這樣可以極大的減少了繼承子類的介面代碼,通過繼承基類,子類自動具備了CRUD的處理介面,只需要根據業務的需要,增加一些特殊的業務介面即可。

以前的處理方法,我們是根據項目的需要,我們定義了一些控制器的基類,用於實現不同的功能,如下界面所示。

其中ControllerBase是.net core Web API中的標準控制器基類,我們由此派生一個LoginController用於登錄授權,而BaseApiController則處理常規介面用戶身份信息,而BusinessController則是對標準的增刪改查等基礎介面進行的封裝,我們實際開發的時候,只需要開發編寫類似CustomerController基類即可。

而現在採用FastEndpoints ,需要垂直切割整個控制器,這種架構稱為 “垂直切片架構", 系統的每個組件都是單獨的一塊,彼此並不影響,就像微服務那樣。

我們需要把基類的介面實現放到具體的業務API類裡面,為了方便,可以給它們不同的名稱一個介面,或者組合在一個文件裡面,如下所示。

我們來看看其中給一個簡單的Count方法介面實現。

namespace FastWebApi.Controllers.User
{
    /// <summary>
    /// 根據條件計算記錄數量
    /// </summary>
    [HttpGet("/user/count")]
    public class Count : Endpoint<UserPagedDto, AjaxResponse>
    {
        /// <summary>
        /// 處理請求
        /// </summary>
        public override async Task HandleAsync(UserPagedDto req, CancellationToken ct)
        {
            var result = await BLLFactory<IUserService>.Instance.CountAsync(req);
            await SendAsync(result.ToAjaxResponse());
        }
    }
}

這裡可以採用介面註入的方式,也可以採用我們輔助類BLLFactory<IUserService>.Instance方法調用介面,一樣的實現。

這樣結合了業務的具體Service來處理,只需要簡單的處理下即可,也算比較方便,由於這些基礎的CRUD的方法,主要路由、分頁對象,業務對象,主鍵類型的不同,這些可以通過我們的代碼生成工具的處理快速生成即可,因此可以實現批量化的業務類的API介面方法生成。

至於具體的業務介面API,我們就需要手工處理了,如對於用戶的登陸獲取token的方法,我們這裡需要模仿來生成一個EndPiont類,如下所示。

    /// <summary>
    /// 根據用戶名、密碼驗證用戶身份有效性
    /// </summary>
    [HttpPost("/user/verify-user")]
    [AllowAnonymous]
    public class VerifyUser : Endpoint<VerifyUserDto, AjaxResponse>
    {
        /// <summary>
        /// 處理請求
        /// </summary>
        public override async Task HandleAsync(VerifyUserDto input, CancellationToken ct)
        {
            var result = await BLLFactory<IUserService>.Instance.VerifyUser(input.UserName, input.UserPassword, input.SystemType, input.IP, input.MacAddr);
            await SendAsync(result.ToAjaxResponse());
        }
    }

其他業務方法也是類似的處理,這裡的FastEndPoints的處理類,只是增加了一個簡單的包裝層就可以了,最後看看這些方法在SwaggerUI中的展示,和我們普通模式的Web API中的Swagger UI界面類似的效果。

 這樣,我們可以在保持介面一致性的情況下,無縫的對接新的Web API介面後端了。

專註於代碼生成工具、.Net/.NetCore 框架架構及軟體開發,以及各種Vue.js的前端技術應用。著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架等框架產品。
  轉載請註明出處:撰寫人:伍華聰  http://www.iqidi.com 
    

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在過去的幾十年的職業生涯中,我觀察到許多同事在技術方面取得了顯著的進步和能力提升。然而,隨著時間的推移,他們似乎逐漸遇到了一個發展的瓶頸。儘管大家都渴望以最快的速度提升自己的技能水平,但他們忽視了一個關鍵的因素,那就是內功修煉。 是的,我相信大家都知道我們所說的內功心法指的是《設計模式》。接下來,我 ...
  • Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹`QDateTime`日期與時間組件的常用方法及靈活運用。在Qt中,日期和時間的處理通常使用 `QDateTime... ...
  • 背景:供應商程式導出的文件是xls格式的,我需要使用Power Query將這些文件合併整理,但是目前沒有找到可以打卡xls文件的代碼,所以將xls文件轉化為xlsx文件後再使用Power Query進行處理。 思路: 1. 網上找到了將xls文件轉化為xlsx文件的代碼,將這個代碼定義為一個函數去 ...
  • ProgressBar(進度條)是在Qt中常用的用戶界面組件之一,用於顯示任務的完成進度。它通常以一個水平或垂直的條形圖形式展示,表示任務已完成的比例。進度條組件提供了一種直觀的方式來顯示任務的進度,讓用戶清晰地瞭解任務的完成情況。其還可根據需要在水平或垂直方向上顯示,以適應不同的界面佈局。 ...
  • 日常業務開發過程中,可能第三方的伺服器分佈在世界的各個角落,所以請求三方介面的時候,難免會遇到一些網路問題,這時候需要加入重試機制了,這期就給大家分享幾個介面重試的寫法。 重試機制實現 1. 迴圈重試 這是最簡單也最直接的一種方式。在請求介面的代碼塊中加入迴圈,如果請求失敗則繼續請求,直到請求成功或 ...
  • 數據的預處理是數據分析,或者機器學習訓練前的重要步驟。通過數據預處理,可以 提高數據質量,處理數據的缺失值、異常值和重覆值等問題,增加數據的準確性和可靠性 整合不同數據,數據的來源和結構可能多種多樣,分析和訓練前要整合成一個數據集 提高數據性能,對數據的值進行變換,規約等(比如無量綱化),讓演算法更加 ...
  • 為了實現一個包含靜態文件輸出、GET、POST 請求處理(含參數讀取)、文件上傳和下載功能的 Web API 服務,我們將使用 cpp-httplib 作為 HTTP 伺服器庫。首先,確保你已經安裝了該庫。 git clone https://github.com/yhirose/cpp-httpl ...
  • 獲取PDF文件中文字或圖片的坐標可以實現精確定位,這對於快速提取指定區域的元素,以及在PDF中添加註釋、標記或自動蓋章等操作非常有用。本文將詳解如何使用國產PDF庫通過C# 提取PDF中指定文本或圖片的坐標位置(X, Y軸)。 ✍ 用於操作PDF文件的第三方庫為Spire.PDF for .NET。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...