From c96be889a1cc67070017a1ff4669c82d57eb2eb8 Mon Sep 17 00:00:00 2001 From: gsonovb Date: Sat, 21 Aug 2021 09:27:49 +0800 Subject: [PATCH 1/7] =?UTF-8?q?docs:=20=F0=9F=9A=9A=20Fix=20Todo=20Tutoria?= =?UTF-8?q?l=20Path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh-Hans/Tutorials/{todo => Todo}/Index.md | 0 .../{todo => Todo}/run-without-iisexpress.png | Bin docs/zh-Hans/Tutorials/{todo => Todo}/todo-api.png | Bin .../{todo => Todo}/todo-efcore-migration.png | Bin docs/zh-Hans/Tutorials/{todo => Todo}/todo-list.png | Bin .../{todo => Todo}/todo-swagger-ui-initial.png | Bin .../Tutorials/{todo => Todo}/todo-ui-initial.png | Bin 7 files changed, 0 insertions(+), 0 deletions(-) rename docs/zh-Hans/Tutorials/{todo => Todo}/Index.md (100%) rename docs/zh-Hans/Tutorials/{todo => Todo}/run-without-iisexpress.png (100%) rename docs/zh-Hans/Tutorials/{todo => Todo}/todo-api.png (100%) rename docs/zh-Hans/Tutorials/{todo => Todo}/todo-efcore-migration.png (100%) rename docs/zh-Hans/Tutorials/{todo => Todo}/todo-list.png (100%) rename docs/zh-Hans/Tutorials/{todo => Todo}/todo-swagger-ui-initial.png (100%) rename docs/zh-Hans/Tutorials/{todo => Todo}/todo-ui-initial.png (100%) diff --git a/docs/zh-Hans/Tutorials/todo/Index.md b/docs/zh-Hans/Tutorials/Todo/Index.md similarity index 100% rename from docs/zh-Hans/Tutorials/todo/Index.md rename to docs/zh-Hans/Tutorials/Todo/Index.md diff --git a/docs/zh-Hans/Tutorials/todo/run-without-iisexpress.png b/docs/zh-Hans/Tutorials/Todo/run-without-iisexpress.png similarity index 100% rename from docs/zh-Hans/Tutorials/todo/run-without-iisexpress.png rename to docs/zh-Hans/Tutorials/Todo/run-without-iisexpress.png diff --git a/docs/zh-Hans/Tutorials/todo/todo-api.png b/docs/zh-Hans/Tutorials/Todo/todo-api.png similarity index 100% rename from docs/zh-Hans/Tutorials/todo/todo-api.png rename to docs/zh-Hans/Tutorials/Todo/todo-api.png diff --git a/docs/zh-Hans/Tutorials/todo/todo-efcore-migration.png b/docs/zh-Hans/Tutorials/Todo/todo-efcore-migration.png similarity index 100% rename from docs/zh-Hans/Tutorials/todo/todo-efcore-migration.png rename to docs/zh-Hans/Tutorials/Todo/todo-efcore-migration.png diff --git a/docs/zh-Hans/Tutorials/todo/todo-list.png b/docs/zh-Hans/Tutorials/Todo/todo-list.png similarity index 100% rename from docs/zh-Hans/Tutorials/todo/todo-list.png rename to docs/zh-Hans/Tutorials/Todo/todo-list.png diff --git a/docs/zh-Hans/Tutorials/todo/todo-swagger-ui-initial.png b/docs/zh-Hans/Tutorials/Todo/todo-swagger-ui-initial.png similarity index 100% rename from docs/zh-Hans/Tutorials/todo/todo-swagger-ui-initial.png rename to docs/zh-Hans/Tutorials/Todo/todo-swagger-ui-initial.png diff --git a/docs/zh-Hans/Tutorials/todo/todo-ui-initial.png b/docs/zh-Hans/Tutorials/Todo/todo-ui-initial.png similarity index 100% rename from docs/zh-Hans/Tutorials/todo/todo-ui-initial.png rename to docs/zh-Hans/Tutorials/Todo/todo-ui-initial.png From 367dc5acb15a6d2ad836afc9c4b91eb147b9c9e5 Mon Sep 17 00:00:00 2001 From: gsonovb Date: Sat, 21 Aug 2021 09:42:13 +0800 Subject: [PATCH 2/7] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Update=20Todo=20Tuto?= =?UTF-8?q?rial=20Translate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh-Hans/Tutorials/Todo/Index.md | 238 ++++++++++++++------------- 1 file changed, 123 insertions(+), 115 deletions(-) diff --git a/docs/zh-Hans/Tutorials/Todo/Index.md b/docs/zh-Hans/Tutorials/Todo/Index.md index 0676a6d894f..5a18e2302a6 100644 --- a/docs/zh-Hans/Tutorials/Todo/Index.md +++ b/docs/zh-Hans/Tutorials/Todo/Index.md @@ -8,15 +8,15 @@ } ```` -这是一个单独的部分,使用ABP框架构建简单待办事项应用程序的快速入门教程.这是一个最终应用的截图: +这是一个由单个部分组成的快速入门教程,旨在使用ABP框架构建一个简单的待办事项应用程序。 这是最终应用程序的屏幕截图: -![todo-list](todo-list.png) +![待办事项列表](todo-list.png) -你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/TodoApp)找到已完成的项目源代码. +你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/TodoApp)找到已完成的项目源代码。 ## 先决条件 -* 一个集成开发环境 (比如: [Visual Studio](https://visualstudio.microsoft.com/vs/)) 它需要支持 [.NET 5.0+](https://dotnet.microsoft.com/download/dotnet) 的开发. +* 一个集成开发环境 (比如: [Visual Studio](https://visualstudio.microsoft.com/vs/)) 它需要支持 [.NET 5.0+](https://dotnet.microsoft.com/download/dotnet) 的开发。 {{if DB=="Mongo"}} @@ -32,13 +32,13 @@ ## 创建新的解决方案 -我们将使用[ABP CLI](../../CLI.md) 创建带有ABP框架的新解决方案. 你可以在命令行终端中运行以下命令来安装它: +我们将使用[ABP CLI](../../CLI.md) 创建带有ABP框架的新解决方案。 你可以在命令行终端中运行以下命令来安装它: ````bash dotnet tool install -g Volo.Abp.Cli ```` -然后创建一个空文件夹,打开命令行终端并以打开的文件夹为路径在终端中执行以下命令: +然后创建一个空文件夹,打开命令行终端并在终端中执行以下命令: ````bash abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{else if UI=="NG"}} -u angular{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} @@ -46,21 +46,21 @@ abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u bl {{if UI=="NG"}} -这将创建一个名为*TodoApp*的新解决方案,其中包含`angular`和`aspnet core`文件夹.解决方案就绪后,在你的IDE中打开ASP.NET Core 解决方案. +这将创建一个名为*TodoApp*的新解决方案,其中包含`angular`和`aspnet core`文件夹。 一旦解决方案就绪,请在您最喜欢的 IDE 中打开ASP.NET Core 解决方案。 {{else}} -这将创建一个名为*TodoApp*的新解决方案.解决方案准备好后,在你的IDE中打开它. +这将创建一个名为*TodoApp*的新解决方案。 一旦解决方案就绪,请在您最喜欢的 IDE 中打开它。 {{end}} ### 创建数据库 -如果你使用的是visual studio,请右键单击`TodoApp.DbMigrator`项目,选择*设置为启动项目*,然后按*Ctrl+F5*运行它而不进行调试.它将创建初始数据库并播种初始数据. +如果你使用的是Visual Studio,请右键单击`TodoApp.DbMigrator`项目,选择*设置为启动项目*,然后按*Ctrl+F5*运行它而不进行调试。 它将创建初始数据库并生成初始数据。 {{if DB=="EF"}} -> 由于*DbMigrator*添加初始迁移并重新编译项目,一些ide(例如Rider)在第一次运行时可能会出现问题.在这种情况下,请打开`.DbMigrator`项目文件夹中的命令行终端,然后执行`dotnet run`命令. +> 一些IDE (例如Rider) 可能会在第一次运行时遇到问题,因为 *DbMigrator* 添加初始迁移并重新编译项目。 在这种情况下,在 `.DbMigrator` 项目文件夹中打开命令行终端并执行 `dotnet run` 命令。 {{end}} @@ -68,59 +68,59 @@ abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u bl {{if UI=="MVC" || UI=="BlazorServer"}} -最好在开始开发之前运行一下应用程序.确保 {{if UI=="BlazorServer"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} 是启动项目,然后运行应用程序(Visual Studio中是Ctrl+F5)以查看查看初始UI: +最好在开始开发之前运行一下应用程序。 确保 {{if UI=="BlazorServer"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} 是启动项目,然后运行应用程序(Visual Studio中是Ctrl+F5)来查看初始UI: {{else if UI=="Blazor"}} -最好在开始开发之前运行一下应用程序.该解决方案有两个主要应用: +最好在开始开发之前运行一下应用程序。 解决方案中有两个主要应用程序 -* `TodoApp.HttpApi.Host` 托管服务器端的 HTTP API. -* `TodoApp.Blazor` 客户端托管的 Blazor WebAssembly 应用. +* `TodoApp.HttpApi.Host` 承载服务器端的 HTTP API。 +* `TodoApp.Blazor` 是客户端的Blazor WebAssembly应用程序。 -确保 `TodoApp.HttpApi.Host` 是启动项目,然后运行应用程序(Visual Studio中的Ctrl+F5)以查看[Swagger UI](https://swagger.io/tools/swagger-ui/)上server-side 的 HTTP API: +确保 `TodoApp.HttpApi.Host` 是启动项目,然后运行应用程序(Visual Studio中的Ctrl+F5)打开[Swagger UI](https://swagger.io/tools/swagger-ui/)来查看服务器端的 HTTP API: -![todo-swagger-ui-initial](todo-swagger-ui-initial.png) +![todo swagger-u 初始化](todo-swagger-ui-initial.png) -你可以使用此UI查看和测试你的HTTP API.现在,我们可以将 `TodoApp.Blazor` 设置为启动项目,并运行它来打开实际的Blazor应用程序UI: +您可以使用此 UI 探索和测试您的 HTTP API。 现在,我们可以将 `TodoApp.Blazor` 设置为启动项目并运行它来打开实际的 Blazor 应用程序UI: {{else if UI=="NG"}} -最好在开始开发之前运行应用程序.该解决方案有两个主要应用: +最好在开始开发之前运行一下应用程序。 解决方案中有两个主要应用程序; -* `TodoApp.HttpApi.Host` (在.NET解决方案中)承载服务器端HTTP API. -* `angular` 文件夹包含 Angular 应用程序. +* `TodoApp.HttpApi.Host` (在.NET解决方案中)承载服务器端HTTP API。 +* `angular` 文件夹包含 Angular 应用程序。 -确保`TodoApp.HttpApi.Host`project是启动项目,然后运行应用程序(visual studio中是Ctrl+F5)以查看[Swagger UI](https://swagger.io/tools/swagger-ui/)上server-side HTTP API: +确保 `TodoApp.HttpApi.Host` 是启动项目,然后运行应用程序(Visual Studio中的Ctrl+F5)打开[Swagger UI](https://swagger.io/tools/swagger-ui/)来查看服务器端的 HTTP API: ![todo-swagger-ui-initial](todo-swagger-ui-initial.png) -你可以使用这个UI查看和测试你的HTTP API.如果可以的话,我们可以运行Angular客户端应用程序. +您可以使用此 UI 探索和测试您的 HTTP API。 如果该功能正常,我们可以运行Angular 客户端应用程序。 -首先,运行以下命令来还原NPM包: +首先,运行以下命令来还原NPM包: ````bash npm install ```` -安装所有软件包需要一些时间.然后可以使用以下命令运行应用程序: +安装所有软件包需要一些时间。 然后可以使用以下命令运行应用程序: ````bash npm start ```` -此命令需要一点时间,但最终会在默认浏览器中运行并打开应用程序: +此命令需要时间,但最终在你的默认浏览器中运行并打开应用程序: {{end}} -![todo-ui-initial](todo-ui-initial.png) +![i待办事项 Ui](todo-ui-initial.png) -你可以单击 *登录* 按钮,以`admin`作为用户名,`1q2w3E*` 作为密码登录到应用程序. +你可以单击 *登录* 按钮,以`admin`作为用户名和`1q2w3E*` 作为密码登录到应用程序。 -一切就绪.我们可以开始编码了! +一切就绪。 我们可以开始编程! ## 领域层 -此应用程序只有一个 [实体](../../Entities.md) 我们开始创建它. 在*TodoApp.Domain*项目中创建一个新的 `TodoItem` 类: +此应用程序只有一个 [实体](../../Entities.md),接下来我们开始创建它。 在 *TodoApp.Domain* 项目中创建一个新的 `TodoItem` 类: ````csharp using System; @@ -135,29 +135,35 @@ namespace TodoApp } ```` -`BasicAggregateRoot` 是创建根实体的最简单的基类之一,`Guid` 是这里实体的主键 (`Id`). +`BasicAggregateRoot` 是创建根实体的最简单的基础类。 `Guid` 是这里实体的主键 (`Id`)。 -## Database Integration 数据库集成 +## 数据库集成 {{if DB=="EF"}} -下一步是配置 [Entity Framework Core](../../Entity-Framework-Core.md). +下一步是设置 [Entity Framework Core](../../Entity-Framework-Core.md)配置 -### Mapping Configuration 映射配置 +### 映射配置 -在 *TodoApp.EntityFrameworkCore* 项目的 `EntityFrameworkCore` 文件夹中打开 `TodoAppDbContext` 类,并向该类添加一个新的 `DbSet` 属性: +打开在 *TodoApp.EntityFrameworkCore* 项目中 `EntityFrameworkCore` 文件夹中的 `TodoAppDbContext` 类,并向该类添加新的 `DbSet` 属性: ````csharp public DbSet TodoItems { get; set; } ```` -然后在同一文件夹中打开 `TodoAppDbContextModelCreatingExtensions` 类,并为 `TodoItem` 类添加映射配置,如下所示: +然后在 `TodoAppDbContext` 类中定位到 `OnModelCreating` 方法,并为 `TodoItem` 实体添加映射代码: ````csharp -public static void ConfigureTodoApp(this ModelBuilder builder) +protected override void OnModelCreating(ModelBuilder builder) { - Check.NotNull(builder, nameof(builder)); + base.OnModelCreating(builder); + + /* Include modules to your migration db context */ + builder.ConfigurePermissionManagement(); + ... + + /* Configure your own tables/entities inside here */ builder.Entity(b => { b.ToTable("TodoItems"); @@ -165,40 +171,41 @@ public static void ConfigureTodoApp(this ModelBuilder builder) } ```` -我们已经将 `TodoItem` 实体映射到数据库中的 `TodoItems` 表. +我们已经将 `TodoItem` 实体映射到数据库中的 `TodoItems` 表。 -### 代码优先迁移 +### Code First 迁移 -解决方案启动模版已经配置为使用Entity Framework Core [Code First 迁移](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations).由于我们已经更改了数据库映射配置,因此我们应该创建一个新的迁移并将更改应用于数据库. +解决方案快速模版已经配置为使用Entity Framework Core的 [Code First 迁移](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations)。 由于我们已经更改了数据库映射配置,因此我们应该创建一个新的迁移并将更改应用于数据库。 -在 *TodoApp.EntityFrameworkCore.DbMigrations* 项目的目录中打开一个命令行终端,然后键入以下命令: +在 *TodoApp.EntityFrameworkCore* 项目目录中打开一个命令行终端并输入以下命令: ````bash dotnet ef migrations add Added_TodoItem ```` -这将向项目添加一个新的迁移类: +这将向项目添加一个新的迁移类: ![todo-efcore-migration](todo-efcore-migration.png) -你可以在同一命令行终端中使用以下命令将更改应用于数据库: +你可以在同一命令行终端中使用以下命令将更改应用于数据库: ````bash dotnet ef database update ```` -> 如果你使用的是Visual Studio,*则可能希望在包管理器控制台 (PMC)* 中使用 `Add-Migration Added_TodoItem` 和 `Update-Database` 命令.在这种情况下,请确保 {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="BlazorServer"}}`TodoApp.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`TodoApp.HttpApi.Host`{{end}} 是启动项目,并且 `TodoApp.EntityFrameworkCore.DbMigrations` 是PMC中的 *默认项目*. +> 如果你使用的是Visual Studio,*则可能希望在包管理器控制台 (PMC)* 中使用 `Add-Migration Added_TodoItem` 和 `Update-Database` 命令。 在这种情况下,请确保 {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="BlazorServer"}}`TodoApp.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`TodoApp.HttpApi.Host`{{end}} 是启动项目,并且 `TodoApp.EntityFrameworkCore` 是PMC中的 *默认项目*。 + {{else if DB=="Mongo"}} -下一步是设置 [MongoDB](../MongoDB.md) 配置.在 *TodoApp.MongoDB* 项目的 `MongoDb` 文件夹中打开 `TodoAppMongoDbContext` 类,并进行以下更改; +下一步是设置 [MongoDB](../../MongoDB.md) 配置。 打开 *TodoApp.MongoDB* 项目中 `MongoDb` 文件夹的`TodoAppMongoDbContext` 类并做出以下更改; -1. 向类添加新属性: +1. 向类添加新属性: ````csharp public IMongoCollection TodoItems => Collection(); ```` -2. 在 `CreateModel` 方法中添加以下代码: +2. 在 `CreateModel` 方法中添加以下代码: ````csharp modelBuilder.Entity(b => @@ -209,11 +216,11 @@ modelBuilder.Entity(b => {{end}} -现在,我们可以使用ABP仓储来保存和检索待办事项列表项了,就像我们将在下一节中做的那样. +现在,我们可以使用ABP仓库保存和检索待办事项,如我们在下一节所做的那样。 ## 应用层 -[应用服务](../../Application-Services.md) 用于执行应用程序的用例.我们需要执行以下用例; +[应用程序服务](../../Application-Services.md) 用于执行应用程序的用例。 我们需要执行以下用例: * 获取待办事项列表 * 创建新的待办事项 @@ -221,7 +228,7 @@ modelBuilder.Entity(b => ### 应用服务接口 -我们可以从为应用程序服务定义一个接口开始.在 *TodoApp.Application.Contracts* 项目中创建一个新的 `ITodoAppService` 接口,如下所示: +我们可以先从为应用程序服务定义接口开始。 在 *TodoAppp.Application.application.contracts* 项目中创建新的 `ITodoAppService` 接口,如下所示: ````csharp using System; @@ -242,7 +249,7 @@ namespace TodoApp ### 数据传输对象 -`GetListAsync` 和 `CreateAsync` 方法返回 `TodoItemDto`. 通常应用服务获取或返回的是 DTO ([数据传输对象](../../Data-Transfer-Objects.md)) 而不是直接获取或返回实体对象. 所以,我们应该在此定义 DTO(数据传输对象) 类. 在 *TodoApp.Application.Contracts* 项目中创建一个名为 `TodoItemDto` 的类: +`GetListAsync` 和`CreateAsync` 方法返回 `TodoItemDto`。 `应用程序服务` 通常获取并返回 DTO ([数据传输对象](../../Data-Transfer-Objects.md)) 而不是实体。 因此,我们应该在这里定义DTO类。 在 *TodoApp.Application.Contracts* 项目中创建新的 `TodoItemDto` 类: ````csharp using System; @@ -257,11 +264,11 @@ namespace TodoApp } ```` -这是一个非常简单的DTO类,与我们的 `TodoItem` 实体相对应.我们接下来实现 `ITodoAppService` 接口. +这是一个非常简单的DTO类,它与我们的 `TodoItem` 实体相对应。 接下来,我们准备实现 `ITodoAppService`接口。 ### 应用服务实现 -在 *TodoApp.Application* 项目内部创建一个 `TodoAppService` 类,如下所示: +在 *TodoApp.Application* 项目中创建 `TodoAppService` 类,如下所示: ````csharp using System; @@ -281,17 +288,17 @@ namespace TodoApp { _todoItemRepository = todoItemRepository; } - + // TODO: Implement the methods here... } } ```` -该类继承自ABP框架的 `ApplicationService` 类,并实现了之前定义的 `ITodoAppService`接口.ABP为实体提供默认的通用的 [仓储](../repositories.md).我们可以使用它们来执行基本的数据库操作. 这个类 [注入](../Dependency-Injection.md) `IRepository` 它是 `TodoItem` 实体的默认存储库.我们将使用它来实现之前描述的用例. +该类继承自ABP框架的`ApplicationService`类,并实现了之前定义的 `ITodoAppService`接口。 ABP为实体提供默认的泛型 [仓储](../../Repositories.md)。 我们可以使用它们来执行基本的数据库操作 此类 [注入](../../Dependency-Injection.md) `IRepository`,它是 `TodoItem` 实体的默认存储库。 我们将使用它来实现之前描述的用例。 -#### 获取所有待办事项列表 +#### 获取待办事项 -让我们开始实现 `GetListAsync` 方法: +让我们先实现 `GetListAsync` 方法: ````csharp public async Task> GetListAsync() @@ -306,11 +313,11 @@ public async Task> GetListAsync() } ```` -我们只是简单的从数据库中获取完整的 `TodoItem` 列表,将它们映射到 `TodoItemDto` 对象并作为结果返回. +我们只是从数据库中获取完整的`TodoItem`列表,将它们映射到`TodoItemDto`对象并作为结果返回。 #### 创建一个新的待办事项 -下一个方法是 `CreateAsync`,我们可以像如下所示来实现: +下一个我们可以实现方法是 `CreateAsync` ,如下所示: ````csharp public async Task CreateAsync(string text) @@ -327,11 +334,11 @@ public async Task CreateAsync(string text) } ```` -仓储的 `InsertAsync` 方法将给定的 `TodoItem` 插入数据库,并返回相同的 `TodoItem` 对象.它还设置了 `Id`,因此我们可以在返回对象上使用它.我们只是通过从新的 `TodoItem` 实体创建和返回 `TodoItemDto`. +仓储的 `InsertAsync` 方法将给定的`TodoItem`插入数据库,并返回相同的`TodoItem` 对象。 它还设置了`Id`,因此我们可以在返回对象上使用它。 我们只是通过从新的 `TodoItem` 实体创建和返回 `TodoItemDto`。 #### 删除待办事项 -最后,我们可以将 `DeleteAsync` 实现为以下代码块: +最后,我们来实现 `DeleteAsync` 方法,代码如下: ````csharp public async Task DeleteAsync(Guid id) @@ -340,21 +347,21 @@ public async Task DeleteAsync(Guid id) } ```` -至此,应用程序服务已准备好了让UI层来使用. +至此,应用程序服务已准备好了让UI层来使用。 ## 用户界面层 -是时候在UI上显示待办事项了!在开始编写代码之前,最好记住我们正在尝试构建的内容.这是最终UI的示例屏幕截图: +现在是在UI上显示待办事项的时候了! 在开始编写代码之前,最好记住我们正在尝试构建的内容。 这里是示例程序的最终用户界面的截图: -![todo-list](todo-list.png) +![待办事项列表](todo-list.png) -> **我们将在本教程中保持最简洁轻量的UI端,以使本教程简单且重点突出.请参阅[web应用程序开发教程](../Part-1.md) 以构建包含各个方面的真实页面.** +> **我们将在本教程中保持最简洁的UI端,以使本教程简单且重点突出。 请参阅 [web应用程序开发教程](../Part-1.md) 来了解构建实际应用各个方面。** {{if UI=="MVC"}} ### Index.cshtml.cs -在 *TodoApp.Web* 项目的 `Pages` 文件夹中打开 `Index.cshtml.cs` 文件,并用以下代码块替换它的默认内容: +打开在 *TodoApp.Web* 项目的 `Pages` 文件夹中`Index.cshtml.cs`文件,并用以下代码块替换它的默认内容: ````csharp using System.Collections.Generic; @@ -381,11 +388,11 @@ namespace TodoApp.Web.Pages } ```` -此类使用 `ITodoAppService` 获取待办事项目列表并将它赋值给 `TodoItems` 属性.我们将用它来渲染razor页面上的待办事项目列表. +此类使用 `ITodoAppService` 获取待办事项列表并将它赋值给 `Todoitems` 属性。 我们将用它来渲染razor页面上的待办事项目列表。 ### Index.cshtml -在 *TodoApp.Web* 项目的 `Pages` 文件夹中打开 `Index.cshtml` 文件,并替换为以下内容: +打开 *TodoApp.Web* 项目中`Pages`文件夹下的`Index.cshtml`,并替换为以下内容: ````xml @page @@ -412,7 +419,7 @@ namespace TodoApp.Web.Pages placeholder="enter text..."> - +
    @foreach (var todoItem in Model.TodoItems) @@ -427,32 +434,32 @@ namespace TodoApp.Web.Pages ```` -我们使用ABP的 [卡片标签助手](../../UI/AspNetCore/Tag-Helpers/Cards.md) 创建一个简单的卡片视图.你可以直接使用标准的bootstrap HTML, 不过ABP的[标签助手](../../UI/AspNetCore/Tag-Helpers/Index.md) 使它更简单并且类型安全. +我们使用 ABP 的 [卡片标签助手](../../UI/AspNetCore/Tag-Helpers/Cards.md) 来创建一个简单的卡片视图。 您可以直接使用标准引导HTML结构,但ABP [标签助手](../../UI/AspNetCore/Tag-Helpers/Index.md) 使它更容易并且更安全。 -这个页面要导入一个CSS和一个JavaScript文件,所以我们也应该创建它们. +此页面导入一个 CSS 和 JavaScript 文件,所以我们需要创建它们。 ### Index.js -在 *TodoApp.Web* 项目的 `Pages` 文件夹中打开 `Index.js` 文件,并替换为以下内容: +打开 *TodoApp.Web* 项目中`Pages`文件夹下的`Index.js`,并替换为以下内容: ````js $(function () { - + // DELETING ITEMS ///////////////////////////////////////// $('#TodoList').on('click', 'li i', function(){ var $li = $(this).parent(); var id = $li.attr('data-id'); - + todoApp.todo.delete(id).then(function(){ $li.remove(); abp.notify.info('Deleted the todo item.'); }); }); - + // CREATING NEW ITEMS ///////////////////////////////////// $('#NewItemForm').submit(function(e){ e.preventDefault(); - + var todoText = $('#NewItemText').val(); todoApp.todo.create(todoText).then(function(result){ $('
  • ') @@ -464,15 +471,15 @@ $(function () { }); ```` -在第一部分中,我们在待办事项目附近注册点击删除图标所要触发的事件,删除服务器上的相关待办事项并在UI上显示通知.另外,我们从DOM中删除已删除的项,因此我们不需要刷新页面. +在第一部分中,我们注册了在待办事项旁边的删除图标的点击事件,来删除服务器上的相关项目并在UI上显示通知。 此外,我们会从 DOM 中移除已删除的项目,所以我们不需要刷新页面。 -在第二部分中,我们在服务器上创建一个新的待办事项.如果成功,我们将操纵DOM以将新的 `
  • ` 元素插入todo列表.这样,创建新的待办事项后就不用刷新整个页面了. +在第二部分中,我们在服务器上创建一个新的待办事项。 如果成功,我们将操纵DOM来将新的 `
  • ` 元素插入到待办事项列表。 这样我们不需要在创建新的待办事项后刷新整个页面。 -这里有趣的部分是我们如何与服务器通信.请参阅 *动态JavaScript代理和自动API控制器* 部分,以了解其工作原理.但是现在让我们继续并完成这个应用程序. +这里有趣的部分是我们如何与服务器通信。 请参阅 *动态JavaScript代理和自动API控制器* 部分来了解其工作原理。 但是现在让我们继续并完成这个应用程序。 ### Index.css -来到最后要做的工作,请打开 *TodoApp.Web* 项目的 `Pages` 文件夹中的 `Index.css` 文件,并替换为以下内容: +最后,请打开 *TodoApp.Web* 项目的 `Pages` 文件夹中的 `Index.css` 文件,并替换为以下内容: ````css #TodoList{ @@ -501,17 +508,17 @@ $(function () { } ```` -这是待办事项页面的简单样式.我们相信你可以做得更好 :) +这是待办事项页面的简单样式。 我们相信你可以做得更好 :) -现在,你可以再次运行应用程序以查看结果. +现在,你可以再次运行应用程序并看到结果。 -### Dynamic JavaScript Proxies & Auto API Controllers 动态JavaScript代理和自动应用编程接口控制器 +### 动态JavaScript 代理服务器 和 自动API控制器 -在 `Index.js` 文件中,我们使用了 `todoApp.todo.delete(...)` 和 `todoApp.todo.create(...)` 函数与服务器通信.这些函数是由ABP框架动态创建的,这要归功于 [动态JavaScript客户端代理](../UI/AspNetCore/Dynamic-JavaScript-Proxies.md) 系统.他们对服务器执行HTTP API调用并返回承诺,因此你可以像上面所做的那样注册对 `then` 函数的回调. +在 `Index.js` 文件中,我们使用了 `todoApp.delete(...)` 和 `todoApp.todo.create(...)` 方法来与服务器通信。 这些函数是由ABP 框架动态创建的,这要归功于 [动态JavaScript 客户端代理](../../UI/AspNetCore/Dynamic-JavaScript-Proxies.md) 系统。 它们执行 HTTP API 服务器调用并返回一个Promise, 这样你就可以使用 `then` 函数注册一个回调,如之前所做的那样。 -但是,你可能会问我们还没有创建任何API控制器,那么服务器如何处理这些请求呢? 这个问题为我们引出了ABP框架的 [自动API控制器](../API/Auto-API-Controllers.md) 功能.它通过约定自动将应用程序服务转换为API Controllers(API控制器). +但是,你可能会注意到我们还没有创建任何API控制器,所以服务器如何处理这些请求? 这个问题为我们引出了ABP 框架的 [自动API控制器](../../API/Auto-API-Controllers.md) 功能。 它通过约定自动将应用程序服务转换为 API 控制器。 -如果通过在应用程序中输入 `/swagger` URL来打开 [swagger UI](https://swagger.io/tools/ Swagger-ui/),则可以看到Todo API: +如果你在应用程序URL中输入 `/swagger` 来打开 [Swagger UI](https://swagger.io/tools/swagger-ui/) ,就会看到Todo API: ![todo-api](todo-api.png) @@ -519,7 +526,7 @@ $(function () { ### Index.razor.cs -在 *TodoApp.Blazor* 项目的 `Pages` 文件夹中打开 `Index.razor.cs` 文件,并用以下代码块替换内容: +打开在*TodoApp.Blazor*项目的`Pages`文件夹中`Index.razor.cs`文件,并替换为一下内容: ````csharp using Microsoft.AspNetCore.Components; @@ -540,7 +547,7 @@ namespace TodoApp.Blazor.Pages { TodoItems = await TodoAppService.GetListAsync(); } - + private async Task Create() { var result = await TodoAppService.CreateAsync(NewTodoText); @@ -558,17 +565,17 @@ namespace TodoApp.Blazor.Pages } ```` -这个类使用 `ITodoAppService` 对待办事项执行操作.它在创建和删除操作后操纵 `TodoItems` 列表.这样,我们不需要从服务器刷新整个todo列表. +此类使用 `ITodoAppService` 来执行待办事项的操作。 它在创建和删除操作后操纵 `TodoItems` 列表。 这样,我们不需要从服务器刷新整个待办事项列表。 {{if UI=="Blazor"}} -请参阅下面的 *动态C # 代理和自动API控制器* 部分,了解如何从浏览器上运行的Blazor应用程序注入和使用应用程序服务接口!但是现在,让我们继续并完成这个应用. +请参阅下面的 *动态C # 代理和自动API控制器* 部分,来了解我们如何在浏览器上运行的 Blazor 应用程序中注入和使用应用服务接口! 但是现在让我们继续并完成这个应用程序。 {{end # Blazor}} ### Index.razor -在 *TodoApp.Blazor* 项目的 `Pages` 文件夹中打开 `Index.razor` 文件,并用以下代码块替换内容: +打开在*TodoApp.Blazor*项目的`Pages`文件夹中 `Index.razor`文件,并替换为以下代码块内容: ````xml @page "/" @@ -611,7 +618,7 @@ namespace TodoApp.Blazor.Pages ### Index.razor.css -最后,请在 *TodoApp.Web* 项目的 `Pages` 文件夹中打开 `Index.razor.css` 文件,并替换为以下内容: +最后,请打开 *TodoApp.Blazor* 项目的 `Pages` 文件夹中的 `Index.razor.css`文件,并替换为以下内容: ````css #TodoList{ @@ -640,21 +647,21 @@ namespace TodoApp.Blazor.Pages } ```` -这是待办事项页面的简单样式.我们相信你可以做得更好 :) +这是待办事项页面的简单样式。 我们相信你可以做得更好 :) -现在,你可以再次运行应用程序以查看结果. +现在,你可以再次运行应用程序来查看结果。 {{if UI=="Blazor"}} -### Dynamic C# Proxies & Auto API Controllers 动态C#代理和自动应用编程接口控制器 +### 动态C#代理 & 自动API控制器 -在 `Index.razor.cs` 文件中,我们已经注入(使用 `[Inject]` 特性)并像使用本地服务一样使用 `ITodoAppService`.请记住,当此应用程序服务的实例在服务器上运行的同时,Blazor应用程序正在浏览器上运行. +在 `Index.razor.cs` 文件中,我们已经注入(使用 `[Inject]` 特性)并像使用本地服务一样使用 `ITodoAppService`。 请记住,Blazor应用程序正在在浏览器上运行,而此应用程序服务正在服务器上运行。 -这个神奇的过程是由ABP框架的 [动态C#客户端代理](../API/Dynamic-CSharp-API-Clients.md) 系统完成的.它使用标准的 `HttpClient` 并向远程服务器执行HTTP API请求.它还为我们处理所有标准任务,包括授权,JSON序列化和异常处理. +这个神奇的过程是由ABP框架的 [动态 C# 客户端代理](../../API/Dynamic-CSharp-API-Clients.md) 系统完成。 它使用标准的`HttpClient` 并执行HTTP API 请求到远程服务器。 它还为我们处理所有标准任务,包括授权、JSON序列化和异常处理。 -但是,你可能会问我们还没有创建任何API控制器,那么服务器如何处理这些请求呢? 这个问题为我们引出了ABP框架的 [自动API控制器](../API/Auto-API-Controllers.md) 功能.它通过约定自动将应用程序服务转换为API控制器. +但是,你可能会问我们还没有创建任何API控制器,那么服务器如何处理这些请求呢? 这个问题为我们引出了ABP 框架的 [自动API控制器](../../API/Auto-API-Controllers.md) 功能。 它通过约定自动将应用程序服务转换为 API 控制器。 -如果你运行 `TodoApp.HttpApi.Host` 应用程序,你可以看到Todo API: +如果你运行 `TodoApp.HttpApi.Host` 应用程序,你可以看到Todo API: ![todo-api](todo-api.png) @@ -664,20 +671,21 @@ namespace TodoApp.Blazor.Pages ### 服务代理生成 -ABP提供了一个方便的功能,可以自动创建客户端服务,轻松使用服务器提供的HTTP APIs. +ABP提供了一个便捷的功能来自动创建客户端服务,以方便地使用由服务器提供的HTTP APIs。 + +你首先需要运行 `TodoApp.HttpApi.Host` 项目,因为代理生成器从服务器应用程序读取API定义。 -你首先需要运行 `TodoApp.HttpApi.Host` 项目,因为代理生成器从服务器应用程序读取API定义. +> **请注意**: IIS Express有一个问题:它不允许从另一个进程连接到应用程序。 如果你使用的是Visual Studio,请在 “运行” 按钮下拉列表中选择`TodoApp.HttpApi.Host` 来替代IIS Express,如下图所示: -> **请注意**: IIS Express有问题; 它不允许从另一个进程连接到应用程序.如果你使用的是Visual Studio,请在 “运行” 按钮下拉列表中选择 `TodoApp.HttpApi.Host` 而不是IIS Express,如下图所示: -![run-without-iisexpress](run-without-iisexpress.png) +![运行时不使用 iisexpress](run-without-iisexpress.png) -运行 `TodoApp.HttpApi.Host` 项目后,在 `angular` 文件夹中打开命令行终端,然后键入以下命令: +当启动 `TodoApp.HttpApi.Host` 项目后,在`angular`文件夹中打开一个命令行终端并输入以下命令: ````bash abp generate-proxy ```` -如果一切顺利,应该生成如下所示的输出: +如果一切顺利,它应该生成如下输出: ````bash CREATE src/app/proxy/generate-proxy.json (170978 bytes) @@ -687,11 +695,11 @@ CREATE src/app/proxy/models.ts (66 bytes) CREATE src/app/proxy/index.ts (58 bytes) ```` -然后,我们可以使用 `todoService` 来使用服务器端HTTP APIs,就像我们将在下一节中做的那样. +然后,我们可以使用 `todoService` 来使用服务器端HTTP APIs ,就像我们将在下一节中做的那样。 ### home.component.ts -打开 `/angular/src/app/home/home.component.ts` 文件,并用以下代码块替换其内容: +打开 `/angular/src/app/home/home.component.html` 文件,并用以下代码块替换其内容: ````js import { ToasterService } from '@abp/ng.theme.shared'; @@ -718,7 +726,7 @@ export class HomeComponent implements OnInit { this.todoItems = response; }); } - + create(): void{ this.todoService.create(this.newTodoText).subscribe((result) => { this.todoItems = this.todoItems.concat(result); @@ -736,11 +744,11 @@ export class HomeComponent implements OnInit { ```` -我们已经实现了使用 `todoService` 来获取待办事项目列表,并将返回值赋值给 `todoItems` 数组.我们还添加了 `create`和 `delete` 方法.这些方法将在视图端使用. +我们已经实现了使用 `todoService` 来获取待办事项目列表,并将返回值赋值给 `todoItems` 数组。 我们还添加了 `create` 和 `delete` 方法。 这些方法将在视图端使用。 ### home.component.html -打开 `/angular/src/app/home/home.component.html` 文件,并用以下代码块替换其内容: +打开 `/angular/src/app/home/home.component.html` 文件,并用以下代码块替换其内容: ````html
    @@ -774,7 +782,7 @@ export class HomeComponent implements OnInit { ### home.component.scss -最后的最后,打开 `/angular/src/app/home/home.component.scss` 文件,并用以下代码块替换其内容: +最后,打开`/angular/src/app/home/home.component.scss` 文件,并用以下代码块替换其内容: ````css #TodoList{ @@ -803,19 +811,19 @@ export class HomeComponent implements OnInit { } ```` -这是待办事项页面的简单样式.我们相信你可以做得更好 :) +这是待办事项页面的简单样式。 我们相信你可以做得更好 :) -现在,你可以再次运行应用程序以查看结果. +现在,你可以再次运行应用程序来查看结果。 {{end}} ## 总结 -在本教程中,我们构建了一个非常简单的应用程序来抢先探究ABP框架的新特性.如果你想构建一个实际场景的应用程序,请查看 [应用程序开发教程](../Part-1.md),其中涵盖了实际web应用程序开发的所有方面. +在这个教程中,我们已经建立了一个非常简单的应用程序来熟悉 ABP 框架。 如果你想要构建一个实际场景的应用程序, 请检查 [web 应用程序开发教程](../Part-1.md) ,该教程涵盖了真实的 web 应用程序开发的所有方面。 ## 源代码 -你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/TodoApp)获取到完整的应用程序源代码. +你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/TodoApp)找到已完成的项目源代码。 ## 另请参见 From a6f1527b2c607ffdaf0d9d4b88f27407e156a82a Mon Sep 17 00:00:00 2001 From: gsonovb Date: Mon, 30 Aug 2021 09:10:54 +0800 Subject: [PATCH 3/7] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Update=20TODO=20imag?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tutorials/Todo/todo-efcore-migration.png | Bin 9490 -> 7122 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/zh-Hans/Tutorials/Todo/todo-efcore-migration.png b/docs/zh-Hans/Tutorials/Todo/todo-efcore-migration.png index df370aebcf44b25ad02ab77df496cc6790690f72..9fffeb716b28b0469976071f38492ed17d03dd51 100644 GIT binary patch literal 7122 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 K2UY^L4EulYZ34{z literal 9490 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 Date: Tue, 31 Aug 2021 12:51:07 +0800 Subject: [PATCH 4/7] =?UTF-8?q?docs:=20=20=F0=9F=93=9D=20Update=20todo=20t?= =?UTF-8?q?utorial=20Chinese=20translation=20=20=F0=9F=93=9D=20Correct=20t?= =?UTF-8?q?odo=20tutorial=20English=20document=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/Tutorials/Todo/Index.md | 2 +- docs/zh-Hans/Tutorials/Todo/Index.md | 194 +++++++++++++-------------- 2 files changed, 98 insertions(+), 98 deletions(-) diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index 9f4a33a9c00..8eca93feadc 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -618,7 +618,7 @@ Open the `Index.razor` file in the `Pages` folder of the *TodoApp.Blazor* projec ### Index.razor.css -As the final touch, open the `Index.razor.css` file in the `Pages` folder of the *TodoApp.Web* project and replace with the following content: +As the final touch, open the `Index.razor.css` file in the `Pages` folder of the *TodoApp.Blazor* project and replace with the following content: ````css #TodoList{ diff --git a/docs/zh-Hans/Tutorials/Todo/Index.md b/docs/zh-Hans/Tutorials/Todo/Index.md index 5a18e2302a6..42c3b4ffd41 100644 --- a/docs/zh-Hans/Tutorials/Todo/Index.md +++ b/docs/zh-Hans/Tutorials/Todo/Index.md @@ -8,15 +8,15 @@ } ```` -这是一个由单个部分组成的快速入门教程,旨在使用ABP框架构建一个简单的待办事项应用程序。 这是最终应用程序的屏幕截图: +这是一个由单个部分组成的快速入门教程, 旨在使用ABP框架构建一个简单的待办事项应用程序. 这是最终应用程序的屏幕截图: ![待办事项列表](todo-list.png) -你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/TodoApp)找到已完成的项目源代码。 +你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/TodoApp)找到已完成的项目源代码. ## 先决条件 -* 一个集成开发环境 (比如: [Visual Studio](https://visualstudio.microsoft.com/vs/)) 它需要支持 [.NET 5.0+](https://dotnet.microsoft.com/download/dotnet) 的开发。 +* 一个集成开发环境 (比如: [Visual Studio](https://visualstudio.microsoft.com/vs/)) 它需要支持 [.NET 5.0+](https://dotnet.microsoft.com/download/dotnet) 的开发. {{if DB=="Mongo"}} @@ -32,13 +32,13 @@ ## 创建新的解决方案 -我们将使用[ABP CLI](../../CLI.md) 创建带有ABP框架的新解决方案。 你可以在命令行终端中运行以下命令来安装它: +我们将使用[ABP CLI](../../CLI.md) 创建带有ABP框架的新解决方案. 你可以在命令行终端中运行以下命令来安装它: ````bash dotnet tool install -g Volo.Abp.Cli ```` -然后创建一个空文件夹,打开命令行终端并在终端中执行以下命令: +然后创建一个空文件夹, 打开命令行终端并在终端中执行以下命令: ````bash abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{else if UI=="NG"}} -u angular{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} @@ -46,21 +46,21 @@ abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u bl {{if UI=="NG"}} -这将创建一个名为*TodoApp*的新解决方案,其中包含`angular`和`aspnet core`文件夹。 一旦解决方案就绪,请在您最喜欢的 IDE 中打开ASP.NET Core 解决方案。 +这将创建一个名为*TodoApp*的新解决方案, 其中包含`angular`和`aspnet core`文件夹. 一旦解决方案就绪, 请在你最喜欢的 IDE 中打开 ASP.NET Core 解决方案. {{else}} -这将创建一个名为*TodoApp*的新解决方案。 一旦解决方案就绪,请在您最喜欢的 IDE 中打开它。 +这将创建一个名为*TodoApp*的新解决方案. 一旦解决方案就绪, 请在你最喜欢的 IDE 中打开它. {{end}} ### 创建数据库 -如果你使用的是Visual Studio,请右键单击`TodoApp.DbMigrator`项目,选择*设置为启动项目*,然后按*Ctrl+F5*运行它而不进行调试。 它将创建初始数据库并生成初始数据。 +如果你使用的是Visual Studio, 请右键单击`TodoApp.DbMigrator`项目, 选择*设置为启动项目*, 然后按*Ctrl+F5*运行它而不进行调试. 它将创建初始数据库并生成初始数据. {{if DB=="EF"}} -> 一些IDE (例如Rider) 可能会在第一次运行时遇到问题,因为 *DbMigrator* 添加初始迁移并重新编译项目。 在这种情况下,在 `.DbMigrator` 项目文件夹中打开命令行终端并执行 `dotnet run` 命令。 +> 一些IDE (例如Rider) 可能会在第一次运行时遇到问题, 因为 *DbMigrator* 添加初始迁移并重新编译项目. 在这种情况下, 在 `.DbMigrator` 项目文件夹中打开命令行终端并执行 `dotnet run` 命令. {{end}} @@ -68,59 +68,59 @@ abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u bl {{if UI=="MVC" || UI=="BlazorServer"}} -最好在开始开发之前运行一下应用程序。 确保 {{if UI=="BlazorServer"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} 是启动项目,然后运行应用程序(Visual Studio中是Ctrl+F5)来查看初始UI: +最好在开始开发之前运行一下应用程序. 确保 {{if UI=="BlazorServer"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} 是启动项目, 然后运行应用程序(Visual Studio中是Ctrl+F5)来查看初始UI: {{else if UI=="Blazor"}} -最好在开始开发之前运行一下应用程序。 解决方案中有两个主要应用程序 +最好在开始开发之前运行一下应用程序. 解决方案中有两个主要应用程序 -* `TodoApp.HttpApi.Host` 承载服务器端的 HTTP API。 -* `TodoApp.Blazor` 是客户端的Blazor WebAssembly应用程序。 +* `TodoApp.HttpApi.Host` 承载服务器端的 HTTP API. +* `TodoApp.Blazor` 是客户端的Blazor WebAssembly应用程序. -确保 `TodoApp.HttpApi.Host` 是启动项目,然后运行应用程序(Visual Studio中的Ctrl+F5)打开[Swagger UI](https://swagger.io/tools/swagger-ui/)来查看服务器端的 HTTP API: +确保 `TodoApp.HttpApi.Host` 是启动项目, 然后运行应用程序(Visual Studio中的Ctrl+F5)打开[Swagger UI](https://swagger.io/tools/swagger-ui/)来查看服务器端的 HTTP API: -![todo swagger-u 初始化](todo-swagger-ui-initial.png) +![todo-swagger-ui-initial](todo-swagger-ui-initial.png) -您可以使用此 UI 探索和测试您的 HTTP API。 现在,我们可以将 `TodoApp.Blazor` 设置为启动项目并运行它来打开实际的 Blazor 应用程序UI: +你可以使用此 UI 探索和测试你的 HTTP API. 现在, 我们可以将 `TodoApp.Blazor` 设置为启动项目并运行它来打开实际的 Blazor 应用程序UI: {{else if UI=="NG"}} -最好在开始开发之前运行一下应用程序。 解决方案中有两个主要应用程序; +最好在开始开发之前运行一下应用程序. 解决方案中有两个主要应用程序; -* `TodoApp.HttpApi.Host` (在.NET解决方案中)承载服务器端HTTP API。 -* `angular` 文件夹包含 Angular 应用程序。 +* `TodoApp.HttpApi.Host` (在.NET解决方案中)承载服务器端HTTP API. +* `Angular` 文件夹包含 Angular 应用程序. -确保 `TodoApp.HttpApi.Host` 是启动项目,然后运行应用程序(Visual Studio中的Ctrl+F5)打开[Swagger UI](https://swagger.io/tools/swagger-ui/)来查看服务器端的 HTTP API: +确保 `TodoApp.HttpApi.Host` 是启动项目, 然后运行应用程序(Visual Studio中的Ctrl+F5)打开[Swagger UI](https://swagger.io/tools/swagger-ui/)来查看服务器端的 HTTP API: ![todo-swagger-ui-initial](todo-swagger-ui-initial.png) -您可以使用此 UI 探索和测试您的 HTTP API。 如果该功能正常,我们可以运行Angular 客户端应用程序。 +你可以使用此 UI 探索和测试你的 HTTP API. 如果该功能正常, 我们可以运行Angular 客户端应用程序. -首先,运行以下命令来还原NPM包: +首先, 运行以下命令来还原NPM包: ````bash npm install ```` -安装所有软件包需要一些时间。 然后可以使用以下命令运行应用程序: +安装所有软件包需要一些时间. 然后可以使用以下命令运行应用程序: ````bash npm start ```` -此命令需要时间,但最终在你的默认浏览器中运行并打开应用程序: +此命令需要时间, 但最终在你的默认浏览器中运行并打开应用程序: {{end}} -![i待办事项 Ui](todo-ui-initial.png) +![todo-ui-initial](todo-ui-initial.png) -你可以单击 *登录* 按钮,以`admin`作为用户名和`1q2w3E*` 作为密码登录到应用程序。 +你可以单击 *登录* 按钮, 以`admin`作为用户名和`1q2w3E*` 作为密码登录到应用程序. -一切就绪。 我们可以开始编程! +一切就绪. 我们可以开始编程! ## 领域层 -此应用程序只有一个 [实体](../../Entities.md),接下来我们开始创建它。 在 *TodoApp.Domain* 项目中创建一个新的 `TodoItem` 类: +此应用程序只有一个 [实体](../../Entities.md), 接下来我们开始创建它. 在 *TodoApp.Domain* 项目中创建一个新的 `TodoItem` 类: ````csharp using System; @@ -135,7 +135,7 @@ namespace TodoApp } ```` -`BasicAggregateRoot` 是创建根实体的最简单的基础类。 `Guid` 是这里实体的主键 (`Id`)。 +`BasicAggregateRoot` 是创建根实体的最简单的基础类. `Guid` 是这里实体的主键 (`Id`). ## 数据库集成 @@ -145,13 +145,13 @@ namespace TodoApp ### 映射配置 -打开在 *TodoApp.EntityFrameworkCore* 项目中 `EntityFrameworkCore` 文件夹中的 `TodoAppDbContext` 类,并向该类添加新的 `DbSet` 属性: +打开在 *TodoApp.EntityFrameworkCore* 项目中 `EntityFrameworkCore` 文件夹中的 `TodoAppDbContext` 类, 并向该类添加新的 `DbSet` 属性: ````csharp public DbSet TodoItems { get; set; } ```` -然后在 `TodoAppDbContext` 类中定位到 `OnModelCreating` 方法,并为 `TodoItem` 实体添加映射代码: +然后在 `TodoAppDbContext` 类中定位到 `OnModelCreating` 方法, 并为 `TodoItem` 实体添加映射代码: ````csharp protected override void OnModelCreating(ModelBuilder builder) @@ -171,41 +171,41 @@ protected override void OnModelCreating(ModelBuilder builder) } ```` -我们已经将 `TodoItem` 实体映射到数据库中的 `TodoItems` 表。 +我们已经将 `TodoItem` 实体映射到数据库中的 `TodoItems` 表. ### Code First 迁移 -解决方案快速模版已经配置为使用Entity Framework Core的 [Code First 迁移](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations)。 由于我们已经更改了数据库映射配置,因此我们应该创建一个新的迁移并将更改应用于数据库。 +解决方案快速模版已经配置为使用Entity Framework Core的 [Code First 迁移](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations). 由于我们已经更改了数据库映射配置, 因此我们应该创建一个新的迁移并将更改应用于数据库. -在 *TodoApp.EntityFrameworkCore* 项目目录中打开一个命令行终端并输入以下命令: +在 *TodoApp.EntityFrameworkCore* 项目目录中打开一个命令行终端并输入以下命令: ````bash dotnet ef migrations add Added_TodoItem ```` -这将向项目添加一个新的迁移类: +这将向项目添加一个新的迁移类: ![todo-efcore-migration](todo-efcore-migration.png) -你可以在同一命令行终端中使用以下命令将更改应用于数据库: +你可以在同一命令行终端中使用以下命令将更改应用于数据库: ````bash dotnet ef database update ```` -> 如果你使用的是Visual Studio,*则可能希望在包管理器控制台 (PMC)* 中使用 `Add-Migration Added_TodoItem` 和 `Update-Database` 命令。 在这种情况下,请确保 {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="BlazorServer"}}`TodoApp.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`TodoApp.HttpApi.Host`{{end}} 是启动项目,并且 `TodoApp.EntityFrameworkCore` 是PMC中的 *默认项目*。 +> 如果你使用的是Visual Studio, 则可能希望在 *包管理器控制台 (PMC)* 中使用 `Add-Migration Added_TodoItem` 和 `Update-Database` 命令. 在这种情况下, 请确保 {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="BlazorServer"}}`TodoApp.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`TodoApp.HttpApi.Host`{{end}} 是启动项目, 并且 `TodoApp.EntityFrameworkCore` 是PMC中的 *默认项目*. {{else if DB=="Mongo"}} -下一步是设置 [MongoDB](../../MongoDB.md) 配置。 打开 *TodoApp.MongoDB* 项目中 `MongoDb` 文件夹的`TodoAppMongoDbContext` 类并做出以下更改; +下一步是设置 [MongoDB](../../MongoDB.md) 配置. 打开 *TodoApp.MongoDB* 项目中 `MongoDb` 文件夹的`TodoAppMongoDbContext` 类并做出以下更改; -1. 向类添加新属性: +1. 向类添加新属性: ````csharp public IMongoCollection TodoItems => Collection(); ```` -2. 在 `CreateModel` 方法中添加以下代码: +2. 在 `CreateModel` 方法中添加以下代码: ````csharp modelBuilder.Entity(b => @@ -216,11 +216,11 @@ modelBuilder.Entity(b => {{end}} -现在,我们可以使用ABP仓库保存和检索待办事项,如我们在下一节所做的那样。 +现在, 我们可以使用ABP仓库保存和检索待办事项, 如我们在下一节所做的那样. ## 应用层 -[应用程序服务](../../Application-Services.md) 用于执行应用程序的用例。 我们需要执行以下用例: +[应用程序服务](../../Application-Services.md) 用于执行应用程序的用例. 我们需要执行以下用例: * 获取待办事项列表 * 创建新的待办事项 @@ -228,7 +228,7 @@ modelBuilder.Entity(b => ### 应用服务接口 -我们可以先从为应用程序服务定义接口开始。 在 *TodoAppp.Application.application.contracts* 项目中创建新的 `ITodoAppService` 接口,如下所示: +我们可以先从为应用程序服务定义接口开始. 在 *TodoAppp.Application.Contracts* 项目中创建新的 `ITodoAppService` 接口, 如下所示: ````csharp using System; @@ -249,7 +249,7 @@ namespace TodoApp ### 数据传输对象 -`GetListAsync` 和`CreateAsync` 方法返回 `TodoItemDto`。 `应用程序服务` 通常获取并返回 DTO ([数据传输对象](../../Data-Transfer-Objects.md)) 而不是实体。 因此,我们应该在这里定义DTO类。 在 *TodoApp.Application.Contracts* 项目中创建新的 `TodoItemDto` 类: +`GetListAsync` 和`CreateAsync` 方法返回 `TodoItemDto`. `应用程序服务` 通常获取并返回 DTO([数据传输对象](../../Data-Transfer-Objects.md)) 而不是实体. 因此, 我们应该在这里定义DTO类. 在 *TodoApp.Application.Contracts* 项目中创建新的 `TodoItemDto` 类: ````csharp using System; @@ -264,11 +264,11 @@ namespace TodoApp } ```` -这是一个非常简单的DTO类,它与我们的 `TodoItem` 实体相对应。 接下来,我们准备实现 `ITodoAppService`接口。 +这是一个非常简单的DTO类, 它与我们的 `TodoItem` 实体相对应. 接下来, 我们准备实现 `ITodoAppService`接口. ### 应用服务实现 -在 *TodoApp.Application* 项目中创建 `TodoAppService` 类,如下所示: +在 *TodoApp.Application* 项目中创建 `TodoAppService` 类, 如下所示: ````csharp using System; @@ -294,11 +294,11 @@ namespace TodoApp } ```` -该类继承自ABP框架的`ApplicationService`类,并实现了之前定义的 `ITodoAppService`接口。 ABP为实体提供默认的泛型 [仓储](../../Repositories.md)。 我们可以使用它们来执行基本的数据库操作 此类 [注入](../../Dependency-Injection.md) `IRepository`,它是 `TodoItem` 实体的默认存储库。 我们将使用它来实现之前描述的用例。 +该类继承自ABP框架的`ApplicationService`类, 并实现了之前定义的 `ITodoAppService`接口. ABP为实体提供默认的泛型 [仓储](../../Repositories.md). 我们可以使用它们来执行基本的数据库操作. 此类中 [注入](../../Dependency-Injection.md) 的 `IRepository`, 它就是 `TodoItem` 实体的默认存储库. 我们将使用它来实现之前描述的用例. #### 获取待办事项 -让我们先实现 `GetListAsync` 方法: +让我们先实现 `GetListAsync` 方法: ````csharp public async Task> GetListAsync() @@ -313,11 +313,11 @@ public async Task> GetListAsync() } ```` -我们只是从数据库中获取完整的`TodoItem`列表,将它们映射到`TodoItemDto`对象并作为结果返回。 +我们只是从数据库中获取完整的`TodoItem`列表, 将它们映射到`TodoItemDto`对象并作为结果返回. #### 创建一个新的待办事项 -下一个我们可以实现方法是 `CreateAsync` ,如下所示: +下一个我们可以实现方法是 `CreateAsync` , 如下所示: ````csharp public async Task CreateAsync(string text) @@ -334,11 +334,11 @@ public async Task CreateAsync(string text) } ```` -仓储的 `InsertAsync` 方法将给定的`TodoItem`插入数据库,并返回相同的`TodoItem` 对象。 它还设置了`Id`,因此我们可以在返回对象上使用它。 我们只是通过从新的 `TodoItem` 实体创建和返回 `TodoItemDto`。 +仓储的 `InsertAsync` 方法将给定的`TodoItem`插入数据库, 并返回相同的`TodoItem` 对象. 它还设置了`Id`, 因此我们可以在返回对象上使用它. 我们只是通过从新的 `TodoItem` 实体创建和返回 `TodoItemDto`. #### 删除待办事项 -最后,我们来实现 `DeleteAsync` 方法,代码如下: +最后, 我们来实现 `DeleteAsync` 方法, 代码如下: ````csharp public async Task DeleteAsync(Guid id) @@ -347,21 +347,21 @@ public async Task DeleteAsync(Guid id) } ```` -至此,应用程序服务已准备好了让UI层来使用。 +至此, 应用程序服务已准备好了让UI层来使用. ## 用户界面层 -现在是在UI上显示待办事项的时候了! 在开始编写代码之前,最好记住我们正在尝试构建的内容。 这里是示例程序的最终用户界面的截图: +现在是在UI上显示待办事项的时候了! 在开始编写代码之前, 最好记住我们正在尝试构建的内容. 这里是示例程序的最终用户界面的截图: ![待办事项列表](todo-list.png) -> **我们将在本教程中保持最简洁的UI端,以使本教程简单且重点突出。 请参阅 [web应用程序开发教程](../Part-1.md) 来了解构建实际应用各个方面。** +> **我们将在本教程中保持最简洁的UI端, 以使本教程简单且重点突出. 请参阅 [web应用程序开发教程](../Part-1.md) 来了解构建实际应用各个方面.** {{if UI=="MVC"}} ### Index.cshtml.cs -打开在 *TodoApp.Web* 项目的 `Pages` 文件夹中`Index.cshtml.cs`文件,并用以下代码块替换它的默认内容: +打开在 *TodoApp.Web* 项目的 `Pages` 文件夹中`Index.cshtml.cs`文件, 并用以下代码块替换它的默认内容: ````csharp using System.Collections.Generic; @@ -388,11 +388,11 @@ namespace TodoApp.Web.Pages } ```` -此类使用 `ITodoAppService` 获取待办事项列表并将它赋值给 `Todoitems` 属性。 我们将用它来渲染razor页面上的待办事项目列表。 +此类使用 `ITodoAppService` 获取待办事项列表并将它赋值给 `TodoItems` 属性. 我们将用它来渲染razor页面上的待办事项目列表. ### Index.cshtml -打开 *TodoApp.Web* 项目中`Pages`文件夹下的`Index.cshtml`,并替换为以下内容: +打开 *TodoApp.Web* 项目中`Pages`文件夹下的`Index.cshtml`, 并替换为以下内容: ````xml @page @@ -434,13 +434,13 @@ namespace TodoApp.Web.Pages
    ```` -我们使用 ABP 的 [卡片标签助手](../../UI/AspNetCore/Tag-Helpers/Cards.md) 来创建一个简单的卡片视图。 您可以直接使用标准引导HTML结构,但ABP [标签助手](../../UI/AspNetCore/Tag-Helpers/Index.md) 使它更容易并且更安全。 +我们使用 ABP 的 [卡片标签助手](../../UI/AspNetCore/Tag-Helpers/Cards.md) 来创建一个简单的卡片视图. 你可以直接使用标准引导HTML结构, 但ABP [标签助手](../../UI/AspNetCore/Tag-Helpers/Index.md) 使它更容易并且更安全. -此页面导入一个 CSS 和 JavaScript 文件,所以我们需要创建它们。 +此页面导入一个 CSS 和 JavaScript 文件, 所以我们需要创建它们. ### Index.js -打开 *TodoApp.Web* 项目中`Pages`文件夹下的`Index.js`,并替换为以下内容: +打开 *TodoApp.Web* 项目中`Pages`文件夹下的`Index.js`, 并替换为以下内容: ````js $(function () { @@ -471,15 +471,15 @@ $(function () { }); ```` -在第一部分中,我们注册了在待办事项旁边的删除图标的点击事件,来删除服务器上的相关项目并在UI上显示通知。 此外,我们会从 DOM 中移除已删除的项目,所以我们不需要刷新页面。 +在第一部分中, 我们注册了在待办事项旁边的删除图标的点击事件, 来删除服务器上的相关项目并在UI上显示通知. 此外, 我们会从 DOM 中移除已删除的项目, 所以我们不需要刷新页面. -在第二部分中,我们在服务器上创建一个新的待办事项。 如果成功,我们将操纵DOM来将新的 `
  • ` 元素插入到待办事项列表。 这样我们不需要在创建新的待办事项后刷新整个页面。 +在第二部分中, 我们在服务器上创建一个新的待办事项. 如果成功, 我们将操纵DOM来将新的 `
  • ` 元素插入到待办事项列表. 这样我们不需要在创建新的待办事项后刷新整个页面. -这里有趣的部分是我们如何与服务器通信。 请参阅 *动态JavaScript代理和自动API控制器* 部分来了解其工作原理。 但是现在让我们继续并完成这个应用程序。 +这里有趣的部分是我们如何与服务器通信. 请参阅 *动态JavaScript代理和自动API控制器* 部分来了解其工作原理. 但是现在让我们继续并完成这个应用程序. ### Index.css -最后,请打开 *TodoApp.Web* 项目的 `Pages` 文件夹中的 `Index.css` 文件,并替换为以下内容: +最后, 请打开 *TodoApp.Web* 项目的 `Pages` 文件夹中的 `Index.css` 文件, 并替换为以下内容: ````css #TodoList{ @@ -508,17 +508,17 @@ $(function () { } ```` -这是待办事项页面的简单样式。 我们相信你可以做得更好 :) +这是待办事项页面的简单样式. 我们相信你可以做得更好 :) -现在,你可以再次运行应用程序并看到结果。 +现在, 你可以再次运行应用程序并看到结果. -### 动态JavaScript 代理服务器 和 自动API控制器 +### 动态JavaScript代理和自动API控制器 -在 `Index.js` 文件中,我们使用了 `todoApp.delete(...)` 和 `todoApp.todo.create(...)` 方法来与服务器通信。 这些函数是由ABP 框架动态创建的,这要归功于 [动态JavaScript 客户端代理](../../UI/AspNetCore/Dynamic-JavaScript-Proxies.md) 系统。 它们执行 HTTP API 服务器调用并返回一个Promise, 这样你就可以使用 `then` 函数注册一个回调,如之前所做的那样。 +在 `Index.js` 文件中, 我们使用了 `todoApp.todo.delete(...)` 和 `todoApp.todo.create(...)` 方法来与服务器通信. 这些函数是由ABP框架动态创建的, 这要归功于 [动态JavaScript客户端代理](../../UI/AspNetCore/Dynamic-JavaScript-Proxies.md) 系统. 它们执行 HTTP API 到服务器调用并返回一个Promise对象, 这样你就可以使用 `then` 函数注册一个回调, 像之前所做的那样. -但是,你可能会注意到我们还没有创建任何API控制器,所以服务器如何处理这些请求? 这个问题为我们引出了ABP 框架的 [自动API控制器](../../API/Auto-API-Controllers.md) 功能。 它通过约定自动将应用程序服务转换为 API 控制器。 +但是, 你可能会注意到我们还没有创建任何API控制器, 所以服务器如何处理这些请求? 这个问题为我们引出了ABP 框架的 [自动API控制器](../../API/Auto-API-Controllers.md) 功能. 它通过约定自动将应用程序服务转换为 API 控制器. -如果你在应用程序URL中输入 `/swagger` 来打开 [Swagger UI](https://swagger.io/tools/swagger-ui/) ,就会看到Todo API: +如果你在应用程序URL中输入 `/swagger` 来打开 [Swagger UI](https://swagger.io/tools/swagger-ui/) , 就会看到Todo API: ![todo-api](todo-api.png) @@ -526,7 +526,7 @@ $(function () { ### Index.razor.cs -打开在*TodoApp.Blazor*项目的`Pages`文件夹中`Index.razor.cs`文件,并替换为一下内容: +打开在*TodoApp.Blazor*项目的`Pages`文件夹中`Index.razor.cs`文件, 并替换为一下内容: ````csharp using Microsoft.AspNetCore.Components; @@ -565,17 +565,17 @@ namespace TodoApp.Blazor.Pages } ```` -此类使用 `ITodoAppService` 来执行待办事项的操作。 它在创建和删除操作后操纵 `TodoItems` 列表。 这样,我们不需要从服务器刷新整个待办事项列表。 +此类使用 `ITodoAppService` 来执行待办事项的操作. 它在创建和删除操作后操纵 `TodoItems` 列表. 这样, 我们不需要从服务器刷新整个待办事项列表. {{if UI=="Blazor"}} -请参阅下面的 *动态C # 代理和自动API控制器* 部分,来了解我们如何在浏览器上运行的 Blazor 应用程序中注入和使用应用服务接口! 但是现在让我们继续并完成这个应用程序。 +请参阅下面的 *动态C#代理和自动API控制器* 部分, 来了解我们如何在浏览器上运行的 Blazor 应用程序中使用注入和应用服务接口的! 但是现在让我们继续并完成这个应用程序. {{end # Blazor}} ### Index.razor -打开在*TodoApp.Blazor*项目的`Pages`文件夹中 `Index.razor`文件,并替换为以下代码块内容: +打开在 *TodoApp.Blazor* 项目的`Pages`文件夹中 `Index.razor`文件, 并替换为以下代码块内容: ````xml @page "/" @@ -618,7 +618,7 @@ namespace TodoApp.Blazor.Pages ### Index.razor.css -最后,请打开 *TodoApp.Blazor* 项目的 `Pages` 文件夹中的 `Index.razor.css`文件,并替换为以下内容: +最后, 请打开 *TodoApp.Blazor* 项目的 `Pages` 文件夹中的 `Index.razor.css`文件, 并替换为以下内容: ````css #TodoList{ @@ -647,21 +647,21 @@ namespace TodoApp.Blazor.Pages } ```` -这是待办事项页面的简单样式。 我们相信你可以做得更好 :) +这是待办事项页面的简单样式. 我们相信你可以做得更好 :) -现在,你可以再次运行应用程序来查看结果。 +现在, 你可以再次运行应用程序来查看结果. {{if UI=="Blazor"}} -### 动态C#代理 & 自动API控制器 +### 动态C#代理和自动API控制器 -在 `Index.razor.cs` 文件中,我们已经注入(使用 `[Inject]` 特性)并像使用本地服务一样使用 `ITodoAppService`。 请记住,Blazor应用程序正在在浏览器上运行,而此应用程序服务正在服务器上运行。 +在 `Index.razor.cs` 文件中, 我们已经注入(使用 `[Inject]` 特性)并像使用本地服务一样使用 `ITodoAppService`. 请记住, Blazor应用程序是在浏览器上运行, 但此应用程序服务的实现却是在服务器上运行的. -这个神奇的过程是由ABP框架的 [动态 C# 客户端代理](../../API/Dynamic-CSharp-API-Clients.md) 系统完成。 它使用标准的`HttpClient` 并执行HTTP API 请求到远程服务器。 它还为我们处理所有标准任务,包括授权、JSON序列化和异常处理。 +这个神奇的过程是由ABP框架的 [动态C#客户端代理](../../API/Dynamic-CSharp-API-Clients.md) 系统完成. 它使用标准的`HttpClient` 并执行HTTP API到远程服务器请求. 它还为我们处理所有标准任务, 包括授权、JSON序列化和异常处理. -但是,你可能会问我们还没有创建任何API控制器,那么服务器如何处理这些请求呢? 这个问题为我们引出了ABP 框架的 [自动API控制器](../../API/Auto-API-Controllers.md) 功能。 它通过约定自动将应用程序服务转换为 API 控制器。 +但是, 你可能会问我们还没有创建任何API控制器, 那么服务器如何处理这些请求呢? 这个问题为我们引出了ABP 框架的 [自动API控制器](../../API/Auto-API-Controllers.md) 功能. 它通过约定自动将应用程序服务转换为 API 控制器. -如果你运行 `TodoApp.HttpApi.Host` 应用程序,你可以看到Todo API: +如果你运行 `TodoApp.HttpApi.Host` 应用程序, 你可以看到Todo API: ![todo-api](todo-api.png) @@ -671,21 +671,21 @@ namespace TodoApp.Blazor.Pages ### 服务代理生成 -ABP提供了一个便捷的功能来自动创建客户端服务,以方便地使用由服务器提供的HTTP APIs。 +ABP提供了一个便捷的功能来自动创建客户端服务, 以方便地使用由服务器提供的HTTP API. -你首先需要运行 `TodoApp.HttpApi.Host` 项目,因为代理生成器从服务器应用程序读取API定义。 +你首先需要运行 `TodoApp.HttpApi.Host` 项目, 因为代理生成器从服务器应用程序读取API定义. -> **请注意**: IIS Express有一个问题:它不允许从另一个进程连接到应用程序。 如果你使用的是Visual Studio,请在 “运行” 按钮下拉列表中选择`TodoApp.HttpApi.Host` 来替代IIS Express,如下图所示: +> **请注意**: IIS Express有一个问题: 它不允许从另一个进程连接到应用程序. 如果你使用的是Visual Studio, 请在 “运行” 按钮下拉列表中选择`TodoApp.HttpApi.Host` 来替代IIS Express, 如下图所示: ![运行时不使用 iisexpress](run-without-iisexpress.png) -当启动 `TodoApp.HttpApi.Host` 项目后,在`angular`文件夹中打开一个命令行终端并输入以下命令: +当启动 `TodoApp.HttpApi.Host` 项目后, 在`angular`文件夹中打开一个命令行终端并输入以下命令: ````bash abp generate-proxy ```` -如果一切顺利,它应该生成如下输出: +如果一切顺利, 它应该生成如下输出: ````bash CREATE src/app/proxy/generate-proxy.json (170978 bytes) @@ -695,11 +695,11 @@ CREATE src/app/proxy/models.ts (66 bytes) CREATE src/app/proxy/index.ts (58 bytes) ```` -然后,我们可以使用 `todoService` 来使用服务器端HTTP APIs ,就像我们将在下一节中做的那样。 +然后, 我们可以使用 `todoService` 来使用服务器端HTTP API, 就像我们将在下一节中做的那样. ### home.component.ts -打开 `/angular/src/app/home/home.component.html` 文件,并用以下代码块替换其内容: +打开 `/angular/src/app/home/home.component.ts` 文件, 并用以下代码块替换其内容: ````js import { ToasterService } from '@abp/ng.theme.shared'; @@ -744,11 +744,11 @@ export class HomeComponent implements OnInit { ```` -我们已经实现了使用 `todoService` 来获取待办事项目列表,并将返回值赋值给 `todoItems` 数组。 我们还添加了 `create` 和 `delete` 方法。 这些方法将在视图端使用。 +我们已经实现了使用 `todoService` 来获取待办事项目列表, 并将返回值赋值给 `todoItems` 数组. 我们还添加了 `create` 和 `delete` 方法. 这些方法将在视图端使用. ### home.component.html -打开 `/angular/src/app/home/home.component.html` 文件,并用以下代码块替换其内容: +打开 `/angular/src/app/home/home.component.html` 文件, 并用以下代码块替换其内容: ````html
    @@ -782,7 +782,7 @@ export class HomeComponent implements OnInit { ### home.component.scss -最后,打开`/angular/src/app/home/home.component.scss` 文件,并用以下代码块替换其内容: +最后, 打开`/angular/src/app/home/home.component.scss` 文件, 并用以下代码块替换其内容: ````css #TodoList{ @@ -811,19 +811,19 @@ export class HomeComponent implements OnInit { } ```` -这是待办事项页面的简单样式。 我们相信你可以做得更好 :) +这是待办事项页面的简单样式. 我们相信你可以做得更好 :) -现在,你可以再次运行应用程序来查看结果。 +现在, 你可以再次运行应用程序来查看结果. {{end}} ## 总结 -在这个教程中,我们已经建立了一个非常简单的应用程序来熟悉 ABP 框架。 如果你想要构建一个实际场景的应用程序, 请检查 [web 应用程序开发教程](../Part-1.md) ,该教程涵盖了真实的 web 应用程序开发的所有方面。 +在这个教程中, 我们已经建立了一个非常简单的应用程序来熟悉 ABP 框架. 如果你想要构建一个实际场景的应用程序, 请查看 [web 应用程序开发教程](../Part-1.md), 该教程涵盖了真实的 Web 应用程序开发的所有方面. ## 源代码 -你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/TodoApp)找到已完成的项目源代码。 +你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/TodoApp)找到已完成的项目源代码. ## 另请参见 From 569a6a8b64fb19d41a5fe6185e6e9c98247250bf Mon Sep 17 00:00:00 2001 From: gsonovb Date: Tue, 31 Aug 2021 20:45:50 +0800 Subject: [PATCH 5/7] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Add=20"Quick=20Start?= =?UTF-8?q?"=20to=20Chinese=20docs=20navigation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh-Hans/docs-nav.json | 4 ++++ docs/zh-Hans/docs-params.json | 2 ++ 2 files changed, 6 insertions(+) diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 28ce41cdb16..15a770e023a 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -1,5 +1,9 @@ { "items": [ + { + "text": "快速入门", + "path": "Tutorials/Todo/Index.md" + }, { "text": "入门", "items": [ diff --git a/docs/zh-Hans/docs-params.json b/docs/zh-Hans/docs-params.json index 23d079f9bb3..46e496f2485 100644 --- a/docs/zh-Hans/docs-params.json +++ b/docs/zh-Hans/docs-params.json @@ -5,6 +5,8 @@ "displayName": "UI", "values": { "MVC": "MVC / Razor Pages", + "Blazor": "Blazor WebAssembly", + "BlazorServer": "Blazor Server", "NG": "Angular" } }, From e4795c2a32a89e27d560b4f768b95dfd70122acd Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 31 Aug 2021 21:25:58 +0800 Subject: [PATCH 6/7] Update Index.md --- docs/zh-Hans/Tutorials/Todo/Index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh-Hans/Tutorials/Todo/Index.md b/docs/zh-Hans/Tutorials/Todo/Index.md index 42c3b4ffd41..d940957c185 100644 --- a/docs/zh-Hans/Tutorials/Todo/Index.md +++ b/docs/zh-Hans/Tutorials/Todo/Index.md @@ -228,7 +228,7 @@ modelBuilder.Entity(b => ### 应用服务接口 -我们可以先从为应用程序服务定义接口开始. 在 *TodoAppp.Application.Contracts* 项目中创建新的 `ITodoAppService` 接口, 如下所示: +我们可以先从为应用程序服务定义接口开始. 在 *TodoApp.Application.Contracts* 项目中创建新的 `ITodoAppService` 接口, 如下所示: ````csharp using System; From 4a4363e2f5f087fc04d3b2fff05b79426cd64608 Mon Sep 17 00:00:00 2001 From: Qingxiao Ren Date: Wed, 1 Sep 2021 10:03:33 +0800 Subject: [PATCH 7/7] Update Part-9.md replace BlazorisePageBase with AbpCrudPageBase --- docs/en/Tutorials/Part-9.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Tutorials/Part-9.md b/docs/en/Tutorials/Part-9.md index 2a3e43c736f..e2df7c262e7 100644 --- a/docs/en/Tutorials/Part-9.md +++ b/docs/en/Tutorials/Part-9.md @@ -1022,7 +1022,7 @@ Create a new Razor Component Page, `/Pages/Authors.razor`, in the `Acme.BookStor ```` -* This code is similar to the `Books.razor`, except it doesn't inherit from the `BlazorisePageBase`, but uses its own implementation. +* This code is similar to the `Books.razor`, except it doesn't inherit from the `AbpCrudPageBase`, but uses its own implementation. * Injects the `IAuthorAppService` to consume the server side HTTP APIs from the UI. We can directly inject application service interfaces and use just like regular method calls by the help of [Dynamic C# HTTP API Client Proxy System](../API/Dynamic-CSharp-API-Clients.md), which performs REST API calls for us. See the `Authors` class below to see the usage. * Injects the `IAuthorizationService` to check [permissions](../Authorization.md). * Injects the `IObjectMapper` for [object to object mapping](../Object-To-Object-Mapping.md).