Browse Source

Improve translation details.

pull/550/head
maliming 8 years ago
parent
commit
dccab0220d
  1. 13
      docs/zh-Hans/AspNetCore/Bundling-Minification.md
  2. 12
      docs/zh-Hans/AspNetCore/Client-Side-Package-Management.md
  3. 2
      docs/zh-Hans/Background-Jobs.md
  4. 10
      docs/zh-Hans/Blog-Posts/2018-09-24-Announcement/Post.md
  5. 28
      docs/zh-Hans/Dependency-Injection.md
  6. 6
      docs/zh-Hans/Exception-Handling.md
  7. 4
      docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md
  8. 2
      docs/zh-Hans/Getting-Started-Console-Application.md
  9. 2
      docs/zh-Hans/Index.md
  10. 14
      docs/zh-Hans/Module-Development-Basics.md
  11. 2
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
  12. 70
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md
  13. 30
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md

13
docs/zh-Hans/AspNetCore/Bundling-Minification.md

@ -51,7 +51,7 @@ namespace MyCompany.MyProject
`abp-script-bundle`定义了一个带有**唯一名称**的样式包:`MyGlobalBundle`. 使用方法很容易理解. 让我们看看它是如何*工作的*:
* 当首次请求时,ABP从提供的文件中 **(延迟)lazy** 创建. 后续将从 **缓存** 中返回内容. 这意味着如果你有条件地将文件添加到包中,它只执行一次, 并且条件的任何更改都不会影响下一个请求的包.
* 在`development`环境中ABP会将包文件**单独**添加到页面中, 其他环境(`staging``production`...)会自动捆绑和压缩.
* 在`development`环境中ABP会将包文件**单独**添加到页面中, 其他环境(`staging`,`production`...)会自动捆绑和压缩.
* 捆绑文件可以是**物理**文件或[**虚拟/嵌入**](../Virtual-File-System.md)的文件.
* ABP自动将 **版本查询字符串(version query string)** 添加到捆绑文件的URL中,以防止浏览器缓存. 如:?_v=67872834243042(从文件的上次更改日期生成). 即使捆绑文件单独添加到页面(在`development`环境中), 版本控制仍然有效.
@ -89,7 +89,6 @@ namespace MyCompany.MyProject
**命名** bundles优点:
* Other **modules can contribute** to the bundle by its name (see the sections below).
* 其他模块可以通过其名称为捆绑包做出贡献(参见下面的部分).
#### 单个文件
@ -100,12 +99,10 @@ namespace MyCompany.MyProject
<abp-script src="/scripts/my-script.js" />
````
对于上面的示例包名称将是 *scripts.my-scripts*("/"替换为"."). 所有捆绑功能也可以按预期应用于单个文件.
对于上面的示例,包名称将是 *scripts.my-scripts*("/"替换为"."). 所有捆绑功能也可以按预期应用于单个文件.
### Bundling 选项
If you need to use same bundle in **multiple pages** or want to use some more **powerful features**, you can configure bundles **by code** in your [module](../Module-Development-Basics.md) class.
如果你需要在 **多个页面中使用相同的包** 或想要使用更多 **强大功能**, 你可以在[模块](../Module-Development-Basics.md)类中进行**配置**.
#### 创建一个新的捆绑包
@ -176,7 +173,7 @@ public class MyWebExtensionModule : AbpModule
将文件添加到现有bundle似乎很有用. 如果你需要**替换**bundle中的文件或者你想**有条件地**添加文件怎么办? 定义bundle贡献者可为此类情况提供额外的功能.
一个bundle的贡献者使用自定义版本bootstrap.css替换示例
一个bundle的贡献者使用自定义版本bootstrap.css替换示例:
````C#
public class MyExtensionGlobalStyleContributor : BundleContributor
@ -240,7 +237,7 @@ public class MyExtensionStyleBundleContributor : BundleContributor
#### 标准包装贡献者
将特定的NPM包资源(jscss文件)添加到包中对于该包非常简单. 例如, 你总是为bootstrap NPM包添加`bootstrap.css`文件.
将特定的NPM包资源(js,css文件)添加到包中对于该包非常简单. 例如, 你总是为bootstrap NPM包添加`bootstrap.css`文件.
所有[标准NPM包](Client-Side-Package-Management.md)都有内置的贡献者. 例如,如果你的贡献者依赖于引导程序,你可以声明它,而不是自己添加bootstrap.css.
@ -257,7 +254,7 @@ public class MyExtensionStyleBundleContributor : BundleContributor
* 防止你输入**无效的资源路径**.
* 如果资源 **路径发生变化** (依赖贡献者将处理它),则防止更改你的贡献者.
* 防止多个模块添加**重复文件**.
* 以递归方式管理依赖项(如果需要添加依赖项的依赖项).
* 以递归方式管理依赖项(如果需要,添加依赖项的依赖项).
##### Volo.Abp.AspNetCore.Mvc.UI.Packages 包

