原文:https://www.php.cn/csharp-article-380181.html
ABP是為新的現代Web應用程序使用最佳實踐和使用最流行工具的一個起點。可作為一般用途的應用程序的基礎框架或項目模板。接下來通過本文給大家詳細介紹ABP入門教程,感興趣的朋友一起看看吧
ABP是“ASP.NET Boilerplate Project (ASP.NET樣板項目)”的簡稱。
ASP.NET Boilerplate是一個用最佳實踐和流行技術開發現代WEB應用程序的新起點,它旨在成為一個通用的WEB應用程序框架和項目模板。
ABP的官方網站:http://www.aspnetboilerplate.com
ABP在Github上的開源項目:https://github.com/aspnetboilerplate
ABP 的由來
“DRY——避免重復代碼”是一個優秀的開發者在開發軟件時所具備的最重要的思想之一。我們在開發企業WEB應用程序時都有一些類似的需求,例如:都需要登錄頁面、用戶/角色管理、權限驗證、數據有效性驗證、多語言/本地化等等。一個高品質的大型軟件都會運用一些最佳實踐,例如分層體系結構、領域驅動設計、依賴注入等。我們也可能會采用ORM、數據庫遷移(Database Migrations)、日志記錄(Logging)等工具。
從零開始創建一個企業應用程序是一件繁瑣的事,因為需要重復做很多常見的基礎工作。許多公司都在開發自己的應用程序框架來重用於不同的項目,然后在框架的基礎上開發一些新的功能。但並不是每個公司都有這樣的實力。假如我們可以分享的更多,也許可以避免每個公司或每個項目的重復編寫類似的代碼。作者之所以把項目命名為“ASP.NET Boilerplate”,就是希望它能成為開發一般企業WEB應用的新起點,直接把ABP作為項目模板。
ABP是什么?
ABP是為新的現代Web應用程序使用最佳實踐和使用最流行工具的一個起點。可作為一般用途的應用程序的基礎框架或項目模板。它的功能包括:
服務器端:
-
基於最新的.NET技術 (目前是ASP.NET MVC 5、Web API 2、C# 5.0,在ASP.NET 5正式發布后會升級)
-
實現領域驅動設計(實體、倉儲、領域服務、領域事件、應用服務、數據傳輸對象,工作單元等等)
-
實現分層體系結構(領域層,應用層,展現層和基礎設施層)提供了一個基礎架構來開發可重用可配置的模塊集成一些最流行的開源框架/庫,也許有些是你正在使用的。
-
提供了一個基礎架構讓我們很方便地使用依賴注入(使用Castle Windsor作為依賴注入的容器)
-
提供Repository倉儲模式支持不同的ORM(已實現Entity Framework 、NHibernate、MangoDb和內存數據庫)
-
支持並實現數據庫遷移(EF 的 Code first)模塊化開發(每個模塊有獨立的EF DbContext,可單獨指定數據庫)
-
包括一個簡單的和靈活的多語言/本地化系統
-
包括一個 EventBus來實現服務器端全局的領域事件統一的異常處理(應用層幾乎不需要處理自己寫異常處理代碼)
-
數據有效性驗證(Asp.NET MVC只能做到Action方法的參數驗證,ABP實現了Application層方法的參數有效性驗證)
-
通過Application Services自動創建Web Api層(不需要寫ApiController層了)
-
提供基類和幫助類讓我們方便地實現一些常見的任務
-
使用“約定優於配置原則”
客戶端:
-
Bootstrap、Less、AngularJs、jQuery、Modernizr和其他JS庫: jQuery.validate、jQuery.form、jQuery.blockUI、json2等
-
為單頁面應用程序(AngularJs、Durandaljs)和多頁面應用程序(Bootstrap+Jquery)提供了項目模板。
-
自動創建Javascript 的代理層來更方便使用Web Api封裝一些Javascript 函數,更方便地使用ajax、消息框、通知組件、忙狀態的遮罩層等等
除ABP框架項目以外,還開發了名叫“Zero”的模塊,實現了以下功能:
-
身份驗證與授權管理(通過ASP.NET Identity實現的)
-
用戶&角色管理系統設置存取管理(系統級、租戶級、用戶級,作用范圍自動管理)
-
審計日志(自動記錄每一次接口的調用者和參數)
ABP不是什么?
ABP提供了一個應用程序開發模型用於最佳實踐。它擁有基礎類、接口和工具使我們容易建立起可維護的大規模的應用程序。
然而:
它不是RAD工具之一,RAD工具的目的是無需編碼創建應用程序。相反,ABP提供了一種編碼的最佳實踐。
它不是一個代碼生成工具。在運行時雖然它有一些特性構建動態代碼,但它不能生成代碼。
它不是一個一體化的框架。相反,它使用流行的工具/庫來完成特定的任務(例如用EF做ORM,用Log4Net做日志記錄,使得Castle Windsor作為賴注入容器, AngularJs 用於SPA 框架)。
就我使用了ABP幾個月的經驗來看,雖然ABP不是RAD,但是用它開發項目絕對比傳統三層架構要快很多。
雖然ABP不是代碼生成工具,但因為有了它,使我們項目的代碼更簡潔規范,這有利於使用代碼生成工具。
我自己使用VS2013的Scaffolder+T4開發的代碼生成器,可根據領域對象的UML類圖自動生成全部前后端代碼和數據庫,簡單的CURD模塊幾乎不需要編寫代碼,有復雜業務邏輯的模塊主要補充領域層代碼即可。這樣就能把時間多花在領域模型的設計上,減少寫代碼的時間。
下面通過原作者的“簡單任務系統”例子,演示如何運用ABP開發項目
從模板創建空的web應用程序
ABP提供了一個啟動模板用於新建的項目(盡管你能手動地創建項目並且從nuget獲得ABP包,模板的方式更容易)。
轉到www.aspnetboilerplate.com/Templates從模板創建你的應用程序。

你可以選擇SPA(AngularJs或DurandalJs)或者選擇MPA(經典的多頁面應用程序)項目。可以選擇Entity Framework或NHibernate作為ORM框架。
這里我們選擇AngularJs和Entity Framework,填入項目名稱“SimpleTaskSystem”,點擊“CREATE MY PROJECT”按鈕可以下載一個zip壓縮包,解壓后得到VS2013的解決方案,使用的.NET版本是 4.5.1。

每個項目里引用了Abp組件和其他第三方組件,需要從Nuget下載。

黃色感嘆號圖標,表示這個組件在本地文件夾中不存在,需要從Nuget上還原。操作如下:


要讓項目運行起來,還得創建一個數據庫。這個模板假設你正在使用SQL2008或者更新的版本。當然也可以很方便地換成其他的關系型數據庫。
打開Web.Config文件可以查看和配置鏈接字符串:
| 1 |
|
(在后面用到EF的Code first數據遷移時,會自動在SQL Server數據庫中創建一個名為SimpleTaskSystemDb的數據庫。)
就這樣,項目已經准備好運行了!打開VS2013並且按F5:

下面將逐步實現這個簡單的任務系統程序
創建實體
把實體類寫在Core項目中,因為實體是領域層的一部分。
一個簡單的應用場景:創建一些任務(tasks)並分配給人。 我們需要Task和Person這兩個實體。
Task實體有幾個屬性:描述(Description)、創建時間(CreationTime)、任務狀態(State),還有可選的導航屬性(AssignedPerson)來引用Person。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Person實體更簡單,只定義了一個Name屬性:
| 1 2 3 4 |
|
在ABP框架中,有一個Entity基類,它有一個Id屬性。因為Task類繼承自Entity<long>,所以它有一個long類型的Id。Person類有一個int類型的Id,因為int類型是Entity基類Id的默認類型,沒有特別指定類型時,實體的Id就是int類型。
創建DbContext
使用EntityFramework需要先定義DbContext類,ABP的模板已經創建了DbContext文件,我們只需要把Task和Person類添加到IDbSet,請看代碼:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
通過Database Migrations創建數據庫表
我們使用EntityFramework的Code First模式創建數據庫架構。ABP模板生成的項目已經默認開啟了數據遷移功能,我們修改SimpleTaskSystem.EntityFramework項目下Migrations文件夾下的Configuration.cs文件:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
在VS2013底部的“程序包管理器控制台”窗口中,選擇默認項目並執行命令“Add-Migration InitialCreate”

會在Migrations文件夾下生成一個xxxx-InitialCreate.cs文件,內容如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
然后繼續在“程序包管理器控制台”執行“Update-Database”,會自動在數據庫創建相應的數據表:
| 1 |
|
數據庫顯示如下:

(以后修改了實體,可以再次執行Add-Migration和Update-Database,就能很輕松的讓數據庫結構與實體類的同步)
定義倉儲接口
通過倉儲模式,可以更好把業務代碼與數據庫操作代碼更好的分離,可以針對不同的數據庫有不同的實現類,而業務代碼不需要修改。
定義倉儲接口的代碼寫到Core項目中,因為倉儲接口是領域層的一部分。
我們先定義Task的倉儲接口:
| 1 2 |
|
它繼承自ABP框架中的IRepository泛型接口。
在IRepository中已經定義了常用的增刪改查方法:

所以ITaskRepository默認就有了上面那些方法。可以再加上它獨有的方法GetAllWithPeople(...)。
不需要為Person類創建一個倉儲類,因為默認的方法已經夠用了。ABP提供了一種注入通用倉儲的方式,將在后面“創建應用服務”一節的TaskAppService類中看到。
實現倉儲類
我們將在EntityFramework項目中實現上面定義的ITaskRepository倉儲接口。
通過模板建立的項目已經定義了一個倉儲基類:SimpleTaskSystemRepositoryBase(這是一種比較好的實踐,因為以后可以在這個基類中添加通用的方法)。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
TaskRepository繼承自SimpleTaskSystemRepositoryBase並且實現了上面定義的ITaskRepository接口。
創建應用服務(Application Services)
在Application項目中定義應用服務。首先定義Task的應用服務層的接口:
| 1 2 3 4 5 6 |
|
ITaskAppService繼承自IApplicationService,ABP自動為這個類提供一些功能特性(比如依賴注入和參數有效性驗證)。
然后,我們寫TaskAppService類來實現ITaskAppService接口:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
|
TaskAppService使用倉儲進行數據庫操作,它通往構造函數注入倉儲對象的引用。
數據驗證
如果應用服務(Application Service)方法的參數對象實現了IInputDto或IValidate接口,ABP會自動進行參數有效性驗證。
CreateTask方法有一個CreateTaskInput參數,定義如下:
| 1 2 3 4 5 6 7 |
|
Description屬性通過注解指定它是必填項。也可以使用其他 Data Annotation 特性。
如果你想使用自定義驗證,你可以實現ICustomValidate 接口:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
你可以在AddValidationErrors方法中寫自定義驗證的代碼。
創建Web Api服務
ABP可以非常輕松地把Application Service的public方法發布成Web Api接口,可以供客戶端通過ajax調用。
| 1 2 3 |
|
SimpleTaskSystemApplicationModule這個程序集中所有繼承了IApplicationService接口的類,都會自動創建相應的ApiController,其中的公開方法,就會轉換成WebApi接口方法。
可以通過http://xxx/api/services/tasksystem/Task/GetTasks這樣的路由地址進行調用。
通過上面的案例,大致介紹了領域層、基礎設施層、應用服務層的用法。
現在,可以在ASP.NET MVC的Controller的Action方法中直接調用Application Service的方法了。
如果用SPA單頁編程,可以直接在客戶端通過ajax調用相應的Application Service的方法了(通過創建了動態Web Api)。
