pull/1202/head
Halil İbrahim Kalkan 6 years ago
commit 8327c848c0

@ -6,7 +6,7 @@
"IsDefault": true
},
{
"DisplayName" : "Chinese",
"DisplayName" : "简体中文",
"Code" : "zh-Hans",
"IsDefault": false
}

@ -2,19 +2,39 @@
Here, a list of localization text files for anyone wants to contribute to localization of the texts coming from the framework. We will keep this list up to date:
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/en.json
* https://github.com/abpframework/abp/tree/master/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json
* https://github.com/abpframework/abp/tree/master/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain/Localization/MyProjectName/en.json
* https://github.com/abpframework/abp/tree/master/templates/module/src/MyCompanyName.MyProjectName.Domain/MyCompanyName/MyProjectName/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/templates/module/src/MyCompanyName.MyProjectName.Web/Localization/Resources/MyProjectName/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json
* https://github.com/abpframework/abp/tree/master/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json
* https://github.com/abpframework/abp/tree/master/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json

@ -91,7 +91,7 @@ This project contains the [application service](../Application-Services.md) **im
* Depends on the `.Application.Contracts` project to be able to implement the interfaces and use the DTOs.
* Depends on the `.Domain` project to be able to use domain objects (entities, repository interfaces... etc.) to perform the application logic.
#### .EntityFrameworkCore Project.
#### .EntityFrameworkCore Project
This is the integration project for the EF Core. It defines the `DbContext` and implements repository interfaces defined in the `.Domain` project.
@ -140,7 +140,7 @@ Most of time you don't need to manually define API Controllers since ABP's [Auto
This is a project that defines C# client proxies to use the HTTP APIs of the solution. You can share this library to 3rd-party clients, so they can easily consume your HTTP APIs in their Dotnet applications (For other type of applications, they can still use your APIs, either manually or using a tool in their own platform)
Most of time you don't need to manually create C# client proxies, thanks to ABP's [Cynamic C# API Clients](../AspNetCore/Dynamic-CSharp-API-Clients.md) feature.
Most of time you don't need to manually create C# client proxies, thanks to ABP's [Dynamic C# API Clients](../AspNetCore/Dynamic-CSharp-API-Clients.md) feature.
`.HttpApi.Client.ConsoleTestApp` project is a console application created to demonstrate the usage of the client proxies.

@ -16,7 +16,9 @@ public class BookStoreWebModule : AbpModule
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(BookStoreApplicationModule).Assembly);
options
.ConventionalControllers
.Create(typeof(BookStoreApplicationModule).Assembly);
});
}
}