12
docs/zh-Hans/AspNetCore/Client-Side-Package-Management.md

@ -17,7 +17,7 @@ ABP是一个模块化平台. 每个开发人员都可以创建模块, 模块应
**标准包**的好处是:
* 它取决于包装的**标准版本**。 取决于此包是**安全**,因为所有模块都依赖于相同的版本。
* 它取决于包装的**标准版本**. 取决于此包是**安全**,因为所有模块都依赖于相同的版本.
* 它包含将库资源(js,css,img...文件)从**node_modules**文件夹复制到**wwwroot/libs**文件夹的gulp任务. 有关更多信息, 请参阅 *映射库资源* 部分.
依赖标准包装很容易. 只需像往常一样将它添加到**package.json**文件中. 例如:
@ -47,10 +47,10 @@ yarn
如果你需要不在标准软件包中的第三方NPM软件包,您可以在Github[repository](https://github.com/volosoft/abp)上创建Pull请求. 接受遵循这些规则的拉取请求:
* 对于NPM上的`package-name`, 包名称应该命名为`@abp/package-name`(例如`bootstrap`包的`@abp/bootstrap`).
* 对于NPM上的`package-name`, 包名称应该命名为`@abp/package-name`(例如:`bootstrap`包的`@abp/bootstrap`).
* 它应该是**最新的稳定**版本的包.
* 它应该只依赖于**单个**第三方包. 它可以依赖于多个`@abp/*`包.
* 包应包含一个`abp.resourcemapping.js`文件格式如*映射库资源*部分中所定义. 此文件应仅映射所依赖包的资源.
* 包应包含一个`abp.resourcemapping.js`文件格式,如*映射库资源*部分中所定义. 此文件应仅映射所依赖包的资源.
* 你还需要为你创建的包创建[bundle贡献者](Bundling-Minification.md).
有关示例, 请参阅当前标准包.
@ -59,15 +59,15 @@ yarn
使用NPM包和NPM/Yarn工具是客户端库的事实标准. NPM/Yarn工具在Web项目的根文件夹中创建一个**node_modules**文件夹.
下一个挑战是将所需的资源(js,css,img ...文件)从`node_modules`复制到**wwwroot**文件夹内的文件夹中,以使其可供客户端/浏览器访问.
下一个挑战是将所需的资源(js,css,img ...文件)从`node_modules`复制到**wwwroot**文件夹内的文件夹中,以使其可供客户端/浏览器访问.
ABP将基于[Gulp](https://gulpjs.com/)的任务定义为**将资源**从**node_modules**复制到**wwwroot/libs**文件夹. 每个**标准包**(参见*@ABP NPM Packages*部分)定义了自己文件的映射. 因此, 大多数情况你只配置依赖项.
**启动模板**已经配置为开箱即用的所有这些。 本节将介绍配置选项。
**启动模板**已经配置为开箱即用的所有这些. 本节将介绍配置选项.
#### 资源映射定义文件
模块应该定义一个名为`abp.resourcemapping.js`的JavaScript文件其格式如下例所示:
模块应该定义一个名为`abp.resourcemapping.js`的JavaScript文件,其格式如下例所示:
````js
module.exports = {

2
docs/zh-Hans/Background-Jobs.md

@ -19,6 +19,6 @@ ABP为后台作业提供了一个**抽象**模块和几个后台作业**实现**
后台作业是一个实现`IBackgroundJob<TArgs>`接口或继承自`BackgroundJob<TArgs>`类的类.`TArgs`是一个简单的C#类, 用于存储作业数据.
在后台发送电子邮件的后台作业例子
在后台发送电子邮件的后台作业例子:
待添加

10
docs/zh-Hans/Blog-Posts/2018-09-24-Announcement/Post.md

@ -112,7 +112,7 @@ UI组合是主要目标之一.为此,主题系统将提供菜单,工具栏和其
### 动态表单
动态表单tag helper允许你为给定的模型类动态地创建表单.例
动态表单tag helper允许你为给定的模型类动态地创建表单.例:
~~~ html
<abp-dynamic-form abp-model="@Model.PersonInput" submit-button="true" />
@ -132,7 +132,7 @@ UI组合是主要目标之一.为此,主题系统将提供菜单,工具栏和其
### 动态捆绑和压缩系统
动态捆绑和压缩系统运行在虚拟文件系统上,并且允许模块以模块化,动态和强大的方式创建,修改和交互捆绑包.一个例子
动态捆绑和压缩系统运行在虚拟文件系统上,并且允许模块以模块化,动态和强大的方式创建,修改和交互捆绑包.一个例子:
~~~ html
<abp-style-bundle>
@ -204,6 +204,6 @@ ABP已经为所有HTTP API创建动态JavaScript代理.该功能也存在于新
## 联系/链接
* 官方网站[abp.io](https://abp.io/)
* Github[github.com/abpframework](https://github.com/abpframework)
* Twitter[@abpframework](https://twitter.com/abpframework)
* 官方网站:[abp.io](https://abp.io/)
* Github:[github.com/abpframework](https://github.com/abpframework)
* Twitter:[@abpframework](https://twitter.com/abpframework)

28
docs/zh-Hans/Dependency-Injection.md

@ -4,7 +4,7 @@ ABP的依赖注入系统是基于Microsoft的[依赖注入扩展](https://docs.m
### 模块化
由于ABP是一个模块化框架,因此每个模块都通过依赖注入定义它自己的服务并通过它自己的单独[模块类](Module-Development-Basics.md)进行注册.例
由于ABP是一个模块化框架,因此每个模块都通过依赖注入定义它自己的服务并通过它自己的单独[模块类](Module-Development-Basics.md)进行注册.例:
````C#
public class BlogModule : AbpModule
@ -30,7 +30,7 @@ public class BlogModule : AbpModule
}
````
一旦跳过自动注册,你应该手动注册你的服务.在这种情况下,`AddAssemblyOf`扩展方法可以帮助你依照约定注册所有服务.例
一旦跳过自动注册,你应该手动注册你的服务.在这种情况下,`AddAssemblyOf`扩展方法可以帮助你依照约定注册所有服务.例:
````c#
public class BlogModule : AbpModule
@ -51,7 +51,7 @@ public class BlogModule : AbpModule
#### 固有的注册类型
一些特定类型会默认注册到依赖注入.例子
一些特定类型会默认注册到依赖注入.例子:
* 模块类注册为singleton.
* MVC控制器(继承``Controller``或``AbpController``)被注册为transient.
@ -73,7 +73,7 @@ public class BlogPostAppService : ApplicationService
#### 依赖接口
如果实现这些接口,则会自动将类注册到依赖注入
如果实现这些接口,则会自动将类注册到依赖注入:
* ``ITransientDependency`` 注册为transient.
* ``ISingletonDependency`` 注册为singleton.
@ -91,9 +91,9 @@ public class TaxCalculator : ITransientDependency
#### Dependency 属性
配置依赖注入服务的另一种方法是使用``DependencyAttribute``.它具有以下属性
配置依赖注入服务的另一种方法是使用``DependencyAttribute``.它具有以下属性:
* ``Lifetime``: 注册的生命周期Singleton,Transient或Scoped.
* ``Lifetime``: 注册的生命周期:Singleton,Transient或Scoped.
* ``TryRegister``: 设置``true``则只注册以前未注册的服务.使用IServiceCollection的TryAdd ... 扩展方法.
* ``ReplaceServices``: 设置``true``则替换之前已经注册过的服务.使用IServiceCollection的Replace扩展方法.
@ -112,7 +112,7 @@ public class TaxCalculator
#### ExposeServices 属性
``ExposeServicesAttribute``用于控制相关类提供了什么服务.例
``ExposeServicesAttribute``用于控制相关类提供了什么服务.例:
````C#
[ExposeServices(typeof(ITaxCalculator))]
@ -126,7 +126,7 @@ public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransie
#### 依照约定公开的服务
如果你未指定要公开的服务,则ABP依照约定公开服务.以上面定义的``TaxCalculator``为例
如果你未指定要公开的服务,则ABP依照约定公开服务.以上面定义的``TaxCalculator``为例:
* 默认情况下,类本身是公开的.这意味着你可以按``TaxCalculator``类注入它.
* 默认情况下,默认接口是公开的.默认接口是由命名约定确定.在这个例子中,``ICalculator``和``ITaxCalculator``是``TaxCalculator``的默认接口,但``ICanCalculate``不是.
@ -146,7 +146,7 @@ public class TaxCalculator : ITaxCalculator, ITransientDependency
#### 手动注册
在某些情况下,你可能需要向``IServiceCollection``手动注册服务,尤其是在需要使用自定义工厂方法或singleton实例时.在这种情况下,你可以像[Microsoft文档](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection)描述的那样直接添加服务.例
在某些情况下,你可能需要向``IServiceCollection``手动注册服务,尤其是在需要使用自定义工厂方法或singleton实例时.在这种情况下,你可以像[Microsoft文档](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection)描述的那样直接添加服务.例:
````C#
public class BlogModule : AbpModule
@ -168,7 +168,7 @@ public class BlogModule : AbpModule
#### 构造方法注入
这是将服务注入类的最常用方法.例如
这是将服务注入类的最常用方法.例如:
````C#
public class TaxAppService : ApplicationService
@ -193,7 +193,7 @@ public class TaxAppService : ApplicationService
#### 属性注入
Microsoft依赖注入库不支持属性注入.但是,ABP可以与第三方DI提供商(例如[Autofac](https://autofac.org/))集成,以实现属性注入.例
Microsoft依赖注入库不支持属性注入.但是,ABP可以与第三方DI提供商(例如[Autofac](https://autofac.org/))集成,以实现属性注入.例:
````C#
public class MyService : ITransientDependency
@ -224,7 +224,7 @@ public class MyService : ITransientDependency
#### 从IServiceProvider解析服务
你可能希望直接从``IServiceProvider``解析服务.在这种情况下,你可以将``IServiceProvider``注入到你的类并使用``GetService``方法,如下所示
你可能希望直接从``IServiceProvider``解析服务.在这种情况下,你可以将``IServiceProvider``注入到你的类并使用``GetService``方法,如下所示:
````C#
public class MyService : ITransientDependency
@ -248,13 +248,13 @@ public class MyService : ITransientDependency
如果你使用了构造函数或属性注入,则无需担心释放服务的资源.但是,如果你从``IServiceProvider``解析了服务,在某些情况下,你可能需要注意释放服务.
ASP.NET Core会在当前HTTP请求结束时释放所有服务,即使你直接从``IServiceProvider``解析了服务(假设你注入了IServiceProvider).但是,在某些情况下,你可能希望释放/处理手动解析的服务
ASP.NET Core会在当前HTTP请求结束时释放所有服务,即使你直接从``IServiceProvider``解析了服务(假设你注入了IServiceProvider).但是,在某些情况下,你可能希望释放/处理手动解析的服务:
* 你的代码在AspNet Core请求之外执行,执行者没有处理服务范围.
* 你只有对根服务提供者的引用.
* 你可能希望立即释放和处理服务(例如,你可能会创建太多具有大量内存占用且不想过度使用内存的服务).
在任何情况下,你都可以使用这样的`using`代码块来安全地立即释放服务
在任何情况下,你都可以使用这样的`using`代码块来安全地立即释放服务:
````C#
using (var scope = _serviceProvider.CreateScope())

6
docs/zh-Hans/Exception-Handling.md

@ -19,7 +19,7 @@ ABP提供了用于处理Web应用程序异常的标准模型.
#### 异常消息格式
每个异常消息都是`RemoteServiceErrorResponse` 类的实例.下面是一个只有 **Message** 属性的错误JSON
每个异常消息都是`RemoteServiceErrorResponse` 类的实例.下面是一个只有 **Message** 属性的错误JSON:
````json
{
@ -161,7 +161,7 @@ throw new UserFriendlyException(
);
````
采用这种方式是不需要本地化的.如果需要本地化消息,则可以注入**string localizer**( 请参阅[本地化文档](Localization.md) )来实现. 例
采用这种方式是不需要本地化的.如果需要本地化消息,则可以注入**string localizer**( 请参阅[本地化文档](Localization.md) )来实现. 例:
````C#
throw new UserFriendlyException(_stringLocalizer["UserNameShouldBeUniqueMessage"]);
@ -267,7 +267,7 @@ throw new BusinessException("App:010046")
### HTTP状态代码 映射
ABP尝试按照以下规则,自动映射常见的异常类型的HTTP状态代码
ABP尝试按照以下规则,自动映射常见的异常类型的HTTP状态代码:
* 对于 `AbpAuthorizationException`:
* 用户没有登录,返回 `401` (未认证).

4
docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md

@ -34,7 +34,7 @@ The solution also contains unit & integration test projects properly configured
### 创建数据库
查看`.Web`项目下`appsettings.json`文件中的 **连接字符串**
查看`.Web`项目下`appsettings.json`文件中的 **连接字符串**:
````json
{
@ -60,7 +60,7 @@ The solution is configured to use **Entity Framework Core** with **MS SQL Server
### 运行应用程序
您现在可以运行应用程序,它将会打开**home**页面
您现在可以运行应用程序,它将会打开**home**页面:
![bookstore-homepage](images/bookstore-homepage.png)

2
docs/zh-Hans/Getting-Started-Console-Application.md

@ -1,6 +1,6 @@
## 使用Console Application
本教程将介绍如何从头开始以最小的依赖关系启动ABP. 您通常希望以 **[启动模板](https://abp.io/Templates)** 开头
本教程将介绍如何从头开始以最小的依赖关系启动ABP. 您通常希望以 **[启动模板](https://abp.io/Templates)** 开头.
### 创建一个新项目

2
docs/zh-Hans/Index.md

@ -1,5 +1,7 @@
# ABP 文档
> 翻译来自[cnAbp](https://github.com/cnabp)组织,中文网会持续跟进翻译,目前Abp vNext的英文文档还未完成,大家对整体框架没有深入的理解,翻译难免存在一些问题.敬请见谅.😀
## 目录
* 入门

14
docs/zh-Hans/Module-Development-Basics.md

@ -6,7 +6,7 @@ ABP本身是一个模块化框架.它还提供了一个基础架构和架构模
### 模块类
每个模块都应该定义一个模块类.定义模块类的最简单方法是创建一个派生自``AbpModule``的类,如下所示
每个模块都应该定义一个模块类.定义模块类的最简单方法是创建一个派生自``AbpModule``的类,如下所示:
````C#
public class BlogModule : AbpModule
@ -20,7 +20,7 @@ public class BlogModule : AbpModule
##### ConfigureServices方法
``ConfigureServices``是将你的服务添加到依赖注入系统并配置其他模块的主要方法.例
``ConfigureServices``是将你的服务添加到依赖注入系统并配置其他模块的主要方法.例:
````C#
public class BlogModule : AbpModule
@ -34,7 +34,7 @@ public class BlogModule : AbpModule
你可以按照Microsoft的[文档](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection)中的说明逐个注册依赖项.但ABP有一个**依照约定的依赖注册系统**,可以自动注册程序集中的所有服务.有关依赖项注入系统的更多信息,请参阅[依赖项注入](Dependency-Injection.md)文档.
你也可以通过这种方式配置其他服务和模块.例
你也可以通过这种方式配置其他服务和模块.例:
````C#
public class BlogModule : AbpModule
@ -49,7 +49,7 @@ public class BlogModule : AbpModule
}
}
````
有关配置系统的更多信息,请参阅配置(TODOlink)文档.
有关配置系统的更多信息,请参阅配置(TODO:link)文档.
##### 配置服务前和后
@ -61,7 +61,7 @@ public class BlogModule : AbpModule
##### OnApplicationInitialization方法
你可以在启动应用程序时覆盖``OnApplicationInitialization``方法来执行代码.例
你可以在启动应用程序时覆盖``OnApplicationInitialization``方法来执行代码.例:
````C#
public class BlogModule : AbpModule
@ -76,7 +76,7 @@ public class BlogModule : AbpModule
}
````
``OnApplicationInitialization``通常由启动模块用于构建ASP.NET Core应用程序的中间件管道.例
``OnApplicationInitialization``通常由启动模块用于构建ASP.NET Core应用程序的中间件管道.例:
````C#
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
@ -111,7 +111,7 @@ public class AppModule : AbpModule
### 模块依赖
在模块化应用程序中,一个模块依赖于另一个模块并不罕见.如果一个Abp模块依赖于另一个模块,它必须声明``[DependsOn]``属性,如下所示
在模块化应用程序中,一个模块依赖于另一个模块并不罕见.如果一个Abp模块依赖于另一个模块,它必须声明``[DependsOn]``属性,如下所示:
````C#
[DependsOn(typeof(AbpAspNetCoreMvcModule))]

2
docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md

@ -200,7 +200,7 @@ namespace Acme.BookStore
* 为应用服务定义接口不是必须的,不过,我们推荐这么做.
* `IAsyncCrudAppService`中定义了基础的 **CRUD**方法:`GetAsync`, `GetListAsync`, `CreateAsync`, `UpdateAsync``DeleteAsync`.不需要扩展它.取而代之,你可以继承空的`IApplicationService`接口定义你自己的方法.
* `IAsyncCrudAppService`有一些变体,你可以为每一个方法使用单个或者多个的DTO.(译者注:意思是类似EntityDto和UpdateEntityDto可以用同一个也可以分别单独指定
* `IAsyncCrudAppService`有一些变体,你可以为每一个方法使用单个或者多个的DTO.(译者注:意思是类似EntityDto和UpdateEntityDto可以用同一个,也可以分别单独指定
)

70
docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-II.md

@ -2,17 +2,17 @@
### 关于本教程
这是本教程所有章节中的第二章下面是所有的章节:
这是本教程所有章节中的第二章.下面是所有的章节:
* [Part I: 创建项目和书籍列表页面](Part-I.md)
* **Part II: 创建,编辑,删除书籍(本章)**
* [Part III: 集成测试](Part-III.md)
你可以从 [这里](https://github.com/volosoft/abp/tree/master/samples/BookStore) 下载本程序的**源码**
你可以从 [这里](https://github.com/volosoft/abp/tree/master/samples/BookStore) 下载本程序的**源码**.
### 新增 Book 实体
通过本节, 你将会了解如何创建一个 modal form 来实现新增书籍的功能 最终成果如下图所示:
通过本节, 你将会了解如何创建一个 modal form 来实现新增书籍的功能. 最终成果如下图所示:
![bookstore-create-dialog](images/bookstore-create-dialog.png)
@ -24,7 +24,7 @@
##### CreateModal.cshtml.cs
展开 `CreateModal.cshtml`,打开 `CreateModal.cshtml.cs` 代码文件,用如下代码替换 `CreateModalModel` 类的实现:
展开 `CreateModal.cshtml`,打开 `CreateModal.cshtml.cs` 代码文件,用如下代码替换 `CreateModalModel` 类的实现:
````C#
using System.Threading.Tasks;
@ -53,9 +53,9 @@ namespace Acme.BookStore.Pages.Books
}
````
* 这个类继承了 `BookStorePageModelBase` 而非默认的 `PageModel` `BookStorePageModelBase` 继承了 `PageModel` 并且添加了一些Razor页面模型通用的属性和方法
* 该类在 `Book` 属性上标记的 `[BindProperty]` 特性绑定了post请求提交上来的数据
* 该类通过构造函数注入了 `IBookAppService` 应用服务并且在 `OnPostAsync` 方法中调用了服务的 `CreateAsync` 方法
* 这个类继承了 `BookStorePageModelBase` 而非默认的 `PageModel`. `BookStorePageModelBase` 继承了 `PageModel` 并且添加了一些Razor页面模型通用的属性和方法.
* 该类在 `Book` 属性上标记的 `[BindProperty]` 特性绑定了post请求提交上来的数据.
* 该类通过构造函数注入了 `IBookAppService` 应用服务,并且在 `OnPostAsync` 方法中调用了服务的 `CreateAsync` 方法.
##### CreateModal.cshtml
@ -80,10 +80,10 @@ namespace Acme.BookStore.Pages.Books
</abp-dynamic-form>
````
* 这个 modal 使用 `abp-dynamic-form` Tag Helper 根据 `CreateBookViewModel` 类自动构建了表单
* `abp-model` 指定了 `Book` 属性为模型对象
* `data-ajaxForm` 设置了表单通过AJAX提交
* `abp-form-content` tag helper 作为表单控件渲染位置的占位符 (这是可选的只有你在 `abp-dynamic-form` 中像本示例这样添加了其他内容才需要).
* 这个 modal 使用 `abp-dynamic-form` Tag Helper 根据 `CreateBookViewModel` 类自动构建了表单.
* `abp-model` 指定了 `Book` 属性为模型对象.
* `data-ajaxForm` 设置了表单通过AJAX提交.
* `abp-form-content` tag helper 作为表单控件渲染位置的占位符 (这是可选的,只有你在 `abp-dynamic-form` 中像本示例这样添加了其他内容才需要).
#### 添加 "New book" 按钮
@ -105,7 +105,7 @@ namespace Acme.BookStore.Pages.Books
</abp-card-header>
````
如下图所示只是在表格 **右上方** 添加了 **New book** 按钮:
如下图所示,只是在表格 **右上方** 添加了 **New book** 按钮:
![bookstore-new-book-button](images/bookstore-new-book-button.png)
@ -124,9 +124,9 @@ $('#NewBookButton').click(function (e) {
});
````
* `abp.ModalManager` 是一个在客户端打开和管理modal的辅助类它基于Twitter Bootstrap的标准modal组件通过简化的API抽象隐藏了许多细节.
* `abp.ModalManager` 是一个在客户端打开和管理modal的辅助类.它基于Twitter Bootstrap的标准modal组件通过简化的API抽象隐藏了许多细节.
现在,你可以 **运行程序** 通过新的 modal form 来创建书籍了。
现在,你可以 **运行程序** 通过新的 modal form 来创建书籍了.
### 编辑更新已存在的 Book 实体
@ -136,7 +136,7 @@ $('#NewBookButton').click(function (e) {
#### EditModal.cshtml.cs
展开 `EditModal.cshtml`打开 `EditModal.cshtml.cs` 文件( `EditModalModel` 类) 并替换成以下代码:
展开 `EditModal.cshtml`,打开 `EditModal.cshtml.cs` 文件( `EditModalModel` 类) 并替换成以下代码:
````C#
using System;
@ -176,9 +176,9 @@ namespace Acme.BookStore.Pages.Books
}
````
* `[HiddenInput]``[BindProperty]` 是标准的 ASP.NET Core MVC 特性。这里启用 `SupportsGet` 从Http请求的查询字符串中获取Id的值。
* 在 `OnGetAsync` 方法中`BookAppService.GetAsync` 方法返回的 `BookDto` 映射成 `CreateUpdateBookDto` 并赋值给Book属性
* `OnPostAsync` 方法直接使用 `BookAppService.UpdateAsync` 来更新实体
* `[HiddenInput]``[BindProperty]` 是标准的 ASP.NET Core MVC 特性.这里启用 `SupportsGet` 从Http请求的查询字符串中获取Id的值.
* 在 `OnGetAsync` 方法中,`BookAppService.GetAsync` 方法返回的 `BookDto` 映射成 `CreateUpdateBookDto` 并赋值给Book属性.
* `OnPostAsync` 方法直接使用 `BookAppService.UpdateAsync` 来更新实体.
#### CreateUpdateBookDto
@ -211,7 +211,7 @@ namespace Acme.BookStore
}
````
* 仅仅是添加 `[AutoMapFrom(typeof(BookDto))]` 特性就可以创建上述映射关系
* 仅仅是添加 `[AutoMapFrom(typeof(BookDto))]` 特性就可以创建上述映射关系.
#### EditModal.cshtml
@ -238,18 +238,18 @@ namespace Acme.BookStore
</abp-dynamic-form>
````
除了以下几点这个页面内容和 `CreateModal.cshtml` 非常相似:
除了以下几点,这个页面内容和 `CreateModal.cshtml` 非常相似:
* 此页面包含了一个 `abp-input` 以保存所编辑book实体的 `Id` 属性
* 此页面指定的post地址是 `Books/EditModal` ,并用文本 *Update* 作为 modal 标题。
* 此页面包含了一个 `abp-input` 以保存所编辑book实体的 `Id` 属性.
* 此页面指定的post地址是 `Books/EditModal` ,并用文本 *Update* 作为 modal 标题.
#### 为表格添加 "操作(Actions)" 下拉菜单
我们将为表格每行添加下拉按钮 ("Actions") 最终效果如下:
我们将为表格每行添加下拉按钮 ("Actions") . 最终效果如下:
![bookstore-books-table-actions](images/bookstore-books-table-actions.png)
打开 `Pages/Books/Index.cshtml` 页面并按下方所示修改表格部分的代码:
打开 `Pages/Books/Index.cshtml` 页面,并按下方所示修改表格部分的代码:
````html
<abp-table striped-rows="true" id="BooksTable">
@ -318,16 +318,16 @@ $(function () {
});
````
* 通过 `abp.localization.getResource('BookStore')` 可以在客户端使用服务器端定义的相同的本地化语言文本
* 定义 `editModal``ModalManager` 来打开编辑用的 modal 对话框
* 在 `columnDefs` 起始处新增一列作为 "Actions" 下拉按钮
* "Edit" 操作只是简单调用 `editModal.open` 来打开编辑对话框
* 通过 `abp.localization.getResource('BookStore')` 可以在客户端使用服务器端定义的相同的本地化语言文本.
* 定义 `editModal``ModalManager` 来打开编辑用的 modal 对话框.
* 在 `columnDefs` 起始处新增一列作为 "Actions" 下拉按钮.
* "Edit" 操作只是简单调用 `editModal.open` 来打开编辑对话框.
现在,你可以运行程序,通过编辑操作来更新任一个book实体。
现在,你可以运行程序,通过编辑操作来更新任一个book实体.
### 删除一个已有的Book实体
打开 `wwwroot/pages/books/index.js` 文件`rowAction` `items` 下新增一项:
打开 `wwwroot/pages/books/index.js` 文件,`rowAction` `items` 下新增一项:
````js
{
@ -346,9 +346,9 @@ $(function () {
}
````
* `confirmMessage` 用来在实际执行 `action` 之前向用户进行确认
* 通过javascript代理方法 `acme.bookStore.book.delete` 执行一个AJAX请求来删除一个book实体
* `abp.notify.info` 用来提示用户操作成功
* `confirmMessage` 用来在实际执行 `action` 之前向用户进行确认.
* 通过javascript代理方法 `acme.bookStore.book.delete` 执行一个AJAX请求来删除一个book实体.
* `abp.notify.info` 用来提示用户操作成功.
最终的 `index.js` 文件内容如下所示:
@ -414,8 +414,8 @@ $(function () {
});
````
运行程序并尝试删除一个book实体
运行程序并尝试删除一个book实体.
### 下一章
查看本教程的 [下一章](Part-III.md)
查看本教程的 [下一章](Part-III.md) .

30
docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md

@ -2,13 +2,13 @@
### About this Tutorial
这是本教程所有章节中的第三章下面是所有的章节:
这是本教程所有章节中的第三章.下面是所有的章节:
- [Part I: 创建项目和书籍列表页面](Part-I.md)
- [Part II: 创建,编辑,删除书籍](Part-II.md)
- **Part III: 集成测试(本章)**
你可以从 [这里](https://github.com/volosoft/abp/tree/master/samples/BookStore) 下载本程序的**源码**
你可以从 [这里](https://github.com/volosoft/abp/tree/master/samples/BookStore) 下载本程序的**源码**.
### 解决方案中的测试项目
@ -16,18 +16,18 @@
![bookstore-test-projects](images/bookstore-test-projects.png)
* `Acme.BookStore.Application.Tests` 项目用于单元测试和集成测试。你可以在这个项目中为Application Service方法写测试代码。这个项目使用了 **EF Core SQLite in-memory** 数据库。
* `Acme.BookStore.Web.Tests` 项目用于包含Web层的完整集成测试。所以,你也可以在这里写关于UI页面的测试。
* `Acme.BookStore.Application.Tests` 项目用于单元测试和集成测试.你可以在这个项目中为Application Service方法写测试代码.这个项目使用了 **EF Core SQLite in-memory** 数据库.
* `Acme.BookStore.Web.Tests` 项目用于包含Web层的完整集成测试.所以,你也可以在这里写关于UI页面的测试.
测试项目使用了以下库:
* [xunit](https://xunit.github.io/) 作为主测试框架
* [Shoudly](http://shouldly.readthedocs.io/en/latest/) 作为断言库
* [NSubstitute](http://nsubstitute.github.io/) 作为模拟库
* [xunit](https://xunit.github.io/) 作为主测试框架.
* [Shoudly](http://shouldly.readthedocs.io/en/latest/) 作为断言库.
* [NSubstitute](http://nsubstitute.github.io/) 作为模拟库.
### 添加测试用数据
起始模板在 `Acme.BookStore.Application.Tests` 项目中包含了 `BookStoreTestDataBuilder`,用于创建一些测试用数据。 相关代码如下所示:
起始模板在 `Acme.BookStore.Application.Tests` 项目中包含了 `BookStoreTestDataBuilder`,用于创建一些测试用数据. 相关代码如下所示:
````C#
using System.Threading.Tasks;
@ -59,8 +59,8 @@ namespace Acme.BookStore
}
````
* 这里直接使用了identity模块实现的 `IIdentityDataSeeder` 接口,创建了一个admin角色和admin用户。你同样可以在你的测试代码中直接使用这些代码。
* 你可以在 `BuildInternalAsync` 方法中添加你自己的测试数据
* 这里直接使用了identity模块实现的 `IIdentityDataSeeder` 接口,创建了一个admin角色和admin用户.你同样可以在你的测试代码中直接使用这些代码.
* 你可以在 `BuildInternalAsync` 方法中添加你自己的测试数据.
按下方所示修改 `BookStoreTestDataBuilder` 类:
@ -122,7 +122,7 @@ namespace Acme.BookStore
}
````
* 通过构造函数注入 `IRepository<Book, Guid>`,在 `BuildInternalAsync` 方法中用它创建两个book实体。
* 通过构造函数注入 `IRepository<Book, Guid>`,在 `BuildInternalAsync` 方法中用它创建两个book实体.
### 测试 BookAppService
@ -161,9 +161,9 @@ namespace Acme.BookStore
}
````
* 测试方法 `Should_Get_List_Of_Books` 直接使用 `BookAppService.GetListAsync` 方法来获取用户列表,并执行检查。
* 测试方法 `Should_Get_List_Of_Books` 直接使用 `BookAppService.GetListAsync` 方法来获取用户列表,并执行检查.
新增测试方法用以测试创建一个合法book实体的场景:
新增测试方法,用以测试创建一个合法book实体的场景:
````C#
[Fact]
@ -186,7 +186,7 @@ public async Task Should_Create_A_Valid_Book()
}
````
新增测试方法用以测试创建一个非法book实体失败的场景:
新增测试方法,用以测试创建一个非法book实体失败的场景:
````C#
[Fact]
@ -210,7 +210,7 @@ public async Task Should_Not_Create_A_Book_Without_Name()
}
````
* 由于 `Name` 是空值, ABP 抛出一个 `AbpValidationException` 异常
* 由于 `Name` 是空值, ABP 抛出一个 `AbpValidationException` 异常.
### 测试 Web 页面

Loading…
Cancel
Save