Jakeuj's Notes master Help

ABP.IO 新手教學 No.01 快速開始

使用 ABP.IO 以 Angular + EF Core 簡單建立  API

著重在 .Net Core API 新增部分

前端 Angular 不在本次重點會先快速帶過

系列文章索引

參考: [2021] ABP.IO WEB應用程式框架 新手教學 No.0 全篇索引

本篇會以官方文件 快速開始 為依據中文化並附圖加以說明的方式進行

快速開始

參考文件: 快速開始

這是一個單一部分的快速入門教程,用於使用 ABP 框架構建一個簡單的待辦事項應用程序。這是最終應用程序的屏幕截圖:

1626744807

preview

您可以在此處找到已完成應用程序的源代碼。

先決條件

參考文件: 先決條件

支持.NET 5.0+ 開發的 IDE (例如: Rider, Visual Studio

Node.js v14.x

// 本篇不實作 Angular, 可以不用裝 Node.js

// Redis,可以安裝 docker 後執行, docker pull redis & docker run --name some-redis -d redis -p 6379:6379

創建新解決方案

參考文件: 創建新解決方案

我們將使用 ABP CLI 通過 ABP 框架創建新的解決方案。您可以在命令行終端中運行以下命令來安裝它:

// 命令行終端: PowerShell, CMD, Bash

dotnet tool install -g Volo.Abp.Cli

然後創建一個空文件夾,打開命令行終端,在終端中執行以下命令:

abp new TodoApp -u angular

這將創建一個新的解決方案,名為TodoAppangularaspnet-core文件夾。解決方案準備就緒後,在您喜歡的 IDE 中打開 ASP.NET Core 解決方案。

1626746994

Aspnet-core

創建數據庫

參考文件: 創建數據庫

如果您使用的是 Visual Studio,請右鍵單擊該TodoApp.DbMigrator項目,選擇Set as StartUp Project ,然後按 Ctrl+F5 運行它而不進行調試。它將創建初始數據庫並建立初始種子資料(SeedData)。

1626746248

PowerShell

運行應用程序

參考文件: 運行應用程序

在開始開發之前運行應用程序是很好的。該解決方案有兩個主要應用;

  • TodoApp.HttpApi.Host (在 .NET 解決方案中)託管服務器端 HTTP API。

  • angular 文件夾包含 Angular 應用程序。

// 因為專案預設會啟用 Redis,如果沒有可以先關閉,在 appsettings.json 中的 Redis 裡面加上 "IsEnabled": "true", 請參考 Redis 快取設定 說明文件 ,很重要所以我會說三次以上

確保TodoApp.HttpApi.Host項目是啟動項目,然後運行應用程序(Visual Studio 中的 Ctrl+F5)以在 Swagger UI 上查看服務器端 HTTP API :

1626746348

TodoAPI

您可以使用此 UI 探索和測試您的 HTTP API。如果可行,我們可以運行 Angular 客戶端應用程序。

// 至此已完成 API 的運行,以下表現層這邊就先不安裝並執行 Angular 了,如果要跑記得先安裝 node.js。

首先,運行以下命令恢復 NPM 包;

npm install

安裝所有軟件包需要一些時間。然後,您可以使用以下命令運行該應用程序:

npm start

此命令需要時間,但最終會在默認瀏覽器中運行並打開應用程序:

todo-ui-initial

您可以單擊 登錄(Login) 按鈕,將admin用作其用戶名和1q2w3E*密碼來登錄應用程序。

一切準備就緒。我們可以開始編碼了!

領域層

參考文件: 領域層

這個應用程序只有一個實體 (Entity),我們從創建它開始。 TodoItemTodoApp.Domain 項目中創建一個新類:

using System; using Volo.Abp.Domain.Entities; namespace TodoApp { public class TodoItem : BasicAggregateRoot<Guid> { public string Text { get; set; } } }

BasicAggregateRoot (內含 Id 欄位當作主鍵) 是創建聚合根實體的最簡單的基類之一,這裡實體的主鍵 (Id) 是 Guid型別 (目前 Abp 推薦使用 Guid 作為 PK)。

1626747076

TodoItem

// 這邊我建了資料夾來放,主要是實戰時不會把全部東西散落在各專案的根目錄,同一個聚合應該建立一個資料夾來放相關物件

// 在其他層的專案也一樣,盡量保持同名方便理解,要移除時也比較清楚該刪除那些東西

數據庫集成

參考文件: 數據庫集成

下一步是設置 Entity Framework Core 配置。

映射配置

參考文件: 映射配置

打開 TodoApp.EntityFrameworkCore 項目文件夾中的TodoAppDbContext類,給這個類添加一個新的屬性: EntityFrameworkCoreDbSet

// 科普:私有唯讀叫欄位,公開有 get, set 叫屬性!

public DbSet<TodoItem> TodoItems { get; set; }
1626747272

DbSet

然後TodoAppDbContextModelCreatingExtensions在同一個文件夾中打開類,為類添加映射配置, TodoItem如下圖:

public static void ConfigureTodoApp(this ModelBuilder builder) { Check.NotNull(builder, nameof(builder)); builder.Entity<TodoItem>(b => { b.ToTable("TodoItems"); }); }

我們已經將TodoItem實體映射到TodoItems數據庫中的一個表。

1626747524

TodoAppDbContextModelCreatingExtensions

// 這邊 ToTable 用來指定資料表名稱,可以參考 EF Core 的官方文件

程式碼優先遷移

參考文件: 程式碼優先遷移

啟動解決方案配置為使用 Entity Framework Core Code First Migrations 。由於我們已經更改了數據庫映射配置,我們應該創建一個新的遷移並將更改應用於數據庫。

// Code First 程式碼優先:Entity Framework 提供從程式碼建立資料庫的功能,不必親自到資料庫伺服器建資料庫或資料表,也不用寫SQL,如此可以先由程式碼開始定義實體

TodoApp.EntityFrameworkCore.DbMigrations 項目的目錄中打開命令行終端並鍵入以下命令:

dotnet ef migrations add Added_TodoItem
1626747795

migrations add

這將向項目添加一個新的遷移類:

1626747863

Migrations

您可以在同一命令行終端中使用以下命令對數據庫應用更改:

dotnet ef database update
1626748005

database update

現在,我們可以使用 ABP 存儲庫來保存和檢索待辦事項,我們將在下一節中進行。

應用層

參考文件: 應用層

一個 應用服務 被用來執行應用程序的使用情況。我們需要執行以下用例;

  • 獲取待辦事項列表

  • 創建一個新的待辦事項

  • 刪除現有的待辦事項

// 下面我將會調換原文說明順序,將應用服務合約中的資料傳輸物件與應用服務介面互換,因為 Application Service Interface 會用到 DTO

數據傳輸對象

參考文件: 數據傳輸對象

GetListAsyncCreateAsync方法返回TodoItemDto

應用程序服務通常獲取和返回 DTO(數據傳輸對象 )而不是實體。

所以,我們應該在這裡定義 DTO 類。

TodoApp.Application.Contracts 項目中創建一個新類 TodoItemDto

using System; namespace TodoApp { public class TodoItemDto { public Guid Id { get; set; } public string Text { get; set; } } }

這是一個非常簡單的 DTO 類,與我們的TodoItem實體相匹配。我們已準備好實施ITodoAppService.

1626748382

TodoItemDto

應用服務接口

參考文件: 應用服務接口

我們可以從為應用程序服務定義一個接口開始。在 TodoApp.Application.Contracts 項目中新建一個界面 ITodoAppService ,如下:

using System; using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Application.Services; namespace TodoApp { public interface ITodoAppService : IApplicationService { Task<List<TodoItemDto>> GetListAsync(); Task<TodoItemDto> CreateAsync(string text); Task DeleteAsync(Guid id); } }
1626748518

ITodoAppService

// 雖然不建立介面也可以直接實作應用服務,但最佳實踐建一位每個應用服務建立各自的 Interface

應用服務實現

參考文件: 應用服務實現

TodoApp.Application項目裡面創建一個類 TodoAppService ,如下:

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; namespace TodoApp { public class TodoAppService : ApplicationService, ITodoAppService { private readonly IRepository<TodoItem, Guid> _todoItemRepository; public TodoAppService(IRepository<TodoItem, Guid> todoItemRepository) { _todoItemRepository = todoItemRepository; } // TODO: Implement the methods here... } }
1626748824

TodoAppService

該類繼承自ABP 框架的類ApplicationService並實現了之前定義的ITodoAppService

ABP 為實體提供默認的通用存儲庫 (Repository)。我們可以使用它們來執行基本的數據庫操作。

這個類註入 IRepository<TodoItem, Guid> ,它是TodoItem實體的默認存儲庫。我們將使用它來實現之前描述的用例。

1626748964

Implement

GetListAsync - 獲取 Todo 項目

參考: ABP 官方教學 - 獲取 Todo 項目

讓我們從實現該GetListAsync方法開始:

public async Task<List<TodoItemDto>> GetListAsync() { var items = await _todoItemRepository.GetListAsync(); return items .Select(item => new TodoItemDto { Id = item.Id, Text = item.Text }).ToList(); }

我們只是從數據庫中獲取 TodoItem 完整列表,將它們映射到TodoItemDto對象並作為結果返回。

// 這邊範例為了快速開始所以使用手動方式手動將 Entity 映射到 DTO, ABP 也有整合 AutoMapper,請參考 連結

1626749022

GetListAsync

CreateAsync - 創建一個新的 Todo 項目

參考: ABP 官方教學 - 創建一個新的 Todo 項目

下一個方法是CreateAsync ,我們可以實現它,如下所示:

public async Task<TodoItemDto> CreateAsync(string text) { var todoItem = await _todoItemRepository.InsertAsync( new TodoItem {Text = text} ); return new TodoItemDto { Id = todoItem.Id, Text = todoItem.Text }; }

Repository 的InsertAsync方法將給定的TodoItem物件插入數據庫並返回相同的 TodoItem 物件。

它還設置了Id ,因此我們可以在返回的物件上使用它。

我們只是從新建的TodoItem實體返回一個TodoItemDto

1626749202

CreateAsync

刪除到每個項目

參考文件: 刪除到每個項目

最後,我們可以實現DeleteAsync如下代碼塊:

public async Task DeleteAsync(Guid id) { await _todoItemRepository.DeleteAsync(id); }
1626749287

DeleteAsync

應用程序服務已準備好從 UI 層使用。

// 因為專案預設會啟用 Redis,如果沒有可以先關閉,在 appsettings.json 中的 Redis 裡面加上 "IsEnabled": "true", 請參考 Redis 快取設定 說明文件 ,很重要所以我會說三次以上

// 至此已完成 API 的新增,以下表現層這邊就先不繼續實作 Angular 了,如果要跑記得先安裝 node.js。

// 特別提一下服務代理 (Service Proxy) ,大致功能是自動根據最新 API 的 JSON 生成 Client 呼叫用的 TypeScript,個人用 Angular 開發時覺得很方便。

用戶界面層

參考文件: 用戶界面層

是時候在 UI 上顯示待辦事項了!在開始編寫代碼之前,最好記住我們正在嘗試構建的內容。這是最終用戶界面的示例屏幕截圖:

全部列表

服務代理生成

參考文件: 服務代理生成

ABP 提供了一個方便的功能來自動創建客戶端服務,以輕鬆使用服務器提供的 HTTP API。

您首先需要運行該TodoApp.HttpApi.Host項目,因為代理生成器從服務器應用程序讀取 API 定義。

// 因為專案預設會啟用 Redis,如果沒有可以先關閉,在 appsettings.json 中的 Redis 裡面加上 "IsEnabled": "true", 請參考 Redis 快取設定 說明文件 ,很重要所以我會說三次以上

運行無 iisexpress

運行TodoApp.HttpApi.Host項目後,在angular文件夾中打開命令行終端並鍵入以下命令:

abp generate-proxy

如果一切順利,它應該生成如下所示的輸出:

CREATE src/app/proxy/generate-proxy.json (170978 bytes) CREATE src/app/proxy/README.md (1000 bytes) CREATE src/app/proxy/todo.service.ts (794 bytes) CREATE src/app/proxy/models.ts (66 bytes) CREATE src/app/proxy/index.ts (58 bytes)

然後我們可以使用todoService來使用服務器端 HTTP API,我們將在下一節中進行。

home.component.ts

參考文件: home.component.ts

打開/angular/src/app/home/home.component.ts文件並將其內容替換為以下代碼塊:

import { ToasterService } from '@abp/ng.theme.shared'; import { Component, OnInit } from '@angular/core'; import { TodoItemDto, TodoService } from '@proxy'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'] }) export class HomeComponent implements OnInit { todoItems: TodoItemDto[]; newTodoText: string; constructor( private todoService: TodoService, private toasterService: ToasterService) { } ngOnInit(): void { this.todoService.getList().subscribe(response => { this.todoItems = response; }); } create(): void{ this.todoService.create(this.newTodoText).subscribe((result) => { this.todoItems = this.todoItems.concat(result); this.newTodoText = null; }); } delete(id: string): void { this.todoService.delete(id).subscribe(() => { this.todoItems = this.todoItems.filter(item => item.id !== id); this.toasterService.info('Deleted the todo item.'); }); } }

我們已經使用todoService來獲取待辦事項列表並將返回值分配給todoItems數組。我們還添加了createdelete方法。這些方法將在視圖端使用。

home.component.html

參考文件: home.component.html

打開/angular/src/app/home/home.component.html文件並將其內容替換為以下代碼塊:

<div class="container"> <div class="card"> <div class="card-header"> <div class="card-title">TODO LIST</div> </div> <div class="card-body"> <!-- FORM FOR NEW TODO ITEMS --> <form class="form-inline" (ngSubmit)="create()"> <input name="NewTodoText" type="text" [(ngModel)]="newTodoText" class="form-control mr-2" placeholder="enter text..." /> <button type="submit" class="btn btn-primary">Submit</button> </form> <!-- TODO ITEMS LIST --> <ul id="TodoList"> <li *ngFor="let todoItem of todoItems"> <i class="fa fa-trash-o" (click)="delete(todoItem.id)"></i> {{ todoItem.text }} </li> </ul> </div> </div> </div>

home.component.scss

參考文件: home.component.scss

最後,打開/angular/src/app/home/home.component.scss文件並將其內容替換為以下代碼塊:

#TodoList{ list-style: none; margin: 0; padding: 0; } #TodoList li { padding: 5px; margin: 5px 0px; border: 1px solid #cccccc; background-color: #f5f5f5; } #TodoList li i { opacity: 0.5; } #TodoList li i:hover { opacity: 1; color: #ff0000; cursor: pointer; }

這是 todo 頁面的簡單樣式。我們相信你可以做得更好:)

現在,您可以再次運行該應用程序以查看結果。

結論

參考文件: 結論

在本教程中,我們構建了一個非常簡單的應用程序來預熱 ABP 框架。如果您希望構建一個嚴肅的應用程序,請查看Web 應用程序開發教程 ,該教程涵蓋了實際 Web 應用程序開發的所有方面。

源代碼

參考文件: 源代碼

您可以在此處找到已完成應用程序的源代碼。

也可以看看

參考文件: 也可以看看

Jakeuj

PS5

  • ABP

  • 回首頁

本文章從點部落遷移至 Writerside

14 October 2025