@ -0,0 +1,136 @@
# ABP CLI
ABP CLI (命令行接口) 是一个命令行工具,用来执行基于ABP解决方案的一些常见操作.
## Installation
ABP CLI 是一个 [dotnet global tool](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools). 使用命令行窗口安装:
````bash
dotnet tool install -g Volo.Abp.Cli
````
更新最新版本:
````bash
dotnet tool update -g Volo.Abp.Cli
````
## Commands
### new
生成基于ABP[启动模板](Startup-Templates/Index.md)的新解决方案.
基本用法:
````bash
abp new <解决方案名称> [options]
````
示例:
````bash
abp new Acme.BookStore
````
* Acme.BookStore是解决方案的名称.
* 常见的命名方式类似于 *YourCompany.YourProject*. 不过你可以使用自己喜欢的方式,如 *YourProject* (单级命名空间) 或 *YourCompany.YourProduct.YourModule* (三级命名空间).
#### Options
* `--template``-t`: 指定模板. 默认的模板是 `mvc`.可用的模板有:
* `mvc` (默认): ASP.NET Core [MVC应用程序模板](Startup-Templates/Mvc.md). 其他选项:
* `--database-provider``-d`: 指定数据库提供程序. 默认提供程序是 `ef`. 可用的提供程序有:
* `ef`: Entity Framework Core.
* `mongodb`: MongoDB.
* `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的. 如果未指定会创建一个分层的解决方案, 此解决方案没有那么复杂,适合大多数场景.
* `mvc-module`: ASP.NET Core [MVC模块模板](Startup-Templates/Mvc-Module.md). 其他选项:
* `--no-ui`: 不包含UI. 仅创建服务模块 (也称为微服务 - 没有UI).
* `--output-folder``-o`: 指定输出文件夹,默认是当前目录.
### add-package
添加新的ABP包到项目中
* 添加nuget包做为项目的依赖项目.
* 添加 `[DependsOn(...)]` attribute到项目的模块类 (请参阅 [模块开发文档](Module-Development-Basics.md)).
> 需要注意的是添加的模块可能需要额外的配置,通常会在包的文档中指出.
基本用法:
````bash
abp add-package <包名> [options]
````
示例:
````
abp add-package Volo.Abp.MongoDB
````
* 示例中将Volo.Abp.MongoDB包添加到项目中.
#### Options
* `--project``-p`: 指定项目 (.csproj) 路径. 如果未指定,Cli会尝试在当前目录查找.csproj文件.
### add-module
通过查找模块的所有包,查找解决方案中的相关项目,并将每个包添加到解决方案中的相应项目,从而将多包模块添加到解决方案中.
> 由于分层,不同的数据库提供程序选项或其他原因,业务模块通常由多个包组成. 使用`add-module`命令可以大大简化向模块添加模块的过程. 但是每个模块可能需要一些其他配置,这些配置通常在相关模块的文档中指出.
基本用法:
````bash
abp add-module <模块名称> [options]
````
示例:
```bash
abp add-module Volo.Blogging
```
* 示例中将Volo.Blogging模块添加到解决方案中.
#### Options
* `--solution``-s`: 指定解决方案 (.sln) 路径. 如果未指定,CLI会尝试在当前目录中寻找.sln文件.
* `--skip-db-migrations`: 对于EF Core 数据库提供程序,它会自动添加新代码的第一次迁移 (`Add-Migration`) 并且在需要时更新数据库 (`Update-Database`). 指定此选项可跳过此操作.
### update
更新所有ABP相关的包可能会很繁琐,框架和模块都有很多包. 此命令自动将解决方案或项目中所有ABP相关的包更新到最新版本.
用法:
````bash
abp update [options]
````
* 如果你的文件夹中有.sln文件,运行命令会将解决方案中所有项目ABP相关的包更新到最新版本.
* 如果你的文件夹中有.csproj文件,运行命令会将项目中所有ABP相关的包更新到最新版本.
#### Options
* `--include-previews``-p`: 将预览版, 测试版本 和 rc 包 同时更新到最新版本.
### help
CLI的基本用法信息.
用法:
````bash
abp help [命令名]
````
示例:
````bash
abp help # 显示常规帮助.
abp help new # 显示有关 "New" 命令的帮助.
````

@ -2,19 +2,39 @@
这是一个来自框架的本地化文本文件列表, 任何人都可以做出贡献. 我们会将此列表保持最新:
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/en.json
* https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json
* https://github.com/abpframework/abp/tree/master/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/en.json
* https://github.com/abpframework/abp/tree/master/modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json
* https://github.com/abpframework/abp/tree/master/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json
* https://github.com/abpframework/abp/tree/master/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain/Localization/MyProjectName/en.json
* https://github.com/abpframework/abp/tree/master/templates/module/src/MyCompanyName.MyProjectName.Domain/MyCompanyName/MyProjectName/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/templates/module/src/MyCompanyName.MyProjectName.Web/Localization/Resources/MyProjectName/en.json
* https://github.com/abpframework/abp/tree/master/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Localization/Resources/AbpTenantManagement/Web/en.json
* https://github.com/abpframework/abp/tree/master/samples/BookStore/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json
* https://github.com/abpframework/abp/tree/master/samples/DashboardDemo/src/DashboardDemo.Domain/Localization/DashboardDemo/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Application.Contracts/ProductManagement/Localization/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Domain/ProductManagement/Localization/Domain/en.json
* https://github.com/abpframework/abp/tree/master/samples/MicroserviceDemo/modules/product/src/ProductManagement.Web/Localization/Resources/ProductManagement/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Application.Contracts/Localization/MyProjectName/ApplicationContracts/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/DomainShared/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc-module/src/MyCompanyName.MyProjectName.Web/Localization/MyProjectName/Web/en.json
* https://github.com/abpframework/abp/tree/master/templates/mvc/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json

@ -0,0 +1,3 @@
# Data Seeding
TODO

@ -2,37 +2,42 @@
### 创建新项目
访问[模板创建页面](https://abp.io/Templates), 输入项目名称并创建项目, 如下所示:
本教程使用 **ABP CLI** 创建一个新项目. 更多选项, 请参阅[入门](https://cn.abp.io/get-started)页面.
![bookstore-create--template](images/bookstore-create-template.png)
如果你之前未安装请使用命令行安装ABP CLI:
单击 *create* 按钮时,将使用你提供的名称创建一个新的Visual Studio解决方案并开始下载.
````bash
dotnet tool install -g Volo.Abp.Cli
````
在空文件夹中使用 `abp new` 命令来创建项目:
````
abp new Acme.BookStore
````
> 你可以使用不同级别的命名空间; 例如BookStore, Acme.BookStore或Acme.Retail.BookStore.
`new` 命令创建**分层MVC应用程序**, **Entity Framework Core**作为数据库提供程序. 但是,它还有其他选择. 有关所有可用选项,请参见[CLI文档](CLI.md)
#### 预先要求
下载的项目需要:
创建项目的要求:
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/)
* [.NET Core 2.1.1+](https://www.microsoft.com/net/download/dotnet-core/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/)
### 解决方案结构
下载后解压文件并在 **Visual Studio 2017(15.7.0 +)** 中打开:
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
该解决方案具有分层结构(基于域驱动设计), 其中:
在**Visual Studio**中打开解决方案:
* ``.Domain`` 为领域层.
* ``.Application`` 为应用层.
* ``.Web`` 为是表示层.
* ``.EntityFrameworkCore`` 是EF Core集成.
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v3.png)
EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项目中.
该解决方案具有分层结构(基于[Domain Driven Design](Domain-Driven-Design.md)), 并包含配置好的的单元&集成测试项目,可与**EF Core**和**SQLite**数据库内存一起使用.
解决方案还包含配置好的的单元&集成测试项目, 以便与 **EF Core****SQLite内存中** 数据库配合使用.
> 请参阅[MVC应用程序模板文档](Startup-Templates/Mvc.md)以详细了解解决方案结构.
### 创建数据库
### 数据库连接字符串
查看`.Web`项目下`appsettings.json`文件中的 **连接字符串**:
@ -44,9 +49,29 @@ EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项
}
````
解决方案使用 **Entity Framework Core****MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/en-us/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS.
解决方案使用 **Entity Framework Core****MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/en-us/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS. 如果需要,请更改连接字符串.
### 创建数据库并应用数据库迁移
你有两个选项来创建数据库.
右键单击`.Web`项目并**设置启动项目**
#### 使用DbMigrator应用程序
该解决方案包含一个控制台应用程序(在此示例中名为`Acme.BookStore.DbMigrator`),可以创建数据库,应用迁移和初始化数据. 它对开发和生产环境都很有用.
> `.DbMigrator`项目有自己的`appsettings.json`. 因此,如果你更改了上面的连接字符串,则还应更改此字符串.
右键单击`.DbMigrator`项目并选择 **设置为启动项目**:
![set-as-startup-project](images/set-as-startup-project.png)
按F5(或Ctrl + F5)运行应用程序. 它将具有如下所示的输出:
![set-as-startup-project](images/db-migrator-app.png)
#### 使用EF Core Update-Database命令
Ef Core具有`Update-Database`命令, 可根据需要创建数据库并应用挂起的迁移. 右键单击`.Web`项目并选择**设置为启动项目**:
![set-as-startup-project](images/set-as-startup-project.png)
@ -56,6 +81,8 @@ EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项
这将基于配置的连接字符串创建新数据库.
> 使用`.Migrator`工具是建议的方法, 因为它还能初始化初始数据能够正确运行Web应用程序.
### 运行应用程序
你现在可以运行应用程序,它将会打开**home**页面:
@ -64,9 +91,9 @@ EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项
单击 **登录** 按钮, 输入用户名`admin`, 密码`1q2w3E*`, 登录应用程序.
启动模板包括 **身份管理(identity management)** 模块. 登录后将提供身份管理菜单,你可以在其中管理**角色**,**用户**及其**权限**.
启动模板包括**身份管理**和**租户管理**模块. 登录后,将显示"管理"菜单, 你可以在其中管理**租户**,**角色**,**用户**和**权限**. 用户管理页面如下所示:
![bookstore-user-management](images/bookstore-user-management.png)
![bookstore-user-management](images/bookstore-user-management-v2.png)
### 下一步是什么?

@ -1,68 +1,32 @@
# ABP 文档
> 翻译来自[cnAbp](https://github.com/cnabp)组织,中文网会持续跟进翻译,目前Abp vNext的英文文档还未完成,大家对整体框架没有深入的理解,翻译难免存在一些问题.敬请见谅.😀
> 中文文档翻译来自[cnAbp](https://github.com/cnabp)组织,Abp中文网会持续跟进翻译,目前Abp vNext的英文文档还未完成,大家对整体框架没有深入的理解,翻译难免存在一些问题.敬请见谅.😀
## 目录
ABP是一个**开源应用程序框架**,专注于基于ASP.NET Core的Web应用程序开发,但也支持开发其他类型的应用程序.
* 入门
* 从启动模板开始
* [ASP.NET Core MVC 模板](Getting-Started-AspNetCore-MVC-Template.md)
* 从空项目开始
* [使用Console Application](Getting-Started-Console-Application.md)
* [使用 ASP.NET Core Web Application](Getting-Started-AspNetCore-Application.md)
* 教程
* 应用开发
* [使用 ASP.NET Core MVC](Tutorials/AspNetCore-Mvc/Part-I.md)
* 基础知识
* [依赖注入](Dependency-Injection.md)
* AutoFac 集成
* [虚拟文件系统](Virtual-File-System.md)
* [本地化](Localization.md)
* [异常处理](Exception-Handling.md)
* 验证
* 授权
* 缓存
* 审计
* 设置管理
* 对象映射
* AutoMapper 集成
* 事件
* 本地 Event Bus
* 分布式 Event Bus
* RabbitMQ 集成
* 服务
* 对象序列化
* JSON序列化
* 邮件
* GUIDs
* 线程
* 定时
* [多租户](Multi-Tenancy.md)
* 模块开发
* [基础](Module-Development-Basics.md)
* 模块插件
* [最佳实践](Best-Practices/Index.md)
* 领域驱动设计
* 领域层
* [实体&聚合根](Entities.md)
* 值对象
* [仓储](Repositories.md)
* 领域服务
* 规约
* 应用服务层
* 应用服务
* 数据传输对象(DTO)
* 工作单元
* ASP.NET Core MVC
* API 版本控制
* 用户界面
* [客户端包管理](AspNetCore/Client-Side-Package-Management.md)
* [捆绑&压缩](AspNetCore/Bundling-Minification.md)
* [Tag Helpers](Tag-Helpers.md)
* [主题](AspNetCore/Theming.md)
* 后台服务
* [后台作业](Background-Jobs.md)
* 数据访问
* [Entity Framework Core 集成](Entity-Framework-Core.md)
* [MongoDB 集成](MongoDB.md)
* 测试
浏览左侧导航菜单以深入了解文档.
## 项目状态
ABP是开源[ASP.NET Boilerplate](https://aspnetboilerplate.com/)框架的**下一代框架**, 它目前处于早期预览阶段,尚未准备好在生产中使用. 文档仍在进行中,远未完成.
对于短期和生产级应用程序, 建议使用[ASP.NET Boilerplate](https://aspnetboilerplate.com/)框架,该框架具有丰富的功能集,成熟,积极维护和最新.
## 入门
使用ABP开发新项目的最简单方法是使用启动模板:
* [ASP.NET Core MVC 模板](Getting-Started-AspNetCore-MVC-Template.md)
如果您想从头开始(使用空项目),请手动安装ABP框架并使用以下教程:
* [控制台应用程序](Getting-Started-Console-Application.md)
* [ASP.NET Core Web 应用程序](Getting-Started-AspNetCore-Application.md)
## 源码
ABP托管在GitHub上, 参见[源代码](https://github.com/abpframework/abp).
## 贡献代码
ABP是一个社区驱动的开源项目.如果你想成为该项目的一部分,请参阅[贡献指南](Contribution/Index.md).

@ -0,0 +1,8 @@
# 启动模板
虽然你可以从一个空项目开始并手动添加所需的包,但启动模板可以非常轻松,舒适地使用ABP框架启动新的解决方案.
单击下面列表中的名称以查看相关启动模板的文档:
* [**mvc**](Mvc.md): ASP.NET Core MVC应用程序模板.
* [**mvc-module**](Mvc-Module.md): ASP.NET Core MVC模块/服务模板.

@ -0,0 +1,6 @@
# MVC Module 启动模板
TODO

@ -0,0 +1,183 @@
# MVC应用程序启动模板
## 介绍
MVC应用程序启动模板是基于[领域驱动设计](../Domain-Driven-Design.md)(DDD)分层(或根据偏好分层)的应用程序结构.
## 如何开始
你要以使用[ABP CLI](../CLI.md)创建基于此启动模板的新项目,或者你也可以在[入门](https://abp.io/get-started)页面创建并下载项目. 在这里我们使用CLI创建新项目.
首先根据[文档](../CLI.md)中的说明安装ABP CLI. 然后使用 `abp new` 命令在空文件夹中创建新解决方案:
````bash
abp new Acme.BookStore -t mvc
````
* `Acme.BookStore` 是解决方案的名称, 命名样式如 *YourCompany.YourProduct*. 更多的命名样式请参阅[CLI文档](../CLI.md).
* 示例中指定了启动模板 (`-t` 或 `--template` 选项). 不过 `mvc` 是默认模板,即使未指定也会创建 `MVC` 的模板项目.
### 指定数据库提供程序
`MVC`模板支持以下数据库提供程序:
- `ef`: Entity Framework Core (默认)
- `mongodb`: MongoDB
使用 `-d` (或 `--database-provider`) 指定数据库提供程序:
````bash
abp new Acme.BookStore -t mvc -d mongodb
````
### 创建分层解决方案
使用 `--tiered` 选项创建分层解决方案, Web与WebApi层在物理上是分开的. 如果未指定,CLI会创建一个分层的解决方案,这个解决方案没有那么复杂,适合大多数场景.
````bash
abp new Acme.BookStore --tiered
````
有关分层的方法,请参阅下面的"分层结构"部分.
## 解决方案结构
根据命令的选项,会创建略有不同的解决方案结构.
### 默认结构
如果未指定选项,你会得到如下所示的解决方案:
![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-v3.png)
项目组织在`src`和`test`文件夹中. `src`文件夹包含实际应用程序,该应用程序基于前面提到的[DDD](../Domain-Driven-Design.md)原则进行分层.
--------------------
**TODO: 添加一些图来说明项目之间的依赖关系.**
------------------
下面介绍解决方案中的项目.
#### .Domain 项目
解决方案的领域层. 它主要包含 [实体, 集合根](../Entities.md), [领域服务](../Domain-Services.md), [值类型](../Value-Types.md), [仓储接口](../Repositories.md) 和解决方案的其他领域对象.
例如 `Book` 实体和 `IBookRepository` 接口都适合放在这个项目中.
* 它依赖 `.Domain.Shared` 项目,因为项目中会用到它的一些常量,枚举和定义其他对象.
#### .Domain.Shared 项目
项目包含常量,枚举和其他对象, 这些对象实际上是领域层的一部分,但是解决方案中所有的层/项目中都会使用到.
例如 `BookType` 枚举和 `BookConts` 类 (可能是 `Book` 实体用到的常数字段,像`MaxNameLength`)都适合放在这个项目中.
该项目不会依赖解决方案中的其他项目.
#### .Application.Contracts 项目
项目主要包含 [应用服务](../Application-Services.md) **interfaces** 和应用层的 [数据传输对象](../Data-Transfer-Objects.md) (DTO). 它用于分离应用层的接口和实现. 这种方式可以将接口项目做为约定包共享给客户端.
* 它依赖 `.Domain.Shared` 因为它可能会在应用接口和DTO中使用常量,枚举和其它的共享对象.
#### .Application 项目
项目包含 `.Application.Contracts` 项目的 [应用服务](../Application-Services.md) 接口实现.
* 它依赖 `.Application.Contracts` 项目, 因为它需要实现接口与使用DTO.
* 它依赖 `.Domain` 项目,因为它需要使用领域对象(实体,仓储接口等)执行应用程序逻辑.
#### .EntityFrameworkCore 项目
这是集成EF Core的项目. 它定义了 `DbContext` 并实现 `.Domain` 项目中定义的仓储接口.
* 它依赖 `.Domain` 项目,因为它需要引用实体和仓储接口.
> 只有在你使用了EF Core做为数据库提供程序时,此项目才会可用.
#### .EntityFrameworkCore.DbMigrations 项目
包含解决方案的EF Core数据库迁移. 它有独立的 `DbContext` 来专门管理迁移.
ABP是一个模块化的框架,理想的设计是让每个模块都有自己的 `DbContext` 类. 这时用于迁移的 `DbContext` 就会发挥作用. 它将所有的 `DbContext` 配置统一到单个模型中以维护单个数据库的模式.
需要注意,迁移 `DbContext` 仅用于数据库迁移,而不在*运行时*使用.
* 它依赖 `.EntityFrameworkCore` 项目,因为它重用了应用程序的 `DbContext` 配置 .
> 只有在你使用了EF Core做为数据库提供程序时,此项目才会可用.
#### .DbMigrator 项目
这是一个控制台应用唾弃,它简化了在开发和生产环境执行数据库迁移的操作.当你使用它时;
* 必要时创建数据库.
* 应用数据库迁移.
* 初始化种子数据.
> 这个项目有自己的 `appsettings.json` 文件. 所以如果要更改数据库连接字符串,请记得也要更改此文件.
初始化种子数据很很要,ABP具有模块化的种子数据基础设施. 种子数据的更多信息,请参阅[文档](../Data-Seeding.md).
虽然创建数据库和应用迁移似乎只对关系数据库有用,但即使您选择NoSQL数据库提供程序(如MongoDB),也会生成此项目. 这时,它会为应用程序提供必要的初始数据.
* 它依赖 `.EntityFrameworkCore.DbMigrations` 项目 (针对EF Core),因为它需要访问迁移文件.
* 它依赖 `.Application.Contracts` 项目,因为它需要访问权限定义在初始化种子数据时为管理员用户赋予权限.
#### .HttpApi 项目
用于定义API控制器.
大多数情况下,你不需要手动定义API控制器,因为ABP的[动态API](../AspNetCore/Auto-API-Controllers.md)功能会根据你的应用层自动创建API控制器. 但是,如果你需要编写API控制器,那么它是最合适的地方.
* 它依赖 `.Application.Contracts` 项目,因为它需要注入应用服务接口.
#### .HttpApi.Client 项目
定义C#客户端代理使用解决方案的HttpAPI项目. 可以将上编辑共享给第三方客户端,让它们轻松的在DotNet应用程序中使用你的httiApi.
`.HttpApi.Client.ConsoleTestApp` 项目是一个用于演示客户端代理用法的控制台应用程序.
ABP有[动态 C# API 客户端](../AspNetCore/Dynamic-CSharp-API-Clients.md)功能,所以大多数情况下你不需要手动的创建C#客户端代理.
* 它依赖 `.Application.Contracts` 项目,因为它需要使用应用服务接口和DTO.
#### .Web 项目
包含应用程序的用户界面(UI). 包括Razor页面,javascript文件,css文件,图片等...
* 依赖 `.HttpApi` 项目,因为UI层需要使用解决方案的API和应用服务接口.
> 如果查看 `.Web.csproj` 源码, 你会看到对 `.Application``.EntityFrameworkCore.DbMigrations` 项目的引用.
>
> 这些引用实际上在开发中并不需要. 因为UI层通常不依赖于EF Core或应用程序实现. 这个启动模板已经为分层部署做好了准备,API层托管在不同与UI层的服务器中.
>
> 但是如果你不选择 `--tiered` 选项, .Web项目会有这些引用,以便能够将Web,Api和应用层托管在单个应用程序站点.
>
> 你可以在表示层中使用领域实体,但是根据DDD的理论,这被认为是一种不好的做法.
#### 测试项目
解决方案有多个测试项目,每一层都会有一个:
* `.Domain.Tests` 用于测试领域层.
* `.Application.Tests` 用于测试应用层.
* `.EntityFrameworkCore.Tests` 用于测试EF Core配置与自定义仓储.
* `.Web.Tests` 用于测试UI.
* `.TestBase` 所有测试项目的基础(共享)项目.
此外, `.HttpApi.Client.ConsoleTestApp` 是一个控制台应用程序(不是自动化测试项目),它用于演示DotNet应用程序中Http Api的用法.
### 分层结构
TODO
### 其它数据库提供程序
TODO
#### MongoDB
TODO

@ -2,7 +2,7 @@
### 关于本教程
本教程中,你会创建一个用于管理书籍和书籍作者的程序.会用到 **Entity Framework Core** (EF Core)作为ORM([启动模板](https://abp.io/Templates)中预配置的ORM).
在本系列教程中, 你将构建一个用于管理书籍及其作者列表的应用程序. **Entity Framework Core**(EF Core)将用作ORM提供者,因为它是默认数据库提供者.
这是本教程所有章节中的第一章,下面是所有的章节:
@ -10,35 +10,37 @@
- [Part II: 创建,编辑,删除书籍](Part-II.md)
- [Part III: 集成测试](Part-III.md)
你可以从[这里](https://github.com/volosoft/abp/tree/master/samples/BookStore)下载本程序的源码.
你可以从[GitHub存储库](https://github.com/volosoft/abp/tree/master/samples/BookStore)访问应用程序的**源代码**.
### 创建项目
打开[启动模板页](https://abp.io/Templates)并下载一个新的项目叫做`Acme.BookStore`.根据[模板文档](../../Getting-Started-AspNetCore-MVC-Template.md)创建数据库并运行这个程序.
创建一个名为`Acme.BookStore`的新项目, 创建数据库并按照[入门文档](../../Getting-Started-AspNetCore-MVC-Template.md)运行应用程序.
### 解决方案的结构
下面的图片展示了从启动模板创建的项目是如何分层的.
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v3.png)
> 你可以查看[MVC应用程序模板文档](../../Startup-Templates/Mvc.md)以详细了解解决方案结构.但是,你将通过本教程了解基础知识.
### 创建Book实体
**领域层** 定义[实体](../../Entities.md)(`Acme.BookStore.Domain` 项目中).这个项目最主要的实体就是`Book`:
启动模板中的域层分为两个项目:
- `Acme.BookStore.Domain`包含你的[实体](../../Entities.md), [领域服务](../../Domain-Services.md)和其他核心域对象.
- `Acme.BookStore.Domain.Shared`包含可与客户共享的常量,枚举或其他域相关对象.
在解决方案的**领域层**(`Acme.BookStore.Domain`项目)中定义[实体](../../Entities.md). 该应用程序的主要实体是`Book`. 在`Acme.BookStore.Domain`项目中创建一个名为`Book`的类,如下所示:
````C#
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Volo.Abp.Domain.Entities.Auditing;
namespace Acme.BookStore
{
[Table("Books")]
public class Book : AuditedAggregateRoot<Guid>
{
[Required]
[StringLength(128)]
public string Name { get; set; }
public BookType Type { get; set; }
@ -50,8 +52,8 @@ namespace Acme.BookStore
}
````
* ABP有两个基本的实体基类: `AggregateRoot``Entity`.**Aggregate Root**是 **领域驱动设计(DDD)** 的概念之一.更多信息和最佳实践请查看[实体文档](../../Entities.md).
* `Book`实体继承了`AuditedAggregateRoot`,`AuditedAggregateRoot`类在`AggregateRoot`类的基础上添加了一些审计属性(`CreationTime`, `CreatorId`, `LastModificationTime`....).
* ABP为实体提供了两个基本的基类: `AggregateRoot`和`Entity`. **Aggregate Root**是**域驱动设计(DDD)** 概念之一. 有关详细信息和最佳做法,请参阅[实体文档](../../Entities.md).
* `Book`实体继承了`AuditedAggregateRoot`,`AuditedAggregateRoot`类在`AggregateRoot`类的基础上添加了一些审计属性(`CreationTime`, `CreatorId`, `LastModificationTime` 等).
* `Guid`是`Book`实体的主键类型.
* 使用 **数据注解** 为EF Core添加映射.或者你也可以使用 EF Core 自带的[fluent mapping API](https://docs.microsoft.com/en-us/ef/core/modeling).
@ -62,10 +64,10 @@ namespace Acme.BookStore
````C#
namespace Acme.BookStore
{
public enum BookType : byte
public enum BookType
{
Undefined,
Advanture,
Adventure,
Biography,
Dystopia,
Fantastic,
@ -91,14 +93,15 @@ public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
#### 配置你的Book实体
从`Acme.BookStore.EntityFrameworkCore` 项目中打开 BookStoreDbContextModelCreatingExtensions.cs 文件, 在 ConfigureBookStore 方法最后添加如下代码来配置Book实体:
在`Acme.BookStore.EntityFrameworkCore`项目中打开`BookStoreDbContextModelCreatingExtensions.cs`文件,并将以下代码添加到`ConfigureBookStore`方法的末尾以配置Book实体:
````C#
builder.Entity<Book>(b =>
{
b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema);
b.ConfigureExtraProperties();
});
builder.Entity<Book>(b =>
{
b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema);
b.ConfigureAuditedAggregateRoot(); //auto configure for the base class props
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
});
````
#### 添加新的Migration并更新数据库
@ -115,26 +118,27 @@ PM> Update-Database
#### 添加示例数据
`Update-Database`命令会在数据库中创建`Books`表.打开这个表添加几行数据,然后就可以把这些数据展示到页面上:
`Update-Database`命令在数据库中创建了`AppBooks`表. 打开数据库并输入几个示例行,以便在页面上显示它们:
![bookstore-books-table](images/bookstore-books-table.png)
### 创建应用服务
下一步是创建[应用服务](../../Application-Services.md)来管理(创建,列出,更新,删除...)书籍.
下一步是创建[应用服务](../../Application-Services.md)来管理(创建,列出,更新,删除)书籍. 启动模板中的应用程序层分为两个项目:
* `Acme.BookStore.Application.Contracts`主要包含你的DTO和应用程序服务接口.
* `Acme.BookStore.Application`包含应用程序服务的实现.
#### BookDto
在`Acme.BookStore.Application`项目中添加一个名为`BookDto`的DTO类:
在`Acme.BookStore.Application.Contracts`项目中创建一个名为`BookDto`的DTO类:
````C#
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AutoMapper;
namespace Acme.BookStore
{
[AutoMapFrom(typeof(Book))]
public class BookDto : AuditedEntityDto<Guid>
{
public string Name { get; set; }
@ -151,7 +155,23 @@ namespace Acme.BookStore
* **DTO**类被用来在 **表示层** 和 **应用层** **传递数据**.查看[DTO文档](../../Data-Transfer-Objects.md)查看更多信息.
* 为了在页面上展示书籍信息,`BookDto`被用来将书籍数据传递到表示层.
* `BookDto`继承自 `AuditedEntityDto<Guid>`.跟上面定义的`Book`类一样具有一些审计属性.
* `[AutoMapFrom(typeof(Book))]`用来创建从`Book`类到`BookDto`的AutoMapper映射.使用这种方法.你可以将`Book`对象自动转换成`BookDto`对象(而不是手动复制所有的属性).
在将书籍返回到表示层时,需要将`Book`实体转换为`BookDto`对象. [AutoMapper](https://automapper.org)库可以在定义了正确的映射时自动执行此转换. 启动模板配置了AutoMapper,因此你只需在`Acme.BookStore.Application`项目的`BookStoreApplicationAutoMapperProfile`类中定义映射:
````csharp
using AutoMapper;
namespace Acme.BookStore
{
public class BookStoreApplicationAutoMapperProfile : Profile
{
public BookStoreApplicationAutoMapperProfile()
{
CreateMap<Book, BookDto>();
}
}
}
````
#### CreateUpdateBookDto
@ -184,11 +204,17 @@ namespace Acme.BookStore
````
* 这个DTO类被用于在创建或更新书籍的时候从用户界面获取图书信息.
* 类中的属性定义了数据注解(如`[Required]`)用来定义有效性验证.ABP会自动校验DTO的数据有效性.
* 它定义了数据注释属性(如`[Required]`)来定义属性的验证. DTO由ABP框架[自动验证](../../Validation.md).
就像上面的`BookDto`一样,创建一个从`CreateUpdateBookDto`对象到`Book`实体的映射:
````csharp
CreateMap<CreateUpdateBookDto, Book>();
````
#### IBookAppService
为应用服务定义一个名为 `IBookAppService` 的接口:
在`Acme.BookStore.Application.Contracts`项目中定义一个名为`IBookAppService`的接口:
````C#
using System;
@ -210,15 +236,14 @@ namespace Acme.BookStore
}
````
* 为应用服务定义接口不是必须的,不过,这是推荐的最佳实践.
* `IAsyncCrudAppService`中定义了基础的 **CRUD**方法:`GetAsync`, `GetListAsync`, `CreateAsync`, `UpdateAsync``DeleteAsync`.不需要扩展它.取而代之,你可以继承空的`IApplicationService`接口定义你自己的方法.
* `IAsyncCrudAppService`有一些变体,你可以为每一个方法使用单个或者多个的DTO.(译者注:意思是类似EntityDto和UpdateEntityDto可以用同一个,也可以分别单独指定
)
* 框架定义应用程序服务的接口<u>不是必需的</u>. 但是,它被建议作为最佳实践.
* `IAsyncCrudAppService`定义了常见的**CRUD**方法:`GetAsync`,`GetListAsync`,`CreateAsync`,`UpdateAsync`和`DeleteAsync`. 你可以从空的`IApplicationService`接口继承并手动定义自己的方法.
* `IAsyncCrudAppService`有一些变体, 你可以在每个方法中使用单独的DTO,也可以分别单独指定.
#### BookAppService
创建 `BookAppService` 并实现 `IBookAppService`接口:
在`Acme.BookStore.Application`项目中实现名为`BookAppService`的`IBookAppService`:
````C#
using System;
@ -243,23 +268,23 @@ namespace Acme.BookStore
````
* `BookAppService`继承了`AsyncCrudAppService<...>`.`AsyncCrudAppService<...>`实现了上面定义的CRUD方法.
* `BookAppService`注入了`IRepository<Book, Guid>`,`IRepository<Book, Guid>`是默认为`Book`创建的仓储.ABP会自动为每一个聚合根(或实体)创建仓储.参考[仓储文档](../../Repositories.md).
* `BookAppService`使用了 `IObjectMapper` 将`Book`转换成`BookDto`,将`CreateUpdateBookDto`转换成`Book`.启动模板中使用了[AutoMapper](http://automapper.org/)作为对象映射提供程序.你可以像上面那样使用`AutoMapFrom` 和 `AutoMapTo`定义映射.查看[AutoMapper集成文档](../../AutoMapper-Integration.md)获取更多信息.
* `BookAppService`注入`IRepository <Book,Guid>`,这是`Book`实体的默认仓储. ABP自动为每个聚合根(或实体)创建默认仓储. 请参阅[仓储文档](../../Repositories.md)
* `BookAppService`使用`IObjectMapper`将`Book`对象转换为`BookDto`对象, 将`CreateUpdateBookDto`对象转换为`Book`对象. 启动模板使用[AutoMapper](http://automapper.org/)库作为对象映射提供程序. 你之前定义了映射, 因此它将按预期工作.
### 自动生成API Controllers
你通常需要创建 **Controllers** 将应用服务暴露为 **HTTP API**.这样浏览器或第三方客户端可以通过AJAX的方式访问它们.
ABP可以通过约定[**自动**](../../AspNetCore/Auto-API-Controllers.md)将应用服务转换成MVC API Controllers.
你通常创建**Controller**以将应用程序服务公开为**HTTP API**端点. 因此允许浏览器或第三方客户端通过AJAX调用它们. ABP可以[**自动**](../../AspNetCore/Auto-API-Controllers.md)按照惯例将你的应用程序服务配置为MVC API控制器.
#### Swagger UI
启动模板使用[Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)库配置了[swagger UI](https://swagger.io/tools/swagger-ui/).运行程序并在浏览器中输入`http://localhost:53929/swagger/`.
启动模板配置为使用[Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)运行[swagger UI](https://swagger.io/tools/swagger-ui/). 运行应用程序并在浏览器中输入`https://localhost:XXXX/swagger/`(用您自己的端口替换XXXX)作为URL.
你会看到一些内置的接口和`Book`的接口,它们都是REST风格的:
![bookstore-swagger](images/bookstore-swagger.png)
Swagger有一个很好的UI来测试API. 你可以尝试执行`[GET] /api/app/book` API来获取书籍列表.
### 动态JavaScript代理
在Javascript端通过AJAX的方式调用HTTP API接口是很常见的,你可以使用`$.ajax`或这其他的工具来调用接口.当然,ABP中提供了更好的方式.
@ -270,6 +295,8 @@ ABP **自动** 为所有的API接口创建了JavaScript **代理**.因此,你可
你可以使用你钟爱的浏览器的 **开发者控制台** 中轻松测试JavaScript代理.运行程序,并打开浏览器的 **开发者工具**(快捷键:F12),切换到 **Console** 标签,输入下面的代码并回车:
你现在可以使用自己喜欢的浏览器的**开发者控制台**轻松测试JavaScript代理. 运行应用程序, 打开浏览器的**开发者工具**(快捷键:F12),切换到**Console**选项卡,输入以下代码并按回车键.
````js
acme.bookStore.book.getList({}).done(function (result) { console.log(result); });
````
@ -277,7 +304,7 @@ acme.bookStore.book.getList({}).done(function (result) { console.log(result); })
* `acme.bookStore`是`BookAppService`的命名空间,转换成了[驼峰命名](https://en.wikipedia.org/wiki/Camel_case).
* `book`是`BookAppService`转换后的名字(去除了AppService后缀并转成了驼峰命名).
* `getList`是定义在`AsyncCrudAppService`基类中的`GetListAsync`方法转换后的名字(去除了Async后缀并转成了驼峰命名).
* `{}`参数用来传递一个空的对象给`GetListAsync`方法.GetListAsync期望的参数是`PagedAndSortedResultRequestDto`类型的对象,`PagedAndSortedResultRequestDto`类型中定义了分页和排序选项.
* `{}`参数用于将空对象发送到`GetListAsync`方法,该方法通常需要一个类型为`PagedAndSortedResultRequestDto`的对象,用于向服务器发送分页和排序选项(所有属性都是可选的,所以你可以发送一个空对象).
* `getList`方法返回了一个`promise`.因此,你可以传递一个回调函数到`done`(或者`then`)方法中来获取服务返回的结果.
运行这段代码会产生下面的输出:
@ -300,7 +327,7 @@ acme.bookStore.book.create({ name: 'Foundation', type: 7, publishDate: '1951-05-
successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7
````
检查数据库表`books`中的数据,你会发现多了一行新数据,你也可以尝试`get`, `update``delete`方法.
检查数据库中的`Books`表以查看新书. 你可以自己尝试`get`,`update`和`delete`功能.
### 创建书籍页面
@ -309,20 +336,21 @@ successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7
`Acme.BookStore.Web`项目的`Pages`文件夹下创建一个新的文件夹叫`Books`并添加一个名为`Index.cshtml`的Razor Page.
![bookstore-add-index-page](images/bookstore-add-index-page.png)
![bookstore-add-index-page](images/bookstore-add-index-page-v2.png)
打开`Index.cshtml`并把内容修改成下面这样:
````html
@page
@using Acme.BookStore.Pages.Books
@inherits Acme.BookStore.Pages.BookStorePageBase
@using Acme.BookStore.Web.Pages.Books
@inherits Acme.BookStore.Web.Pages.BookStorePageBase
@model IndexModel
<h2>Books</h2>
````
* 修改Razor View Page Model的默认继承,使页面 **继承** 自`BookStorePageBase`类(代替`PageModel`).`BookStorePageBase`类来自于启动模板,它提供了一些公开的可以被所有的页面使用的属性/方法.
* 此代码更改了Razor View Page Model的默认继承,因此它从`BookStorePageBase`类(而不是`PageModel`)继承.启动模板附带的`BookStorePageBase`类,提供所有页面使用的一些共享属性/方法.
* 确保`IndexModel`(Index.cshtml.cs)具有`Acme.BookStore.Pages.Books`命名空间,或者在`Index.cshtml`中更新它.
#### 将Books页面添加到主菜单
@ -337,17 +365,16 @@ context.Menu.AddItem(
#### 本地化菜单
本地化的文本在`Acme.BookStore.Domain`项目的`Localization/BookStore`文件夹中.
本地化文本位于`Acme.BookStore.Domain.Shared`项目的`Localization/BookStore`文件夹下:
![bookstore-localization-files](images/bookstore-localization-files.png)
![bookstore-localization-files](images/bookstore-localization-files-v2.png)
打开`en.json`文件,为`Menu:BookStore` 和 `Menu:Books`添加本地化文本:
打开`en.json`文件,将`MenuBookStore`和`MenuBooks`键的本地化文本添加到文件末尾:
````json
{
"culture": "en",
"texts": {
//...
"Menu:BookStore": "Book Store",
"Menu:Books": "Books"
}
@ -355,9 +382,9 @@ context.Menu.AddItem(
````
* ABP的本地化功能建立在[ASP.NET Core's standard localization]((https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization))之上并增加了一些扩展.查看[本地化文档](../../Localization.md).
* 本地化中key的名字是随便定义的,你可以随意命名.我们喜欢为菜单添加`Menu`命名空间,以区别于其他的文本.如果文本没有在本地化文件中定义,就会 **返回** 本地的化的key(ASP.NET Core的标准做法).
* 本地化key是任意的. 你可以设置任何名称. 我们更喜欢为菜单项添加`Menu:`前缀以区别于其他文本. 如果未在本地化文件中定义文本,则它将**返回**到本地化的key(ASP.NET Core的标准行为).
运行程序就会看到菜单已经添加到了顶部:
运行该应用程序,看到新菜单项已添加到顶部栏:
![bookstore-menu-items](images/bookstore-menu-items.png)
@ -365,17 +392,16 @@ context.Menu.AddItem(
#### 书籍列表
我们会在页面上使用JQuery插件[Datatables.net](https://datatables.net/)来展示列表.Datatables可以完全通过AJAX工作,所以它很快而且有良好的用户体验.启动模板中已经配置好了Datatables插件,因此你可以在你的页面中直接使用,不需要引用样式和脚本文件.
我们将使用[Datatables.net](https://datatables.net/)JQuery插件来显示页面上的表格列表. 数据表可以完全通过AJAX工作,速度快,并提供良好的用户体验. Datatables插件在启动模板中配置,因此你可以直接在任何页面中使用它,而需要在页面中引用样式和脚本文件.
##### 修改Index.cshtml
##### Index.cshtml
将`Pages/Books/Index.cshtml`改成下面的样子:
````html
@page
@using Acme.BookStore.Pages.Books
@inherits Acme.BookStore.Pages.BookStorePageBase
@model IndexModel
@inherits Acme.BookStore.Web.Pages.BookStorePageBase
@model Acme.BookStore.Web.Pages.Books.IndexModel
@section scripts
{
<abp-script src="/Pages/Books/index.js" />
@ -408,7 +434,7 @@ context.Menu.AddItem(
在`Pages/Books/`文件夹中创建 `index.js`文件
![bookstore-index-js-file](images/bookstore-index-js-file.png)
![bookstore-index-js-file](images/bookstore-index-js-file-v2.png)
`index.js`的内容如下:
@ -430,7 +456,7 @@ $(function () {
* `abp.libs.datatables.createAjax`是帮助ABP的动态JavaScript API代理跟Datatable的格式相适应的辅助方法.
* `abp.libs.datatables.normalizeConfiguration`是另一个辅助方法.不是必须的, 但是它通过为缺少的选项提供常规值来简化数据表配置.
* `acme.bookStore.book.getList`是获取书籍列表的方法(上面已经介绍过了)
* 查看 [Datatable's 文档](https://datatables.net/manual/) 了解更多配置项.
* 查看 [Datatable文档](https://datatables.net/manual/) 了解更多配置项.
最终的页面如下:

@ -2,13 +2,13 @@
### 关于本教程
这是本教程所有章节中的第二章.下面是所有的章节:
这是ASP.NET Core MVC教程系列的第二章. 查看其它章节
* [Part I: 创建项目和书籍列表页面](Part-I.md)
* **Part II: 创建,编辑,删除书籍(本章)**
* [Part III: 集成测试](Part-III.md)
你可以从 [这里](https://github.com/volosoft/abp/tree/master/samples/BookStore) 下载本程序的**源码**.
你可以从[GitHub存储库](https://github.com/volosoft/abp/tree/master/samples/BookStore)访问应用程序的**源代码**.
### 新增 Book 实体
@ -20,7 +20,7 @@
`Acme.BookStore.Web` 项目的 `Pages/Books` 目录下新建一个 `CreateModal.cshtml` Razor页面:
![bookstore-add-create-dialog](images/bookstore-add-create-dialog.png)
![bookstore-add-create-dialog](images/bookstore-add-create-dialog-v2.png)
##### CreateModal.cshtml.cs
@ -30,7 +30,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Acme.BookStore.Pages.Books
namespace Acme.BookStore.Web.Pages.Books
{
public class CreateModalModel : BookStorePageModelBase
{
@ -63,9 +63,9 @@ namespace Acme.BookStore.Pages.Books
````html
@page
@inherits Acme.BookStore.Pages.BookStorePageBase
@inherits Acme.BookStore.Web.Pages.BookStorePageBase
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@model Acme.BookStore.Pages.Books.CreateModalModel
@model Acme.BookStore.Web.Pages.Books.CreateModalModel
@{
Layout = null;
}
@ -138,12 +138,12 @@ $('#NewBookButton').click(function (e) {
展开 `EditModal.cshtml`,打开 `EditModal.cshtml.cs` 文件( `EditModalModel` 类) 并替换成以下代码:
````C#
````csharp
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Acme.BookStore.Pages.Books
namespace Acme.BookStore.Web.Pages.Books
{
public class EditModalModel : BookStorePageModelBase
{
@ -180,38 +180,26 @@ namespace Acme.BookStore.Pages.Books
* 在 `OnGetAsync` 方法中,将 `BookAppService.GetAsync` 方法返回的 `BookDto` 映射成 `CreateUpdateBookDto` 并赋值给Book属性.
* `OnPostAsync` 方法直接使用 `BookAppService.UpdateAsync` 来更新实体.
#### CreateUpdateBookDto
#### BookDto到CreateUpdateBookDto对象映射
为了执行`BookDto``CreateUpdateBookDto` 的对象映射, 按如下所示修改 `CreateUpdateBookDto`:
为了执行`BookDto`到`CreateUpdateBookDto`对象映射,请打开`Acme.BookStore.Web`项目中的`BookStoreWebAutoMapperProfile.cs`并更改它,如下所示:
````C#
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.AutoMapper;
````csharp
using AutoMapper;
namespace Acme.BookStore
namespace Acme.BookStore.Web
{
[AutoMapTo(typeof(Book))]
[AutoMapFrom(typeof(BookDto))]
public class CreateUpdateBookDto
public class BookStoreWebAutoMapperProfile : Profile
{
[Required]
[StringLength(128)]
public string Name { get; set; }
[Required]
public BookType Type { get; set; } = BookType.Undefined;
[Required]
public DateTime PublishDate { get; set; }
[Required]
public float Price { get; set; }
public BookStoreWebAutoMapperProfile()
{
CreateMap<BookDto, CreateUpdateBookDto>();
}
}
}
````
* 仅添加 `[AutoMapFrom(typeof(BookDto))]` 特性就可以创建上述映射关系.
* 刚刚添加了`CreateMap<BookDto, CreateUpdateBookDto>();`作为映射定义.
#### EditModal.cshtml
@ -219,8 +207,8 @@ namespace Acme.BookStore
````html
@page
@inherits Acme.BookStore.Pages.BookStorePageBase
@using Acme.BookStore.Pages.Books
@inherits Acme.BookStore.Web.Pages.BookStorePageBase
@using Acme.BookStore.Web.Pages.Books
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@model EditModalModel
@{
@ -231,7 +219,7 @@ namespace Acme.BookStore
<abp-modal-header title="@L["Update"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Id" />
<abp-form-content/>
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
@ -240,8 +228,8 @@ namespace Acme.BookStore
这个页面内容和 `CreateModal.cshtml` 非常相似,除了以下几点:
* 此页面包含了一个 `abp-input` 以保存所编辑book实体的 `Id` 属性值.
* 此页面指定的post地址是 `Books/EditModal` ,并用文本 *Update* 作为 modal 标题.
* 它包含`id`属性的`abp-input`, 用于存储编辑书的id(它是隐藏的Input)
* 此页面指定的post地址是`Books/EditModal`, 并用文本 *Update* 作为 modal 标题.
#### 为表格添加 "操作Actions" 下拉菜单
@ -420,6 +408,12 @@ $(function () {
});
````
打开`Acme.BookStore.Domain.Shared`项目中的`en.json`并添加以下行:
````json
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?"
````
运行程序并尝试删除一个book实体.
### 下一章

@ -2,23 +2,21 @@
### 关于本教程
这是本教程所有章节中的第三章.下面是所有的章节:
这是ASP.NET Core MVC教程系列的第三章. 查看其它章节
- [Part I: 创建项目和书籍列表页面](Part-I.md)
- [Part II: 创建,编辑,删除书籍](Part-II.md)
- **Part III: 集成测试(本章)**
你可以从 [这里](https://github.com/volosoft/abp/tree/master/samples/BookStore) 下载本程序的**源码**.
你可以从[GitHub存储库](https://github.com/volosoft/abp/tree/master/samples/BookStore)访问应用程序的**源代码**.
### 解决方案中的测试项目
本解决方案中有两个测试项目:
解决方案中有多个测试项目:
![bookstore-test-projects-v2](images/bookstore-test-projects-v2.png)
* `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/) 作为断言库.
@ -26,79 +24,39 @@
### 添加测试用数据
起始模板在 `Acme.BookStore.Application.Tests` 项目中包含了 `BookStoreTestDataBuilder` 类,用于创建一些测试用数据. 相关代码如下所示:
````C#
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.Threading;
namespace Acme.BookStore
{
public class BookStoreTestDataBuilder : ITransientDependency
{
private readonly IIdentityDataSeeder _identityDataSeeder;
public BookStoreTestDataBuilder(IIdentityDataSeeder identityDataSeeder)
{
_identityDataSeeder = identityDataSeeder;
}
public void Build()
{
AsyncHelper.RunSync(BuildInternalAsync);
}
public async Task BuildInternalAsync()
{
await _identityDataSeeder.SeedAsync("1q2w3E*");
}
}
}
````
* 这里直接使用了identity模块实现的 `IIdentityDataSeeder` 接口,创建了一个admin角色和admin用户.你可以在测试代码中使用它们.
* 你可以在 `BuildInternalAsync` 方法中添加你自己的测试数据.
按下方所示修改 `BookStoreTestDataBuilder` 类:
启动模板包含`Acme.BookStore.TestBase`项目中的`BookStoreTestDataSeedContributor`类,它创建一些数据来运行测试.
更改`BookStoreTestDataSeedContributor`类如下所示:
````C#
using System;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Volo.Abp.Threading;
using Volo.Abp.Guids;
namespace Acme.BookStore
{
public class BookStoreTestDataBuilder : ITransientDependency
public class BookStoreTestDataSeedContributor
: IDataSeedContributor, ITransientDependency
{
private readonly IIdentityDataSeeder _identityDataSeeder;
private readonly IRepository<Book, Guid> _bookRepository;
private readonly IGuidGenerator _guidGenerator;
public BookStoreTestDataBuilder(
IIdentityDataSeeder identityDataSeeder,
IRepository<Book, Guid> bookRepository)
public BookStoreTestDataSeedContributor(
IRepository<Book, Guid> bookRepository,
IGuidGenerator guidGenerator)
{
_identityDataSeeder = identityDataSeeder;
_bookRepository = bookRepository;
_guidGenerator = guidGenerator;
}
public void Build()
public async Task SeedAsync(DataSeedContext context)
{
AsyncHelper.RunSync(BuildInternalAsync);
}
public async Task BuildInternalAsync()
{
await _identityDataSeeder.SeedAsync("1q2w3E*");
await _bookRepository.InsertAsync(
new Book
{
Id = Guid.NewGuid(),
Id = _guidGenerator.Create(),
Name = "Test book 1",
Type = BookType.Fantastic,
PublishDate = new DateTime(2015, 05, 24),
@ -109,7 +67,7 @@ namespace Acme.BookStore
await _bookRepository.InsertAsync(
new Book
{
Id = Guid.NewGuid(),
Id = _guidGenerator.Create(),
Name = "Test book 2",
Type = BookType.Science,
PublishDate = new DateTime(2014, 02, 11),
@ -121,7 +79,8 @@ namespace Acme.BookStore
}
````
* 通过构造函数注入 `IRepository<Book, Guid>`,在 `BuildInternalAsync` 方法中用它创建两个book实体.
* 注入`IRepository<Book,Guid>`并在`SeedAsync`中使用它来创建两个书实体作为测试数据.
* 使用`IGuidGenerator`服务创建GUID. 虽然`Guid.NewGuid()`非常适合测试,但`IGuidGenerator`在使用真实数据库时还有其他特别重要的功能(参见[Guid生成文档](../../Guid-Generation.md)了解更多信息).
### 测试 BookAppService
@ -211,6 +170,8 @@ public async Task Should_Not_Create_A_Book_Without_Name()
* 由于 `Name` 是空值, ABP 抛出一个 `AbpValidationException` 异常.
### 测试 Web 页面
打开**测试资源管理器**(测试 -> Windows -> 测试资源管理器)并**执行**所有测试:
![bookstore-appservice-tests](images/bookstore-appservice-tests.png)
TODO
恭喜, 绿色图标表示测试已成功通过!

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

@ -0,0 +1,3 @@
## Value Types
TODO

@ -41,6 +41,10 @@
}
]
},
{
"text": "CLI",
"path": "CLI.md"
},
{
"text": "基础知识",
"items": [

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using JetBrains.Annotations;
@ -47,7 +48,7 @@ namespace Microsoft.AspNetCore.Builder
.UseMiddleware<AbpCorrelationIdMiddleware>();
}
public static IApplicationBuilder UseAbpRequestLocalization(this IApplicationBuilder app)
public static IApplicationBuilder UseAbpRequestLocalization(this IApplicationBuilder app, Action<RequestLocalizationOptions> optionsAction = null)
{
IReadOnlyList<LanguageInfo> languages;
string defaultLanguage;
@ -61,28 +62,27 @@ namespace Microsoft.AspNetCore.Builder
defaultLanguage = settingProvider.GetOrNull(LocalizationSettingNames.DefaultLanguage);
}
if (!languages.Any())
{
return app.UseRequestLocalization();
}
var options = !languages.Any()
? new RequestLocalizationOptions()
: new RequestLocalizationOptions
{
DefaultRequestCulture = DefaultGetRequestCulture(defaultLanguage, languages),
SupportedCultures = languages
.Select(l => l.CultureName)
.Distinct()
.Select(c => new CultureInfo(c))
.ToArray(),
SupportedUICultures = languages
.Select(l => l.UiCultureName)
.Distinct()
.Select(c => new CultureInfo(c))
.ToArray()
};
optionsAction?.Invoke(options);
var options = new RequestLocalizationOptions
{
DefaultRequestCulture = DefaultGetRequestCulture(defaultLanguage, languages),
SupportedCultures = languages
.Select(l => l.CultureName)
.Distinct()
.Select(c => new CultureInfo(c))
.ToArray(),
SupportedUICultures = languages
.Select(l => l.UiCultureName)
.Distinct()
.Select(c => new CultureInfo(c))
.ToArray()
};
return app.UseRequestLocalization(options);
}

@ -3,6 +3,18 @@
"texts": {
"Menu:Home": "Úvod",
"Welcome": "Vítejte",
"LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io."
"LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io.",
"Menu:BookStore": "Knihkupectví",
"Menu:Books": "Knihy",
"Name": "Název",
"Type": "Typ",
"PublishDate": "Publikováno",
"Price": "Cena",
"CreationTime": "Vytvořeno",
"NewBook": "Nová kniha",
"Books": "Knihy",
"Update": "Aktualizovat",
"BookDeletionConfirmationMessage": "Opravdu chcete smazat knihu {0}?",
"SuccessfullyDeleted": "Úspěšně smazáno."
}
}

@ -6,6 +6,15 @@
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.",
"Menu:BookStore": "Book Store",
"Menu:Books": "Books",
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?"
"Name": "Name",
"Type": "Type",
"PublishDate": "Publish Date",
"Price": "Price",
"CreationTime": "Creation Time",
"NewBook": "New book",
"Books": "Books",
"Update": "Update",
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?",
"SuccessfullyDeleted": "Successfully deleted."
}
}

@ -3,6 +3,18 @@
"texts": {
"Menu:Home": "Ana sayfa",
"Welcome": "Hoşgeldiniz",
"LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz."
"LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz.",
"Menu:BookStore": "Kitap Mağazası",
"Menu:Books": "Kitaplar",
"Name": "İsim",
"Type": "Tür",
"PublishDate": "Yayınlanma Tarihi",
"Price": "Fiyat",
"CreationTime": "Oluşturulma zamanı",
"NewBook": "Yeni kitap",
"Books": "Kitaplar",
"Update": "Güncelle",
"BookDeletionConfirmationMessage": "Bu kitabı silmek istediğinize emin misiniz: {0}",
"SuccessfullyDeleted": "Başarıyla silindi."
}
}

@ -1,8 +1,20 @@
{
"culture": "zh-Hans",
"texts": {
"Menu:Home": "首页",
"Welcome": "欢迎",
"LongWelcomeMessage": "欢迎来到该应用程序. 这是一个基于ABP框架的启动项目. 有关更多信息, 请访问 cn.abp.io."
}
}
"culture": "zh-Hans",
"texts": {
"Menu:Home": "首页",
"Welcome": "欢迎",
"LongWelcomeMessage": "欢迎来到该应用程序. 这是一个基于ABP框架的启动项目. 有关更多信息, 请访问 cn.abp.io.",
"Menu:BookStore": "图书商店",
"Menu:Books": "图书",
"Name": "名称",
"Type": "类型",
"PublishDate": "出版时间",
"Price": "价格",
"CreationTime": "添加时间",
"NewBook": "新书籍",
"Books": "图书",
"Update": "更新",
"BookDeletionConfirmationMessage": "你确定删除书箱: {0} 吗",
"SuccessfullyDeleted": "删除成功."
}
}
Loading…
Cancel
Save