快速入门
这是一个由单个部分组成的快速入门教程, 旨在使用ABP框架构建一个简单的待办事项应用程序. 这是最终应用程序的屏幕截图:
你可以在这里找到已完成的项目源代码.
先决条件
一个集成开发环境 (比如: Visual Studio) 它需要支持 .NET 5.0+ 的开发.
创建新的解决方案
我们将使用ABP CLI 创建带有ABP框架的新解决方案. 你可以在命令行终端中运行以下命令来安装它:
dotnet tool install -g Volo.Abp.Cli
然后创建一个空文件夹, 打开命令行终端并在终端中执行以下命令:
abp new TodoApp -u angular -d mongodb
这将创建一个名为TodoApp的新解决方案, 其中包含angular
和aspnet core
文件夹. 一旦解决方案就绪, 请在你最喜欢的 IDE 中打开 ASP.NET Core 解决方案.
创建数据库
如果你使用的是Visual Studio, 请右键单击TodoApp.DbMigrator
项目, 选择设置为启动项目, 然后按Ctrl+F5运行它而不进行调试. 它将创建初始数据库并生成初始数据.
运行应用程序
最好在开始开发之前运行一下应用程序. 解决方案中有两个主要应用程序;
TodoApp.HttpApi.Host
(在.NET解决方案中)承载服务器端HTTP API.Angular
文件夹包含 Angular 应用程序.
确保 TodoApp.HttpApi.Host
是启动项目, 然后运行应用程序(Visual Studio中的Ctrl+F5)打开Swagger UI来查看服务器端的 HTTP API:
你可以使用此 UI 探索和测试你的 HTTP API. 如果该功能正常, 我们可以运行Angular 客户端应用程序.
首先, 运行以下命令来还原NPM包:
npm install
安装所有软件包需要一些时间. 然后可以使用以下命令运行应用程序:
npm start
此命令需要时间, 但最终在你的默认浏览器中运行并打开应用程序:
你可以单击 登录 按钮, 以admin
作为用户名和1q2w3E*
作为密码登录到应用程序.
一切就绪. 我们可以开始编程!
领域层
此应用程序只有一个 实体, 接下来我们开始创建它. 在 TodoApp.Domain 项目中创建一个新的 TodoItem
类:
using System;
using Volo.Abp.Domain.Entities;
namespace TodoApp
{
public class TodoItem : BasicAggregateRoot<Guid>
{
public string Text { get; set; }
}
}
BasicAggregateRoot
是创建根实体的最简单的基础类. Guid
是这里实体的主键 (Id
).
数据库集成
下一步是设置 MongoDB 配置. 打开 TodoApp.MongoDB 项目中 MongoDb
文件夹的TodoAppMongoDbContext
类并做出以下更改;
- 向类添加新属性:
public IMongoCollection<TodoItem> TodoItems => Collection<TodoItem>();
- 在
CreateModel
方法中添加以下代码:
modelBuilder.Entity<TodoItem>(b =>
{
b.CollectionName = "TodoItems";
});
现在, 我们可以使用ABP仓库保存和检索待办事项, 如我们在下一节所做的那样.
应用层
应用程序服务 用于执行应用程序的用例. 我们需要执行以下用例:
- 获取待办事项列表
- 创建新的待办事项
- 删除现有的待办事项
应用服务接口
我们可以先从为应用程序服务定义接口开始. 在 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);
}
}
数据传输对象
GetListAsync
和CreateAsync
方法返回 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
接口.
应用服务实现
在 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...
}
}
该类继承自ABP框架的ApplicationService
类, 并实现了之前定义的 ITodoAppService
接口. ABP为实体提供默认的泛型 仓储. 我们可以使用它们来执行基本的数据库操作. 此类中 注入 的 IRepository<TodoItem, Guid>
, 它就是 TodoItem
实体的默认存储库. 我们将使用它来实现之前描述的用例.
获取待办事项
让我们先实现 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
对象并作为结果返回.
创建一个新的待办事项
下一个我们可以实现方法是 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
};
}
仓储的 InsertAsync
方法将给定的TodoItem
插入数据库, 并返回相同的TodoItem
对象. 它还设置了Id
, 因此我们可以在返回对象上使用它. 我们只是通过从新的 TodoItem
实体创建和返回 TodoItemDto
.
删除待办事项
最后, 我们来实现 DeleteAsync
方法, 代码如下:
public async Task DeleteAsync(Guid id)
{
await _todoItemRepository.DeleteAsync(id);
}
至此, 应用程序服务已准备好了让UI层来使用.
用户界面层
现在是在UI上显示待办事项的时候了! 在开始编写代码之前, 最好记住我们正在尝试构建的内容. 这里是示例程序的最终用户界面的截图:
我们将在本教程中保持最简洁的UI端, 以使本教程简单且重点突出. 请参阅 web应用程序开发教程 来了解构建实际应用各个方面.
服务代理生成
ABP提供了一个便捷的功能来自动创建客户端服务, 以方便地使用由服务器提供的HTTP API.
你首先需要运行 TodoApp.HttpApi.Host
项目, 因为代理生成器从服务器应用程序读取API定义.
请注意: IIS Express有一个问题: 它不允许从另一个进程连接到应用程序. 如果你使用的是Visual Studio, 请在 “运行” 按钮下拉列表中选择
TodoApp.HttpApi.Host
来替代IIS Express, 如下图所示:
当启动 TodoApp.HttpApi.Host
项目后, 在angular
文件夹中打开一个命令行终端并输入以下命令:
abp generate-proxy -t ng
如果一切顺利, 它应该生成如下输出:
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
打开 /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
数组. 我们还添加了 create
和 delete
方法. 这些方法将在视图端使用.
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
最后, 打开/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;
}
这是待办事项页面的简单样式. 我们相信你可以做得更好 :)
现在, 你可以再次运行应用程序来查看结果.
总结
在这个教程中, 我们已经建立了一个非常简单的应用程序来熟悉 ABP 框架. 如果你想要构建一个实际场景的应用程序, 请查看 web 应用程序开发教程, 该教程涵盖了真实的 Web 应用程序开发的所有方面.
源代码
你可以在这里找到已完成的项目源代码.