MASA Framework的MinimalAPIs應用

在以前的MVC引用程序中,控制器是一個功能齊全的框架,但它偏重,因此在.Net6.0官方引入了MinimalAPIs,即最小API,與MVC相比,它足夠的簡潔,適合小型服務來使用,下面就讓我們看看如何使用MinimalAPI來開發一個web應用程序

入門

下面我們來看一下官方提供的MinimalAPI是如何使用的

  • 前提條件:安裝.NET 6.0?(https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0)

1.新建ASP.NET Core 空項目Assignment.MinimalApiDemo

dotnet new web -o Assignment.MinimalApiDemo
cd Assignment.MinimalApiDemo

2.增加一個Get請求,修改Program

app.MapGet("/test", () => "Test Success!");

根據需求,自行增加Get?(MapGet)、Post?(MapPost)、Put?(MapPut)、Delete?(MapDelete)方法即可,完整代碼如下:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/test", () => "Test Success!");

MASA Framework版MinimalAPI

隨著我們的服務變得越來越多,這些服務全部被堆積在Program中,這樣豈不是變成流水賬式的代碼?那怎么做才能使得我們的代碼更加美觀呢?

下面我們就來看一下MASA Framework提供的MinimalAPIs?(https://github.com/masastack/MASA.Framework/blob/main/src/Contrib/Service/Masa.Contrib.Service.MinimalAPIs/README.zh-CN.md)是如何來使用的

1.選中項目Assignment.MinimalApiDemo,并安裝Masa.Contrib.Service.MinimalAPIs

dotnet add package Masa.Contrib.Service.MinimalAPIs --version 0.6.0-preview.13

2.注冊MASA Framework版的MinimalAPI,修改Program

var app = builder.AddServices();

3.新增加一個用戶的服務,新增UserService

public class UserService : ServiceBase
{public IResult Add(RegisterUserRequest request){//模擬添加用戶return Results.Ok();}
}

如何新建類目到這里已經結束了,可能會有小伙伴十分的疑惑,MASA Framework提供的方案讓我有點摸不著頭腦,但項目運行后就會發現在Swagger上多了一個服務

cb338ecfc004f6bc8e3002e4c859c123.png

細心的小伙伴發現了,這個服務好像是我們新增的添加用戶服務,但鏈接地址為什么是api/v1/Users?呢?讓我們接著往下看。

進階

通過快速入門我們了解到如何使用MinimalAPI,但我們也清楚流水賬式編程的危害,我們不希望讓項目中充斥著流水賬式的代碼,我們希望它是整潔的,并且是有跡可循的,這時候MASA提供的MinimalAPI方案進入了我們的視野,它上手難度極低,對我們來說它是很棒的,但如果我們不清楚它是如何設計的話,我們敢放心大膽的使用它嗎?雖然它有些枯燥,但我們必須要掌握它是如何設計的,它都支持了什么樣的功能

約定

當服務未禁用自動映射路由時,框架會自動掃描繼承ServiceBase的非抽象子類并注冊到服務集合中(IServiceCollection),并為滿足以下要求的方法自動注冊路由

  • 當前類的方法的訪問級別為public(不包含父類方法)

  • 方法上未增加特性IgnoreRouteAttribute

路由規則

路由規則優先級:

自定義路由 > 約定生成路由

  1. 如何自定義路由?

通過RoutePattern特性我們可以為方法自定義路由

[RoutePattern("user/add")]
public IResult Add([FromBody]RegisterUserRequest request)
{//模擬添加用戶return Results.Ok();
}
  1. 約定的生成路由規則為:

Pattern(路由) = BaseUri + RouteMethodName

  • BaseUri: 根地址,默認: null

    • BaseUri或者null時,則?BaseUri = Prefix/Version/ServiceName

  • RouteMethodName: 除非自定義RouteMethodName,否則RouteMethodName = GetMethodName(方法名)

GetMethodName:

  1. TrimStart:Get/Post/Create/Put/Update/Delete/Remove?等

  2. TrimEnd:Async

PS:/api/v1/User/Add,將會變成/api/v1/User

當方法的參數存在id并且id支持從Route中獲取時,將會變成/api/v1/User/{id},如果id為可空或者存在默認值時,將會變成/api/v1/User/{id?}

配置

配置分為全局配置、局部配置(僅在當前服務生效),其中優先級為:局部配置 > 全局配置,默認局部配置的參數為null,我們約定局部參數未配置時,以全局配置為準

全局配置

  • DisableAutoMapRoute: 是否禁用自動映射路由,如果為true (禁用),則框架不會自動映射路由,默認:false

  • Prefix: 前綴,默認: api

  • Version: 版本,默認: v1

  • AutoAppendId: 是否追加Id,默認: true

  • PluralizeServiceName: 服務名稱是否啟用復數,默認: true

  • GetPrefixes: 用于識別當前方法類型為Get請求,默認:?new List<string> { "Get", "Select" }

  • PostPrefixes: 用于識別當前方法類型為Post請求,默認:?new List<string> { "Post", "Add", "Upsert", "Create" }

  • PutPrefixes: 用于識別當前方法類型為Put請求,默認:?new List<string> { "Put", "Update", "Modify" }

  • DeletePrefixes: 用于識別當前方法類型為Delete請求,默認:?new List<string> { "Delete", "Remove" }

  • DisableTrimMethodPrefix: 禁用移除方法前綴(Get/Post/Create/Put/Update/Delete/Remove?等), 默認: false

  • MapHttpMethodsForUnmatched: 匹配請求方式失敗使用,默認: 支持Post、Get、Delete、Put

  • Assemblies: 用于掃描服務所在的程序集,默認:?AppDomain.CurrentDomain.GetAssemblies()

  • RouteHandlerBuilder: 基于RouteHandlerBuilder的委托,可用于權限認證、Cors等

局部配置

  • BaseUri: 根地址,默認: null

  • ServiceName: 自定義服務名,默認: null

  • RouteHandlerBuilder:基于RouteHandlerBuilder的委托,可用于權限認證、Cors等

  • RouteOptions: 局部路由配置

    • DisableAutoMapRoute

    • Prefix

    • Version

    • AutoAppendId

    • PluralizeServiceName

    • GetPrefixes

    • PostPrefixes

    • PutPrefixes

    • DeletePrefixes

    • DisableTrimMethodPrefix

    • MapHttpMethodsForUnmatched

其中ServiceName為null時,

ServiceName = 類名.TrimEnd("Service")?//不區分大小寫

特性

RoutePattern

用于自定義路由,支持參數

  • Pattern: 自定義路由或自定義方法名

    • 當StartWithBaseUri:true,Pattern為自定義方法名

    • 當StartWithBaseUri:false,Pattern為自定義路由

  • StartWithBaseUri: 是否基于BaseUri進行追加,默認: false

  • HttpMethod:請求類型,默認: null(根據方法名前綴自動識別),如果希望指定請求類型而非自動識別,則可手動指定:GetPostPutDelete

IgnoreRoute

用于忽略方法自動映射,例如;存在某個方法已經手動指定映射路由,不希望框架重復進行映射可使用IgnoreRoute, 例如:

public class User2Service : ServiceBase
{public User2Service(){App.Map("/api/v2/user/add", Add);}[IgnoreRoute]public void Add([FromBody] RegisterUserRequest request, IData data){data.Add(request.Name, request.Age);}
}

場景

通過上面的學習我們已經了解到了MASA提供了哪些配置,那下面就讓我們實戰來演練一下,通過模擬不同的場景使用不同的配置,以確保我們正確掌握這些知識

場景一:

Q: 我不是一個新手,從0.6.0版本以前的版本就開始使用MASA提供的MinimalAPI了,對新版的MinimalAPI很喜歡,但我暫時不希望更改手動注冊的方式,我希望升級之后不會對我現有的項目造成影響,我不希望將升級導致原來的服務無法訪問

A: 你希望繼續使用最新版的MinimalAPI,但不希望對原來的項目造成影響,在當前服務中,希望能一如既往的使用手動注冊,而不是自動注冊,那你可以配置全局禁用自動注冊,例如:

var app = builder.AddServices(options =>
{options.DisableAutoMapRoute = true;
});

當然如果你希望在某個特定的服務中開啟自動映射,則可以在服務中配置:

public class UserService: ServiceBase
{public UserService(){RouteOptions.DisableAutoMapRoute = false;}public void Add([FromBody] RegisterUserRequest request, IData data){data.Add(request.Name, request.Age);}
}

場景二:

Q: 我是一個新手,我覺得我的項目不需要使用前綴以及版本,我希望自動映射的路由可以幫助我刪掉它們

A: 你需要的是全局配置,通過全局配置禁用前綴以及版本即可,例如:

var app = builder.AddServices(options =>
{options.Prefix = string.Empty;options.Version = string.Empty;
});

場景三:

Q: 我是一個新手,雖然我很想嚴格遵守Resetful標準來寫服務,但遺憾的是我無法掌控全局,總是有人不按照標準對方法進行命名,我希望可以人為控制特定的方法的路由

A: 目前有兩種方法可供選擇,它們分別是:

第一種:自定義路由并忽略自動映射

public class UserService : ServiceBase
{public UserService(){App.Map("/user/add", Add);}[IgnoreRoute]public void Add([FromBody] RegisterUserRequest request, IData data){data.Add(request.Name, request.Age);}
}

第二種: 完整自定義路由

public class UserService : ServiceBase
{[RoutePattern("/api/v2/user/add")]public void CreateUser([FromBody] RegisterUserRequest request, IData data){data.Add(request.Name, request.Age);}
}

第三種: 僅修改請求方式

public class UserService : ServiceBase
{[RoutePattern(HttpMethod = "Post")]public void CreateUser([FromBody] RegisterUserRequest request, IData data){data.Add(request.Name, request.Age);}
}

如果你希望手動指定方法的請求類型,則可以使用[RoutePattern("/api/v2/user/add", HttpMethod = "Post")]

場景四:

Q: 我希望為項目中所有的接口都必須授權才能訪問,但我不希望在每個方法上增加Authorize特性

A: 你的項目是需要為全局服務來設置,則可通過全局配置的RouteHandlerBuilder參數來完成,例如:

var app = builder.AddServices(options =>
{options.RouteHandlerBuilder = routeHandlerBuilder => routeHandlerBuilder.RequireAuthorization();
});

如果你希望對某個服務增加特殊的授權策略,則可以:

public class UserService : ServiceBase
{public UserService(){RouteHandlerBuilder = routeHandlerBuilder => routeHandlerBuilder.RequireAuthorization("test");}public void CreateUser([FromBody] RegisterUserRequest request, IData data){data.Add(request.Name, request.Age);}
}

但是你必須知道的是,如果在服務內配置了RouteHandlerBuilder,那么全局配置的RouteHandlerBuilder將對當前服務失效,局部配置存在時,全局配置將不起作用

場景五:

Q: 我希望某個服務不需要經過授權即可訪問,那我該怎么做?
A: 只需要在方法上加AllowAnonymous特性即可, 它是MinimalAPI支持的,除了AllowAnonymousEnableCorsAuthorize等都是支持的, 但HttpGetHttpPostHttpPutHttpDelete特性是不支持的

public class UserService : ServiceBase
{[AllowAnonymous]public void CreateUser([FromBody] RegisterUserRequest request, IData data){data.Add(request.Name, request.Age);}
}

常見問題

Q1:為何使用DbContext時總是提示DbContext已經被釋放?

A:UserService僅在項目啟動時會被初始化一次,之后不再初始化,因此Service的構造函數參數僅支持SingletonTransient。如果您的服務的生命周期為Scoped,建議在對應的方法中增加參數,例如:

public void Add([FromBody] RegisterUserRequest request, IData data)
{data.Add(request.Name, request.Age);
}

Q2:模型校驗不起作用?

A:目前版本的MinimalAPI并不支持模型綁定與驗證,后續版本(https://github.com/dotnet/aspnetcore/issues/39504)會增加支持

Q3:Builder.AddServices()又為什么必須要放到最后?

A:我們知道通過builder.Build()可以得到WebApplication,但在.Net6.0中新增加了限制,這個限制就是在Build后無法再次更新IServiceCollection,否則會提示Cannot modify ServiceCollection after application is built

Q4:為什么MinimalAPIs的生命周期是單例?

A:目前AddServices方法中做了兩件事,第一件事就是獲取到所有的服務,并注冊到服務集合中,第二件事就是觸發服務并將對應服務的地址以及方法映射到到AppApp.Map類似App.Use,也是一個擴展方法,類似MVC的路由,其生命周期是單例,我們僅僅是將繼承ServiceBase的服務映射到App中,并沒有魔改MinimalAPI,因此并不存在性能問題,但同樣其生命周期也無法改變

總結

MinimalAPIMVC我應該如何選擇?

小型服務使用MinimalAPI,因為它是很輕量級的,但如果是大型服務或者功能特別復雜的,還是推薦使用MVCMinimalAPI的上手成本很低,但它不是銀彈,選擇適合自己的才是最好的

MinimalAPI還有一些特殊的地方,例如Get請求無法使用類對象來接收參數,如果希望使用類對象來接受,

則需要使用自定義綁定? (https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0#custom-binding)

除此之外還有其他不一樣的地方

完整文檔可查看(https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0)

本章源碼

Assignment14

https://github.com/zhenlei520/MasaFramework.Practice

開源地址

MASA.Framework:https://github.com/masastack/MASA.Framework


如果你對我們的 MASA Framework 感興趣,無論是代碼貢獻、使用、提 Issue,歡迎聯系我們

4b43b72ac6b694e93c6b9c85b444b02f.png

44373e92bee8eac49fe35bad72974456.gif

《MASA?Framework實戰課程》已開課

點擊“閱讀原文”查看課程安排

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282480.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282480.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282480.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【轉】Java開發必須要知道的知識體系

Java Java是一門超高人氣編程語言&#xff0c;擁有跨平臺、面向對象、泛型編程等特性。在TIOBE編程語言排行榜中&#xff0c;連續奪得第一寶座&#xff0c;而且國內各大知名互聯網公司&#xff0c;后端開發首選語言&#xff1a;非Java莫屬。今天只是梳理下Java知識體系&#xf…

CrossPHP--在我們用ajax,js取不到指定數據時,我們可以換一種方式

項目中遇到的問題: 需求: 用的是layui的laypage組件,進行分頁操作,熟悉layui的朋友都知道,laypage需要從服務端給其一個總條數, 但是在進行ajax請求時出了問題, 我是這樣定義的但是調用的時候卻無法將數值直接返回回去,所以這里只能更換一種思路 在控制器中進行數據的查詢,然后…

VS 代碼行數統計

按CTRLSHIFTF (Find in files)&#xff0c;勾上支持正則表達式&#xff0c;然后輸入搜索內容&#xff1a; ^:b*[^:b#/].*$#開頭和/開頭或者空行都不計入代碼量。如果需要只統計代碼文件的代轉載于:https://www.cnblogs.com/sunlyk/p/7484728.html

MySQL設置從庫只讀模式

常見現象 運維工作中會經常維護MySQL主從服務器&#xff0c;當然Slave我們只是用于讀操作。 一般權限開通也只授權只讀賬號&#xff0c;但是有時候維護工作可能不是一個人在做&#xff0c;你不能保證其他同事都按照這個標準操作。 有同事可能會授權Slave庫MySQL賬號為all或者se…

尋找kernel32.dll的地址

為了尋找kernel32.dll的地址&#xff0c;可以直接輸出&#xff0c;也可以通過TEB,PEB等查找。 尋找TEB: dt _TEB nt!_TEB 0x000 NtTib : _NT_TIB 0x01c EnvironmentPointer : Ptr32 Void 0x020 ClientId : _CLIENT_ID 0x028 ActiveRpcHandle : Ptr32 Void 0x02c ThreadLocalSto…

layui彈出層使用(layer.alert / layer.open / layer.prompt )

一 layer.alert 效果圖: 代碼: //取消提現 function back(id) {layer.alert(真的要取消嗎, {skin: layui-layer-molv //樣式類名 自定義樣式,closeBtn: 1 // 是否顯示關閉按鈕,anim: 1 //動畫類型,btn: [確定,取消] //按鈕,icon: 6 // icon,yes:function(){return $.aj…

SkiaSharp 自繪彈幕效果

SkiaSharp 自繪彈幕效果控件名&#xff1a;SkiaSharpBarrage作者&#xff1a; 驚鏵原文鏈接&#xff1a; https://github.com/yanjinhuagood/SkiaSharpBarrage框架使用.NET60&#xff1b;Visual Studio 2022;項目使用 MIT 開源許可協議&#xff1b;接著上一篇 WPF 彈幕上期有…

JavaScript中this指向

一.重點來了&#xff0c;this指向問題&#xff1a;1.this指向之普通函數。 2.this指向之對象 3.this指向之構造函數 4.this指向之&#xff08;call,apply&#xff09;動態更改this指向。 二.具體分析如下 1.普通函數 // 第23行的調用者為null,this指向也為null,// 所以這時js把…

【python】python中的定義類屬性和對像屬性

python中變量是沒有類型的可以綁定任意類型&#xff0c;但是在語法上不能聲明變量。 那我們怎麼來聲名一個變量呢&#xff1f; fNone 這樣我們給著個變量綁定了以各None類型&#xff0c;我們隨時可用重新綁定其它類型。這樣我們起到了預先聲名變量的效果。 類中如何去定義類的…

提交Form表單,submit之前做js判斷處理

效果:在點擊提交按鈕時,首先進行js判斷, 如果不符合條件,則alert出提示信息,并return false. 主要點就在于給form表單添加一個onsubmit事件. 在onsubmit事件中定義的函數里進行js驗證處理.代碼 : <!DOCTYPE html> <html lang"en"> <head><meta …

如何在Windows上一鍵部署PaddleOCR的WebAPI服務

PaddleOCR旨在打造一套豐富、領先、且實用的OCR工具庫&#xff0c;助力開發者訓練出更好的模型&#xff0c;并應用落地。官方開源項目地址&#xff1a;https://github.com/PaddlePaddle/PaddleOCR一定會有小伙伴們看完不知道如何部署與應用&#xff0c;怎么才能融入到自己的產品…

微軟為 Visual Studio 擴展添加對 Arm64 的支持

微軟在 6 月份推出了支持 Arm64 架構的 Visual Studio&#xff0c;這是第一個原生支持在基于 Arm 的處理器上構建和調試 Arm64 應用程序的 Visual Studio 版本。近日&#xff0c;他們宣布為 Visual Studio 擴展也添加了對 Arm64 的支持&#xff0c;因此開發者可在 Arm64 Visual…

WIN10 查看已經連接的wifi的密碼

命令行: 1. 顯示以前連接過的wifi2. 將wifi配置存入文件中3. 查看剛剛保存的wifi配置的文件這樣,我們就可以看到連接的wifi名稱和wifi密碼了.

ubantu 重啟mysql

如何啟動/停止/重啟MySQL一、 啟動方式1、使用 service 啟動&#xff1a;service mysql start2、使用 mysqld 腳本啟動&#xff1a;/etc/inint.d/mysql start3、使用 safe_mysqld 啟動&#xff1a;safe_mysql&二、停止1、使用 service 啟動&#xff1a;service mysql stop2…

C++ 反射機制的簡單實現

C并不支持反射機制&#xff0c;只能自己實現。 如果需要實現字字符串到函數到映射&#xff0c;一定要使用到函數指針。 簡單實現反射機制&#xff0c;根據字符串來構造相應到類。主要有以下幾點&#xff1a; (1) 可以使用map保存字符從到函數指針到映射。 (2) 工廠類提供字符串…

微軟與 Canonical 合作,將 systemd 引入 WSL

微軟和 Canonical 聯合宣布&#xff0c;systemd 現在可以在 Windows Subsystem for Linux&#xff08;WSL2&#xff09;中運行了&#xff0c;此舉可以讓用戶在 Windows 設備上獲得更加全面的 Linux 體驗。systemd 的作者 Lennart Poettering 在 7 月份離開紅帽并加入了微軟&…

vsftpd配置

1.) yum install -y vsftpd 2.) useradd -g ftp -s /sbin/nologin afcupload (默認生成/home/afcupload, 可使用 -d參數自定義主目錄生成位置) 3.) passwd afcupload 4.) chgrp -R ftp afcupload 5.) chown -R afcupload:ftp afcupload 6.) chmod -R 700 afcupload 4.) 修…

2017.9.6數學

集合&#xff1a;一個可以代表一類事物或數據的代詞。&#xff08;個人定義&#xff09; &#xff08;其內容帶有輔助功效【個人記不下來】&#xff09;自然數&#xff1a;所有的非負整數。 有理數&#xff1a;是可以用正數和分數代表的數。實數&#xff1a;包括有理數和無理數…

.NET 反向代理-YARP 根據域名轉發

編者&#xff1a;fastgithub 就是基于YARP使用域名做轉發邏輯的。 前段時間發布過一個關于 YARP 的簡單介紹&#xff0c;感興趣的小伙伴恭請移步看看 .NET 反向代理-YARP 作為反向代理&#xff0c;必不可少的當然是根據域名代理轉發啦&#xff0c;毫無疑問&#xff0c;YARP…