Abp vnext Web应用程序开发教程 1 —— 创建服务器端
文章目录
- 关于本教程
- 下载源代码
- 创建解决方案
- 创建书籍实体
- BookType枚举
- 将图书实体添加到DbContext
- 将图书实体映射到数据库表
- 添加数据库迁移
- 添加样本种子数据
- 更新数据库
- 创建应用程序服务
- BookDto
- CreateUpdateBookDto
- IBookAppService
- BookAppService
- 自动API控制器
- Swagger UI
- 下一部分
关于本教程
本教程基于版本3.1
在本教程系列中,您将构建一个名为Acme.BookStore
的基于ABP的Web应用程序。该应用程序用于管理书籍及其作者的列表。它是使用以下技术开发的:
- 实体框架核心作为ORM提供者。
- MVC/Razor页面作为UI框架。
本教程分为以下部分:
第1部分:创建服务器端(此部分)
第2部分:图书列表页面
第3部分:创建、更新和删除书籍
第4部分:集成测试
第5部分:授权
第6部分:作者:领领域层
第7部分:作者:数据库集成
第8部分:作者:应用程序层
第9部分:作者:用户界面
第10部分:书与作者的关系
下载源代码
MVC (Razor Pages) UI with EF Core
创建解决方案
在开始开发之前,请按照入门教程来创建一个名为Acme.BookStore
的新解决方案并运行它。
创建书籍实体
启动模板中的领域层分为两个项目:
Acme.BookStore.Domain
包含您的实体,领域服务和其他核心域对象。Acme.BookStore.Domain.Shared
包含constants
,enums
或其他领域相关的那些能够与客户共享的对象。
因此,在解决方案的领域层(Acme.BookStore.Domain
项目)中定义您的实体。
应用程序的主要实体是Book
。在Acme.BookStore.Domain
项目中创建一个Books
文件夹(命名空间),并在其中添加一个Book
类:
using System;
using Volo.Abp.Domain.Entities.Auditing;namespace Acme.BookStore.Books
{public class Book : AuditedAggregateRoot<Guid>{public string Name { get; set; }public BookType Type { get; set; }public DateTime PublishDate { get; set; }public float Price { get; set; }}
}
ABP框架为实体提供了两个基本基类:
AggregateRoot
和Entity
。聚合根是域驱动设计概念,可以将其视为直接查询和使用的根实体(有关更多信息,请参见实体文档)。Book
从实体继承了AuditedAggregateRoot
,其在AggregateRoot
类的顶部添加了一些基本的审计属性(比如CreationTime
,CreatorId
,LastModificationTime
…)。ABP会自动为您管理这些属性。Guid
是主键类型的Book
实体。
为了简单起见,本教程将实体属性使用public get / set修饰。如果您了解有关DDD最佳做法的更多信息,请参见实体文档。
BookType枚举
该Book
实体使用BookType
枚举。在Acme.BookStore.Domain.Shared
项目中创建一个Books
文件夹(命名空间)并在其中添加一个BookType
内部文件:
namespace Acme.BookStore.Books
{public enum BookType{Undefined,Adventure,Biography,Dystopia,Fantastic,Horror,Science,ScienceFiction,Poetry}
}
最终的文件夹/文件结构应如下所示:
将图书实体添加到DbContext
EF Core要求将实体与您的DbContext
关联。最简单的方法是在Acme.BookStore.EntityFrameworkCore
项目的BookStoreDbContext
类中添加一个DbSet
属性,如下所示:
public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
{public DbSet<Book> Books { get; set; }//...
}
将图书实体映射到数据库表
在Acme.BookStore.EntityFrameworkCore
项目中打开BookStoreDbContextModelCreatingExtensions.cs
文件,然后添加Book
实体的映射代码。最终类应为:
using Acme.BookStore.Books;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;namespace Acme.BookStore.EntityFrameworkCore
{public static class BookStoreDbContextModelCreatingExtensions{public static void ConfigureBookStore(this ModelBuilder builder){Check.NotNull(builder, nameof(builder));/* Configure your own tables/entities inside here */builder.Entity<Book>(b =>{b.ToTable(BookStoreConsts.DbTablePrefix + "Books",BookStoreConsts.DbSchema);b.ConfigureByConvention(); //auto configure for the base class propsb.Property(x => x.Name).IsRequired().HasMaxLength(128);});}}
}
BookStoreConsts
含有用于表的架构和表前缀的常量值。您不必使用它,但是建议您在单点中控制表前缀。ConfigureByConvention()
方法优雅地配置/映射继承的属性。始终将其用于所有实体。
添加数据库迁移
启动模板使用EF Core Code First Migrations来创建和维护数据库架构。在菜单工具> NuGet软件包管理器下,打开软件包管理器控制台(PMC)。
选择Acme.BookStore.EntityFrameworkCore.DbMigrations
作为默认项目并执行以下命令:
Add-Migration "Created_Book_Entity"
这将在Acme.BookStore.EntityFrameworkCore.DbMigrations
项目的Migrations
文件夹内创建一个新的迁移类。
在更新数据库之前,请阅读以下部分,以了解如何将一些初始数据插入到数据库中。
如果使用的不是Visual Studio,则可以使用此处文档中的
dotnet-ef
工具。
添加样本种子数据
在运行应用程序之前,最好在数据库中包含一些初始数据。本节介绍ABP框架的数据种子系统。如果您不想创建种子数据,则可以跳过本节,但是建议您遵循它来学习此有用的ABP Framework功能。
创建一个从*.Domain
项目中的IDataSeedContributor
派生的类,并复制以下代码:
using System;
using System.Threading.Tasks;
using Acme.BookStore.Books;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;namespace Acme.BookStore
{public class BookStoreDataSeederContributor: IDataSeedContributor, ITransientDependency{private readonly IRepository<Book, Guid> _bookRepository;public BookStoreDataSeederContributor(IRepository<Book, Guid> bookRepository){_bookRepository = bookRepository;}public async Task SeedAsync(DataSeedContext context){if (await _bookRepository.GetCountAsync() <= 0){await _bookRepository.InsertAsync(new Book{Name = "1984",Type = BookType.Dystopia,PublishDate = new DateTime(1949, 6, 8),Price = 19.84f},autoSave: true);await _bookRepository.InsertAsync(new Book{Name = "The Hitchhiker's Guide to the Galaxy",Type = BookType.ScienceFiction,PublishDate = new DateTime(1995, 9, 27),Price = 42.0f},autoSave: true);}}}
}
如果数据库中当前没有书,则此代码仅使用IRepository<Book, Guid>
(默认存储库)将两本书插入数据库。
更新数据库
运行Acme.BookStore.DbMigrator应用程序以更新数据库:
.DbMigrator
是一个控制台应用程序,可以运行该应用程序以迁移数据库架构并将数据植入到开发和生产环境中。
创建应用程序服务
应用程序层分为两个项目:
Acme.BookStore.Application.Contracts
包含您的DTO和应用程序服务接口。Acme.BookStore.Application
包含您的应用程序服务的实现。
在本部分中,您将创建一个应用程序服务,以使用ABP框架的CrudAppService
基类来get, create, update和delete书籍。
BookDto
CrudAppService
基类需要定义实体的基本DTO。在Acme.BookStore.Application.Contracts
项目中创建一个Books
文件夹(命名空间),并在其中添加一个BookDto
类:
using System;
using Volo.Abp.Application.Dtos;namespace Acme.BookStore.Books
{public class BookDto : AuditedEntityDto<Guid>{public string Name { get; set; }public BookType Type { get; set; }public DateTime PublishDate { get; set; }public float Price { get; set; }}
}
DTO类用于在表示层和应用程序层之间传输数据。有关更多详细信息,请参见数据传输对象文档。
BookDto
用于将书籍数据传输到表示层,以便在UI上显示书籍信息。BookDto
派生自AuditedEntityDto<Guid>
,其具有与上面定义的Book
实体一样的审计属性。
在将书籍返回到表示层时,需要将Book
实体映射到BookDto
对象。当您定义正确的映射时,AutoMapper库可以自动执行此转换。启动模板带有预先配置的AutoMapper
。因此,您只需在Acme.BookStore.Application
项目的BookStoreApplicationAutoMapperProfile
类中定义映射即可:
using Acme.BookStore.Books;
using AutoMapper;namespace Acme.BookStore
{public class BookStoreApplicationAutoMapperProfile : Profile{public BookStoreApplicationAutoMapperProfile(){CreateMap<Book, BookDto>();}}
}
有关详细信息,请参见对象到对象映射文档。
CreateUpdateBookDto
在Acme.BookStore.Application.Contracts
项目的Books
文件夹(命名空间)中创建一个CreateUpdateBookDto
类:
using System;
using System.ComponentModel.DataAnnotations;namespace Acme.BookStore.Books
{public class CreateUpdateBookDto{[Required][StringLength(128)]public string Name { get; set; }[Required]public BookType Type { get; set; } = BookType.Undefined;[Required][DataType(DataType.Date)]public DateTime PublishDate { get; set; } = DateTime.Now;[Required]public float Price { get; set; }}
}
此
DTO
类用于在创建或更新书籍时从用户界面获取书籍信息。它定义了数据注释属性(如
[Required]
)来定义属性的验证。DTO
会由ABP框架自动验证。
就像上面BookDto
所做的一样,我们应该定义从CreateUpdateBookDto
对象到Book
实体的映射。最终类如下所示:
using Acme.BookStore.Books;
using AutoMapper;namespace Acme.BookStore
{public class BookStoreApplicationAutoMapperProfile : Profile{public BookStoreApplicationAutoMapperProfile(){CreateMap<Book, BookDto>();CreateMap<CreateUpdateBookDto, Book>();}}
}
IBookAppService
下一步是为应用程序服务定义接口。在Acme.BookStore.Application.Contracts
项目的Books
文件夹(命名空间)中创建一个IBookAppService
接口:
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;namespace Acme.BookStore.Books
{public interface IBookAppService :ICrudAppService< //Defines CRUD methodsBookDto, //Used to show booksGuid, //Primary key of the book entityPagedAndSortedResultRequestDto, //Used for paging/sortingCreateUpdateBookDto> //Used to create/update a book{}
}
框架不需要为应用程序服务定义接口。但是,建议将其作为最佳实践。
ICrudAppService
定义了通用CRUD方法:GetAsync
,GetListAsync
,CreateAsync
,UpdateAsync
和DeleteAsync
。不需要扩展它。相反,您可以从空IApplicationService
接口继承并手动定义自己的方法(将在下一部分为作者完成)。ICrudAppService
中有一些变体,你可以在每个方法中使用单独的DTO,也可以分别单独指定(例如使用不同的DTO进行创建和更新)。
BookAppService
现在是实现IBookAppService
接口的时候了。创建一个新类,在Acme.BookStore.Application
项目的Books
命名空间(文件夹)中命名BookAppService
:
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;namespace Acme.BookStore.Books
{public class BookAppService :CrudAppService<Book, //The Book entityBookDto, //Used to show booksGuid, //Primary key of the book entityPagedAndSortedResultRequestDto, //Used for paging/sortingCreateUpdateBookDto>, //Used to create/update a bookIBookAppService //implement the IBookAppService{public BookAppService(IRepository<Book, Guid> repository): base(repository){}}
}
BookAppService
派生自CrudAppService<...>
,它实现由ICrudAppService
定义的所有CRUD
(创建,读取,更新,删除)方法。BookAppService
注入IRepository<Book, Guid>
,这是Book
实体的默认存储库。ABP自动为每个聚合根(或实体)创建默认存储库。请参阅存储库文档。BookAppService
使用IObjectMapper
服务(请参考)将Book
对象映射到BookDto
对象以及将Book
对象映射到CreateUpdateBookDto
对象。启动模板使用AutoMapper库作为对象映射提供程序。我们之前已经定义了映射,因此它将按预期工作。
自动API控制器
在典型的ASP.NET Core
应用程序中,您创建API控制器以将应用程序服务公开为HTTP API端点。这允许浏览器或第三方客户端通过HTTP
调用它们。
ABP可以按照约定自动将您的应用程序服务配置为MVC API控制器。
Swagger UI
启动模板配置为使用Swashbuckle.AspNetCore
库运行Swagger UI
。通过在浏览器上按CTRL+F5
并导航到https://localhost:<port>/swagger/
来运行该应用程序。(替换<port>
为您自己的端口号。)
您将看到一些内置服务端点以及该Book
服务及其REST样式
端点:
Swagger有一个不错的接口来测试API。
如果您尝试执行[GET] /api/app/bookAPI
以获取书籍列表,则服务器会返回这样的JSON结果:
{"totalCount": 2,"items": [{"name": "The Hitchhiker's Guide to the Galaxy","type": 7,"publishDate": "1995-09-27T00:00:00","price": 42,"lastModificationTime": null,"lastModifierId": null,"creationTime": "2020-07-03T21:04:18.4607218","creatorId": null,"id": "86100bb6-cbc1-25be-6643-39f62806969c"},{"name": "1984","type": 3,"publishDate": "1949-06-08T00:00:00","price": 19.84,"lastModificationTime": null,"lastModifierId": null,"creationTime": "2020-07-03T21:04:18.3174016","creatorId": null,"id": "41055277-cce8-37d7-bb37-39f62806960b"}]
}
这很酷,因为我们没有编写任何代码来创建API控制器,但是现在我们有了一个可以正常使用的REST API!
下一部分
请参阅本教程的下一部分。
Abp vnext Web应用程序开发教程 1 —— 创建服务器端相关推荐
- Abp vnext Web应用程序开发教程 3 —— 创建、更新和删除书籍
文章目录 关于本教程 下载源代码 创建新书 创建模态表单 添加"新书"按钮 更新书 EditModal.cshtml.cs 从BookDto映射到CreateUpdateBookD ...
- Abp vnext Web应用程序开发教程 10 —— 书与作者的关系
文章目录 关于本教程 下载源代码 介绍 向书实体添加关系 数据库和数据迁移 更新EF核心映射 添加新的EF核心迁移 更改数据播种器 应用层 数据传输对象 IBookAppService BookApp ...
- Abp vnext Web应用程序开发教程 9 —— 作者:用户界面
文章目录 关于本教程 下载源代码 介绍 图书列表页面 Index.cshtml IndexModel.cshtml.cs Index.js 本地化 添加到主菜单 运行应用程序 创建模态 CreateM ...
- Abp vnext Web应用程序开发教程 8 —— 作者:应用程序层
文章目录 关于本教程 下载源代码 介绍 IAuthorAppService AuthorDto GetAuthorListDto CreateAuthorDto UpdateAuthorDto Aut ...
- Abp vnext Web应用程序开发教程 7 —— 作者:数据库集成
文章目录 关于本教程 下载源代码 介绍 数据库上下文 创建一个新的数据库迁移 实现IAuthorRepository 下一部分 关于本教程 本教程基于版本3.1 在本教程系列中,您将构建一个名为Acm ...
- Abp vnext Web应用程序开发教程 6 —— 作者:领域层
文章目录 关于本教程 下载源代码 介绍 作者实体 AuthorManager:领域服务 IAuthorRepository 结论 下一部分 关于本教程 本教程基于版本3.1 在本教程系列中,您将构建一 ...
- Abp vnext Web应用程序开发教程 4 —— 集成测试
文章目录 关于本教程 下载源代码 在解决方案中测试项目 添加测试数据 测试BookAppService 下一部分 关于本教程 本教程基于版本3.1 在本教程系列中,您将构建一个名为Acme.BookS ...
- Abp vnext Web应用程序开发教程 2 —— 图书列表页面
文章目录 关于本教程 下载源代码 动态JavaScript代理 在开发者控制台中进行测试 本地化 创建书籍页面 将书籍页面添加到主菜单 图书列表 运行最终应用程序 下一部分 关于本教程 本教程基于版本 ...
- Abp vnext Web应用程序开发教程 5 —— 授权
文章目录 关于本教程 下载源代码 权限 权限名称 权限定义 权限管理界面 授权 应用层和HTTP API Razor页面 JavaScript端 菜单项 下一部分 关于本教程 本教程基于版本3.1 在 ...
最新文章
- android unzip file,Unzip File in Android Assets
- 软件工程复习提纲——第五章
- 库克用iPhone12 Pro Max发中秋祝福 网友调侃:库克也没抢到iPhone13?
- 关于u-boot中的.balignl 16,0xdeadbeef的理解
- Java中的Instanceof
- Tina-TI 电路仿真 多参数交流传输特性分析 频率与相位增益的关系 选择控制对象
- vue 地图使用navigator_9 个实验 + 3 个项目,带你入门 Vue.js 3 !
- 计蒜客 16876 韩梅梅的抽象画
- 案例分享:Windows Phone上的移动浏览体验
- 鼎捷T100标准接口调用
- PHP一句话木马,中国菜刀
- android webview 真正实现---保存整个网页源码
- AliOS Things学习笔记(5)——ESP8266对接天猫精灵下篇(设备端)
- 极验3forbidden,易盾d包
- 【​观察】六脉神剑第二式-读写分离之双箭齐发
- Redis三种删除策略
- 计算机组成原理实验——实验1 运算器实验
- 【定时任务】Springboot定时任务
- 关于以太网光纤收发器,逻辑隔离与物理隔离的理解与区别
- 参加ACM比赛所需的基础知识(转)
热门文章
- android studio app显示红叉_发现这个 APP 后,感觉可以放弃桌面时钟了
- 鸿蒙os开启第二批公测,鸿蒙OS开启第二批公测,7款机型加入升级名单,NOVA用户恭喜了...
- 基于dijsktra算法的最短路径求解_基于dijkstra算法的AGV路径规划(含C++代码)
- UI设计实用素材|功能性图标ICON的作用
- UI使用素材模板|login登录界面
- python中if控制语句_Python 极简教程(十二)逻辑控制语句 if else
- 如何产生cpk图形_PPK与CPK定义,差异分析及计算
- Python获取代理IP地址
- numactl:NETLINK示例源码
- 二叉树的中序遍历_94. 二叉树的中序遍历 - 中等