ASP.NET Core 奇淫技巧之動態WebApi

一.前言

接觸到動態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.DynamicWebApihttps://github.com/dotnetauth/Panda.DynamicWebApi)。源自於ABP的一個可獨立使用的,可自動爲你的業務邏輯層生成 ASP.NET Core WebApi 層的開源組件。它生成的API符合Restful風格,能夠根據符合條件的類來生成WebApi,由MVC框架直接調用邏輯,無性能問題,完美兼容Swagger來構建API說明文檔。shell

三.使用

這裏以 DDD 經典四層架構中的應用邏輯層來說解。json

1.準備

(1)創建兩個項目一個是應用邏輯層類庫項目;一個是做爲生成WebApi Host,ASP.NET Core WebApi項目api

1560273021487

(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。

2.動態WebApi

經過Nuget 爲 Application 項目安裝組件:

Install-Package Panda.DynamicWebApi

爲接口 IApplicationService繼承 IDynamicWebApi同時添加特性DynamicWebApi

[DynamicWebApi]
public interface IApplicationService:IDynamicWebApi
{
}

在 WebApi Host 項目中,Startup裏配置動態WebApi:

Startup.cs:

// 添加動態WebApi 需放在 AddMvc 以後
services.AddDynamicWebApi();

而後打開瀏覽器訪問將會看到:

1560277564506

能夠看到成功爲咱們的 StudentAppService 生成了WebApi,而且和Swagger完美兼容。

四.詳細介紹

通過上面的介紹,你們應該能夠看出使用是很是簡單的,只需兩步:

第一步:爲你的類(或者該類的接口、該類繼承的抽象類,不得放在該類前面兩種狀況的父類上)繼承 IDynamicWebApi接口並加入特性[DynamicWebApi]

第二步:Startup中註冊

// 添加動態WebApi 需放在 AddMvc 以後
services.AddDynamicWebApi();

由於須要MVC的一些類來進行處理,因此必須放在AddMvc以後,本組件有檢查。

1.規則

本組件採用約定大於配置,因此在實際使用中有幾個規則:

(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] 特性由於可被繼承,因此爲了父類被誤識別,禁止放在除抽象類、接口之外的父類上。

2.配置

全部的配置均在對象 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

ABP:https://github.com/aspnetboilerplate/aspnetboilerplate

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息