ABP開發框架前後端開發系列---(16)ABP框架升級最新版本的經驗總結
有一小段時間沒有持續升級ABP框架了,最近就因應客戶的需要,把ABP框架進行全面的更新,由於我們應用的ABP框架,基礎部分還是會使用官方的內容,因此升級的時候需要把官方基礎ABP的DLL進行全面的更新,以及對應的引用DLL也同步更新才行。不過在升級過程中還是很多奇奇怪怪的問題,本篇隨筆針對出現的情況進行一系列的總結,以便後面有一個對照參考吧。
1、最新案例原始碼和NugGet程式包更新
ABP官方的基礎模組更新速度還是很快的,一段時間過去,就跳過了幾個版本號,我是在舊版本的基礎上進行手動的NugGet更新,但是基於VS的Nugget總是更新卡頓,不知不覺就沒有反應了,嚴重影響開發的效率。因此先從官方下載的Demo案例中把相關部分原始碼進行更新。
官方的案例原始碼下載地址是:https://aspnetboilerplate.com/Templates
1)最新案例原始碼結構和部分內容調整
我們從其中下載對應的原始碼,然後根據專案結構中的對應原始碼檔案,使用Beyond Compare對比檔案進行檔案逐一對比,原則上除了個人擴充套件的部分,都以官方的原始碼做法為準即可。
目前ABP官方最新的DLL版本是5.3.0,可以下載的Demo版本是5.2.0,它們應該差別不大。下載下來的Aspnet-core部分的原始碼結構如下所示。
而我們的ABP框架是在這個基礎上進行一定的結構優化,以更加方便快速的開發,以及結合程式碼生成工具進行快速的使用。
我們的VS專案結構 如下所示。
以上是VS裡面解決方案的專案結構,我根據專案之間的關係,整理了一個架構的圖形,如下所示。
上圖中,其中橘紅色部分就是我們為各個層新增的類或者介面,分層上的序號是我們需要逐步處理的內容。
應用服務層是整個ABP框架的靈魂所在,對內協同倉儲物件實現資料的處理,對外配合Web.Core、Web.Host專案提供Web API的服務,而Web.Core、Web.Host專案幾乎不需要進行修改,因此應用服務層就是一個非常關鍵的部分,需要考慮對使用者登入的驗證、介面許可權的認證、以及對審計日誌的記錄處理,以及異常的跟蹤和傳遞,基本上應用服務層就是一個大內總管的角色,重要性不言而喻。
回顧瞭解一下我們改造過的ABP開發框架的結構後,我們返回到版本升級的主體上來介紹。
目前我把VS的版本升級到最新,其.net framework支援4.8, 並單獨安裝了dotnetcore最新版本3.1,因此環境是最新的,而基礎的ABP 5.3.0也是採用了.net core3.1。
對比原始碼,我們可以發現,Web.Host和Web.Core專案裡面已經有所差異,IHostingEnvironment已經被拋棄使用,而採用dotnetcore最新物件IWebHostEnvironment來替代了。
替換最新原始碼為
因此Web.Host專案中的Module類也進行了調整。
相對應的Web.Core專案裡面的Module也同時進行調整了。
2)NugGet程式包更新
Nugget程式包的更新,原則上可以選擇單個專案進行更新,或者選擇整個解決方案進行程式包的更新,前者可能相應速度快一些,後者由於解決方案專案數量問題,可能會較慢。
我早期的基礎ABP版本是4.9,因此想一次性整個的解決方案的程式包進行更新,不過嘗試多次,花了幾個小時,都無法順利進行專案的全部更新,於是單個專案進行更新,也非常慢。
於是也通過推薦採用Nugget最新地址進行更新,如下設定更新源。
在程式包源中新增:https://api.nuget.org/v3/index.json
響應速度相對快了一些,沒有不經常的出問題了。
我們如果需要單獨更新某個專案的程式包,那麼需要選擇專案,選擇【管理Nugget程式包】進入介面更新即可。如下介面所示。
一般情況下,我們推薦對整個解決方案進行全面的程式包更新,如下選擇解決方案,然後進入對應Nugget程式包管理介面更新即可。
這樣的全部更新解決方案的程式包,如果能夠順利完成,那是皆大歡喜,不過可能會稍微慢一些。如果不行,只有逐個更新程式包了。
我之前選擇這樣的方式更新的時候,總是有一兩個程式包更新出錯,因此只有使用npm 控制檯進行單獨的升級了。
2、ABP框架基類封裝介面命名調整
在更新ABP基礎模組的時候,發現ABP的基礎介面全部調整了命名,如原來的Get變為GetAsync,GetAll變為 GetAllAsync,Delete變為了DeleteAsync,Update變為了UpdateAsync,Create變為了CreateAsync。
也就是說,他們全部採用了非同步名稱的命名規則,在非同步方法後面全部加上了Async作為標識。
我在之前模組介紹過ABP框架的基礎介面。IAsyncCrudAppService定義了幾個通用的建立、更新、刪除、獲取單個物件和獲取所有物件列表的介面,介面定義如下所示。
namespace Abp.Application.Services { public interface IAsyncCrudAppService<TEntityDto, TPrimaryKey, in TGetAllInput, in TCreateInput, in TUpdateInput, in TGetInput, in TDeleteInput> : IApplicationService, ITransientDependency where TEntityDto : IEntityDto<TPrimaryKey> where TUpdateInput : IEntityDto<TPrimaryKey> where TGetInput : IEntityDto<TPrimaryKey> where TDeleteInput : IEntityDto<TPrimaryKey> { Task<TEntityDto> Create(TCreateInput input); Task Delete(TDeleteInput input); Task<TEntityDto> Get(TGetInput input); Task<PagedResultDto<TEntityDto>> GetAll(TGetAllInput input); Task<TEntityDto> Update(TUpdateInput input); } }
現在這些介面全部調整如下所示了。
namespace Abp.Application.Services { public interface IAsyncCrudAppService<TEntityDto, TPrimaryKey, in TGetAllInput, in TCreateInput, in TUpdateInput, in TGetInput, in TDeleteInput> : IApplicationService, ITransientDependency where TEntityDto : IEntityDto<TPrimaryKey> where TUpdateInput : IEntityDto<TPrimaryKey> where TGetInput : IEntityDto<TPrimaryKey> where TDeleteInput : IEntityDto<TPrimaryKey> { Task<TEntityDto> CreateAsync(TCreateInput input); Task DeleteAsync(TDeleteInput input); Task<PagedResultDto<TEntityDto>> GetAllAsync(TGetAllInput input); Task<TEntityDto> GetAsync(TGetInput input); Task<TEntityDto> UpdateAsync(TUpdateInput input); } }
那麼這些我們都必須隨著ABP框架的調整也同時進行介面和對應類實現的調整了。
例如對應的非同步ApplicationService服務的基類封裝,我們也需要調整對應的非同步介面實現。
針對遠端呼叫的ApiCaller介面和實現,我們也需要進行命名方面的統一調整,這樣才能順利進行非同步介面的呼叫
我在之前隨筆《ABP開發框架前後端開發系列---(10)Web API呼叫類的簡化處理》有針對API呼叫層的簡化處理做了說明,我們所有的API呼叫,基本都是通過統一的一個函式進行呼叫的。
統一呼叫處理的方法名稱是DoActionAsync。
雖然由於前面介紹了應用服務層的介面很多介面增加了Async的字尾字元,但是客戶端通過URL呼叫,這個Async是不需要的,也就是需要移除,我們之前組裝的URL地址是根據函式名稱,那麼函式名稱需要移除這個字尾的Async字樣了。
這樣系統就順利跑起來了。服務端介面如下所示。
我們啟動Winform客戶端,介面如下所示。
登陸啟動後主體介面如下所示