接觸到動態WebApi(Dynamic Web API)這個詞的已有幾年,是從ABP框架裏面接觸到的,當時便對ABP的這個技術很好奇,後面分析了一波,也嘗試過從ABP剝離一個出來做爲獨立組件來使用,但是後來因與ABP依賴太多而放棄。十幾天前朋友 熊貓 將這部分代碼(我和他在搞事情)成功的從 ABP 中剝離出來並作了一個簡單Demo扔給我,通過這麼久(實在是太懶^_^)終於通過一些修改、添加功能、封裝,如今已經能做爲一個獨立組件使用,項目開源在Github(https://github.com/dotnetauth/Panda.DynamicWebApi),但願以爲有用的朋友能給一個 Star 支持一下。git
本文只講使用,不講原理,原理放到後面的文章中詳細介紹。github
無論是傳統的三層架構、 DDD 經典四層架構(DDD Lite),亦或是其餘具備應用邏輯層(業務邏輯層)的架構,在Web應用程序開發當中 ,咱們的業務邏輯最終都須要通過 Web Api 來進行調用,這裏咱們可能會有一個重複的操做:編寫業務邏輯->編寫API調用業務邏輯,這種重複性的操做有沒有解決辦法呢,咱們編寫完業務邏輯之後便給咱們自動生成WebApi,答案固然是有的。web
這裏介紹一下本文的主角:Panda.DynamicWebApi
(https://github.com/dotnetauth/Panda.DynamicWebApi)。源自於ABP的一個可獨立使用的,可自動爲你的業務邏輯層生成 ASP.NET Core WebApi 層的開源組件。它生成的API符合Restful風格,能夠根據符合條件的類來生成WebApi,由MVC框架直接調用邏輯,無性能問題,完美兼容Swagger來構建API說明文檔。shell
這裏以 DDD 經典四層架構中的應用邏輯層來說解。json
(1)創建兩個項目一個是應用邏輯層類庫項目;一個是做爲生成WebApi Host,ASP.NET Core WebApi項目api
(2)編寫應用邏輯瀏覽器
定義一個應用邏輯接口,全部應用邏輯都應實現它:架構
public interface IApplicationService { }
定義一個學生管理邏輯接口,繼承應用邏輯接口app
public interface IStudentAppService : IApplicationService { /// <summary> /// 根據ID獲取學生 /// </summary> /// <param name="id"></param> /// <returns></returns> StudentOutput Get(int id); /// <summary> /// 獲取全部學生 /// </summary> /// <returns></returns> List<StudentOutput> Get(); /// <summary> /// 更新學生信息 /// </summary> /// <param name="input"></param> void Update(UpdateStudentInput input); /// <summary> /// 更新學生年齡 /// </summary> /// <param name="age"></param> void UpdateAge(int age); /// <summary> /// 根據ID刪除學生 /// </summary> /// <param name="id"></param> void Delete(int id); /// <summary> /// 添加學生 /// </summary> /// <param name="input"></param> void Create(CreateStudentInput input); }
實現學生邏輯管理接口:框架
public class StudentAppService: IStudentAppService { /// <summary> /// 根據ID獲取學生 /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpGet("{id:int}")] public StudentOutput Get(int id) { return new StudentOutput() {Id = 1, Age = 18, Name = "張三"}; } /// <summary> /// 獲取全部學生 /// </summary> /// <returns></returns> public List<StudentOutput> Get() { return new List<StudentOutput>() { new StudentOutput(){Id = 1,Age = 18,Name = "張三"}, new StudentOutput(){Id = 2,Age = 19,Name = "李四"} }; } /// <summary> /// 更新學生信息 /// </summary> /// <param name="input"></param> public void Update(UpdateStudentInput input) { throw new System.NotImplementedException(); } /// <summary> /// 更新學生年齡 /// </summary> /// <param name="age"></param> [HttpPatch("{id:int}/age")] public void UpdateAge(int age) { throw new System.NotImplementedException(); } /// <summary> /// 根據ID刪除學生 /// </summary> /// <param name="id"></param> [HttpDelete("{id:int}")] public void Delete(int id) { throw new System.NotImplementedException(); } /// <summary> /// 添加學生 /// </summary> /// <param name="input"></param> public void Create(CreateStudentInput input) { throw new System.NotImplementedException(); } }
(3)給 WebApi Host 項目配置 Swagger。
Install-Package Swashbuckle.AspNetCore -Version 4.0.1
Startup 中配置
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new Info { Title = "曉晨學生管理系統 WebApi", Version = "v1" }); options.DocInclusionPredicate((docName, description) => true); options.IncludeXmlComments(@"bin\Debug\netcoreapp2.2\Xc.StuMgr.WebApiHost.xml"); options.IncludeXmlComments(@"bin\Debug\netcoreapp2.2\Xc.StuMgr.Application.xml"); }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "曉晨學生管理系統 WebApi"); }); app.UseMvc(); }
運行則會直接看到默認的 ValuesController 的5個API。
經過Nuget 爲 Application 項目安裝組件:
Install-Package Panda.DynamicWebApi
爲接口 IApplicationService
繼承 IDynamicWebApi
同時添加特性DynamicWebApi
[DynamicWebApi] public interface IApplicationService:IDynamicWebApi { }
在 WebApi Host 項目中,Startup裏配置動態WebApi:
Startup.cs:
// 添加動態WebApi 需放在 AddMvc 以後 services.AddDynamicWebApi();
而後打開瀏覽器訪問將會看到:
能夠看到成功爲咱們的 StudentAppService
生成了WebApi,而且和Swagger完美兼容。
通過上面的介紹,你們應該能夠看出使用是很是簡單的,只需兩步:
第一步:爲你的類(或者該類的接口、該類繼承的抽象類,不得放在該類除前面兩種狀況的父類上)繼承 IDynamicWebApi
接口並加入特性[DynamicWebApi]
第二步:Startup中註冊
// 添加動態WebApi 需放在 AddMvc 以後 services.AddDynamicWebApi();
由於須要MVC的一些類來進行處理,因此必須放在AddMvc以後,本組件有檢查。
本組件採用約定大於配置,因此在實際使用中有幾個規則:
(1)要讓類生成動態API須要知足兩個條件,一個是該類直接或間接實現 IDynamicWebApi
,同時該類自己或者父抽象類或者實現的接口具備特性 DynamicWebApi
(2)添加特性 [NonDynamicWebApi]
可以使一個類或者一個方法不生成API,[NonDynamicWebApi]
具備最高的優先級。
(3)會對符合規則的動態API類名進行後綴的刪除,如:咱們前面的 StudentAppService
,會被刪除 AppService 後綴,這個規則是能夠動態配置的。
(4)會自動添加API路由前綴,默認會爲全部API添加 api
前綴
(5)默認的HTTP動詞爲POST
,能夠經過 HttpGet/HttpPost/HttpDelete
等等ASP.NET Core 內置特性來覆蓋
(6)能夠經過HttpGet/HttpPost/HttpDelete
等內置特性來覆蓋默認路由
(7)默認會根據你的方法名字來設置HTTP動詞,如 CreateApple 或者 Create 生成的API動詞爲 POST
,對照表以下,若命中(忽略大小寫)對照表那麼該API的名稱中的這個動詞將會被省略,如 CreateApple 將會變成 Apple,如未在如下對照表中,將會使用默認動詞 POST
方法名開頭 | 動詞 |
---|---|
create | POST |
add | POST |
post | POST |
get | GET |
find | GET |
fetch | GET |
query | GET |
update | PUT |
put | PUT |
delete | DELETE |
remove | DELETE |
(8)強烈建議方法名稱使用帕斯卡命名(PascalCase)規範,以更好的自動處理API名稱,且使用以上對照表的動詞。如:
添加蘋果 -> Add/AddApple/Create/CreateApple
更新蘋果 -> Update/UpdateApple
...
(9)[DynamicWebApi]
特性由於可被繼承,因此爲了父類被誤識別,禁止放在除抽象類、接口之外的父類上。
全部的配置均在對象 DynamicWebApiOptions
中,說明以下:
屬性名 | 是否必須 | 說明 |
---|---|---|
DefaultHttpVerb | 否 | 默認值:POST。默認HTTP動詞 |
DefaultAreaName | 否 | 默認值:空。Area 路由名稱 |
DefaultApiPrefix | 否 | 默認值:api。API路由前綴 |
RemoveControllerPostfixes | 否 | 默認值:AppService/ApplicationService。類名須要移除的後綴 |
RemoveActionPostfixes | 否 | 默認值:Async。方法名須要移除的後綴 |
FormBodyBindingIgnoredTypes | 否 | 默認值:IFormFile。不經過MVC綁定到參數列表的類型。 |
若遇到問題,可以使用 Issues 進行提問。
本項目開源地址:https://github.com/dotnetauth/Panda.DynamicWebApi 但願給個 Star 支持一下
本文Demo地址:XiaoChen.StudentManagement