Introduction

这是系列文章 “Using ASP.NET Core, Entity Framework Core and ASP.NET Boilerplate to Create NLayered Web Application” 的第一部分。

本文将演示如何创建一个跨平台分层的网页程序。我们将用到以下工具:

还将用到 ABP startup 模板里面包含的 Log4Net 和 AutoMapper。我们将用到以下技术:

我们将开发一个简单的任务管理程序。

Prerequirements

Create the Application

按照教程创建程序,记得取消勾选 Authentication。

整个解决方案包含 6 个项目:

  • .Core 领域/业务层(实体,领域服务等)

  • .Application 应用层(DTOs,应用服务等)

  • .EntityFramework 集成 EF Core(从其他层抽象出 EF Core)

  • .Web ASP.NET MVC 层

  • .Tests 单元测试和集成测试(直到 Application 应用层,不包括 Web 层)

  • .Web.Tests ASP.NET Core 集成测试(完整的集成测试,包括 Web 层)

Developing the Application

Creating a Task Entity

  1. using System;
  2. using System.ComponentModel.DataAnnotations;
  3. using System.ComponentModel.DataAnnotations.Schema;
  4. using Abp.Domain.Entities;
  5. using Abp.Domain.Entities.Auditing;
  6. using Abp.Timing;
  7. namespace Acme.SimpleTaskApp.Tasks
  8. {
  9. [Table("AppTasks")]
  10. public class Task : Entity, IHasCreationTime
  11. {
  12. public const int MaxTitleLength = 256;
  13. public const int MaxDescriptionLength = 64 * 1024; //64KB
  14. [Required]
  15. [StringLength(MaxTitleLength)]
  16. public string Title { get; set; }
  17. [StringLength(MaxDescriptionLength)]
  18. public string Description { get; set; }
  19. public DateTime CreationTime { get; set; }
  20. public TaskState State { get; set; }
  21. public Task()
  22. {
  23. CreationTime = Clock.Now;
  24. State = TaskState.Open;
  25. }
  26. public Task(string title, string description = null)
  27. : this()
  28. {
  29. Title = title;
  30. Description = description;
  31. }
  32. }
  33. public enum TaskState : byte
  34. {
  35. Open = 0,
  36. Completed = 1
  37. }
  38. }
  • 继承自 ABP Entity 类。Entity 包含类型为 int 的 Id 属性。可以通过 Entity 设置其它主键类型

  • IHasCreationTime 是个简单的接口,只定义了 CreationTime 属性(最好就用 CreationTime 这个标准名称)

  • Task 实体类定义了一个必须的 Title 和可选的 Description

  • TaskState 是任务状态的枚举

  • Clock.Now 默认返回 DateTime.Now。但它提供了抽象,以便我们轻松切换使用 DateTime.UtcNow。使用 ABP 框架时始终使用 Clock.Now

  • 将 Task 实体保存在 AppTasks 表中

Adding Task to DbContext

.EntityFrameworkCore project includes a pre-defined DbContext. I should add a DbSet for the Task entity into the DbContext:

  1. public class SimpleTaskAppDbContext : AbpDbContext
  2. {
  3. public DbSet<Task> Tasks { get; set; }
  4. public SimpleTaskAppDbContext(DbContextOptions<SimpleTaskAppDbContext> options)
  5. : base(options)
  6. {
  7. }
  8. }

Creating the First Database Migration

这里我按照教程的操作顺序尝试了几遍都失败了。

后来先临时卸载了两个测试项目,然后迁移数据库就成功了。

Task Application Service

Application Services are used to expose domain logic to the presentation layer. An Application Service is called from presentation layer with a Data Transfer Object (DTO) as parameter (if needed), uses domain objects to perform some specific business logic and returns a DTO back to the presentation layer (if needed)

GetAllTasksInput:之所以用它作为 GetAll 方法的参数而不直接用 state 是为了避免后期修改方法参数时破坏现有代码。

ObjectMapper:继承自 AppServiceBase 类,并默认通过 AutoMapper实现。用于将 Task 对象列表映射至 TaskListDtos 对象列表。

Task List View

Adding a New Menu Item

NavigationProvider 在 Web 项目的 Startup 文件夹中。

Localization

应用 Localization 前:
Introduction ASP.NET Core And EF Core Part 1 - 图1

应用 Localization 后:
Introduction ASP.NET Core And EF Core Part 1 - 图2

PS:ABP Localization 添加中文

Filtering Tasks

学了一波如何使用 Bundler & Minifier 压缩 JS。

Automated Testing Task List Page

居然是使用 AngleSharp 来解析测试网页。