diff --git a/abp_io/README.md b/abp_io/README.md index 2095b52ef6..813329cbea 100644 --- a/abp_io/README.md +++ b/abp_io/README.md @@ -1,2 +1,2 @@ -## abp.op +## abp.io Source code of the official web site: https://abp.io diff --git a/abp_io/src/Volo.AbpWebSite.Domain/Volo.AbpWebSite.Domain.csproj b/abp_io/src/Volo.AbpWebSite.Domain/Volo.AbpWebSite.Domain.csproj index b0c9926b35..78d1a7ac96 100644 --- a/abp_io/src/Volo.AbpWebSite.Domain/Volo.AbpWebSite.Domain.csproj +++ b/abp_io/src/Volo.AbpWebSite.Domain/Volo.AbpWebSite.Domain.csproj @@ -12,7 +12,7 @@ - + diff --git a/abp_io/src/Volo.Utils.SolutionTemplating/Volo.Utils.SolutionTemplating.csproj b/abp_io/src/Volo.Utils.SolutionTemplating/Volo.Utils.SolutionTemplating.csproj index 254d8b65c5..10004ae55e 100644 --- a/abp_io/src/Volo.Utils.SolutionTemplating/Volo.Utils.SolutionTemplating.csproj +++ b/abp_io/src/Volo.Utils.SolutionTemplating/Volo.Utils.SolutionTemplating.csproj @@ -15,7 +15,7 @@ - + diff --git a/docs/en/Entities.md b/docs/en/Entities.md index a90b95d100..3a946461e7 100644 --- a/docs/en/Entities.md +++ b/docs/en/Entities.md @@ -22,7 +22,7 @@ public class Person : Entity } ``` -> If you do not want derive your entity from the base `Entity` class, you can directly implement `IEntity` interface. +> If you do not want to derive your entity from the base `Entity` class, you can directly implement `IEntity` interface. `Entity` class just defines an `Id` property with the given primary **key type**, which is `int` in the sample above. It can be other types like `string`, `Guid`, `long` or whatever you need. @@ -57,9 +57,9 @@ For the example above, the composite key is composed of `UserId` and `RoleId`. F Entities with composite keys should implement the `GetKeys()` method as shown above. -Notice that you also need to define keys of the entity in your **object-to-relational mapping** (ORM) configuration. +Notice that you also need to define keys of the entity in your **object-relational mapping** (ORM) configuration. -> Composite primary keys has a restriction with repositories. Since it has not known Id property, you can not use `IRepository` for these entities. However, you can always use `IRepository`. See repository documentation (TODO: link) for more. +> Composite primary keys has a restriction with repositories. Since it has not known Id property, you can not use `IRepository` for these entities. However, you can always use `IRepository`. See [repositories documentation](Repositories.md) for more. ### AggregateRoot Class @@ -67,7 +67,7 @@ Notice that you also need to define keys of the entity in your **object-to-relat `AggregateRoot` class extends the `Entity` class. So, it also has an `Id` property by default. -> Notice that ABP creates default repositories only for aggregate roots by default. However, it's possible to include all entities. See repository documentation (TODO: link) for more. +> Notice that ABP creates default repositories only for aggregate roots by default. However, it's possible to include all entities. See [repositories documentation](Repositories.md) for more. ABP does not force you to use aggregate roots, you can in fact use the `Entity` class as defined before. However, if you want to implement DDD and want to create aggregate root classes, there are some best practices you may want to consider: @@ -160,7 +160,7 @@ public class OrderLine : Entity > If you do not want to derive your aggregate root from the base `AggregateRoot` class, you can directly implement the `IAggregateRoot` interface. -`Order` is an **aggregate root** with `Guid` type `Id` property. It has a collection of `OrderLine` entities. `OrderLine` is another entity with a composite primary key (`OrderLine` and ` ProductId`). +`Order` is an **aggregate root** with `Guid` type `Id` property. It has a collection of `OrderLine` entities. `OrderLine` is another entity with a composite primary key (`OrderId` and ` ProductId`). While this example may not implement all the best practices of an aggregate root, it still follows good practices: diff --git a/docs/en/Exception-Handling.md b/docs/en/Exception-Handling.md index 144c6016dd..93bad2b6ed 100644 --- a/docs/en/Exception-Handling.md +++ b/docs/en/Exception-Handling.md @@ -29,7 +29,7 @@ Error Message is an instance of the `RemoteServiceErrorResponse` class. The simp } ```` -There are **optional fields** those can be filled based upon the exception that has occured. +There are **optional fields** those can be filled based upon the exception that has occurred. ##### Error Code @@ -70,7 +70,7 @@ Error **details** in an optional field of the JSON error message. Thrown `Except "code": "App:010046", "message": "Your request is not valid, please correct and try again!", "validationErrors": [{ - "message": "Username should be minimum lenght of 3.", + "message": "Username should be minimum length of 3.", "members": ["userName"] }, { diff --git a/docs/en/Microservice-Architecture.md b/docs/en/Microservice-Architecture.md index e30c070a01..ff85873ee7 100644 --- a/docs/en/Microservice-Architecture.md +++ b/docs/en/Microservice-Architecture.md @@ -19,7 +19,7 @@ One of the major goals of the ABP framework is to provide a convenient infrastru ## Microservice for New Applications -One common advise to start a new solution is **always to start with a monolith**, keep it modular and split into microservices once the monolith becomes a problem. This makes your progress fast in the beginning especially if your team is small and you don't want to deal with challanges of the microservice architecture. +One common advise to start a new solution is **always to start with a monolith**, keep it modular and split into microservices once the monolith becomes a problem. This makes your progress fast in the beginning especially if your team is small and you don't want to deal with challenges of the microservice architecture. However, developing such a well-modular application can be a problem since it is **hard to keep modules isolated** from each other as you would do it for microservices (see [Stefan Tilkov's article](https://martinfowler.com/articles/dont-start-monolith.html) about that). Microservice architecture naturally forces you to develop well isolated services, but in a modular monolithic application it's easy to tight couple modules to each other and design **weak module boundaries** and API contracts. diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 118fea5c19..ee0648f483 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -90,32 +90,6 @@ namespace MyCompany.MyProject TODO: ... -### Volo.Abp.MultiTenancy Package - -Volo.Abp.MultiTenancy is the actual package that makes your application multi-tenant. Install it into your project using PMC: - -```` -Install-Package Volo.Abp.MultiTenancy -```` - -Then you can add **AbpMultiTenancyModule** dependency to your module: - -````C# -using Volo.Abp.Modularity; -using Volo.Abp.MultiTenancy; - -namespace MyCompany.MyProject -{ - [DependsOn(typeof(AbpMultiTenancyModule))] - public class MyModule : AbpModule - { - //... - } -} -```` - -> If you add AbpMultiTenancyModule dependency to your module, then you don't need to add AbpMultiTenancyModule dependency separately since AbpMultiTenancyModule already depends on it. - #### Determining Current Tenant The first thing for a multi-tenant application is to determine the current tenant on the runtime. Volo.Abp.MultiTenancy package only provides abstractions (named as tenant resolver) for determining the current tenant, however it does not have any implementation out of the box. diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md index a841b6ad65..ecc302c34d 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md @@ -151,7 +151,7 @@ namespace Acme.BookStore * **DTO** classes are used to **transfer data** between the *presentation layer* and the *application layer*. See the [Data Transfer Objects document](../../Data-Transfer-Objects.md) for more details. * `BookDto` is used to transfer book data to the presentation layer in order to show the book information on the UI. * `BookDto` is derived from the `AuditedEntityDto` which has audit properties just like the `Book` class defined above. -* `[AutoMapFrom(typeof(Book))]` is used to create AutoMapper mapping from the `Book` class to the `BookDto` class. In this way, you get automatic convertion of `Book` objects to `BookDto` objects (instead of manually copy all properties). +* `[AutoMapFrom(typeof(Book))]` is used to create AutoMapper mapping from the `Book` class to the `BookDto` class. In this way, you get automatic conversion of `Book` objects to `BookDto` objects (instead of manually copy all properties). #### CreateUpdateBookDto @@ -425,7 +425,7 @@ $(function () { ```` * `abp.libs.datatables.createAjax` is a helper function to adapt ABP's dynamic JavaScript API proxies to Datatable's format. -* `abp.libs.datatables.normalizeConfiguration` is another helper function. There's no requirment to use it, but it simplifies the datatables configuration by providing conventional values for missing options. +* `abp.libs.datatables.normalizeConfiguration` is another helper function. There's no requirement to use it, but it simplifies the datatables configuration by providing conventional values for missing options. * `acme.bookStore.book.getList` is the function to get list of books (you have seen it before). * See [Datatable's documentation](https://datatables.net/manual/) for more configuration options. diff --git a/docs/zh-Hans/Apps/VoloDocs.md b/docs/zh-Hans/Apps/VoloDocs.md new file mode 100644 index 0000000000..f8cee69ad5 --- /dev/null +++ b/docs/zh-Hans/Apps/VoloDocs.md @@ -0,0 +1,174 @@ +# VoloDocs + +## 什么是VoloDocs? + +VoloDocs是一个跨平台的应用程序,帮助你简单的创建良好的文档与构建开发人员社区. 它借助Github集成简化了软件文档. 使用Github的强大功能进行版本控制,托管文档,并允许用户编译文档. + +## 主要功能 + +- 集成Github从仓库提供文档. +- 支持Markdown/HTML文档格式. +- 支持版本控制 (集成Github release). +- 支持多个项目. +- 允许用户在Github上编辑文档. +- 跨平台,可部署到Windows/Linux/macOS. + +## Github源码仓库 + +它是免费并且开源的. 你可以查看VoloDocs源码,我们也欢迎PR: + +https://github.com/abpframework/abp/tree/master/modules/docs + +## 下载 + +你可以在下面的链接下载VoloDocs release版: + +http://apps.abp.io/VoloDocs/VoloDocs.win-x64.zip - **Windows 64 bit** + +http://apps.abp.io/VoloDocs/VoloDocs.win-x86.zip - **Windows 32 bit** + +http://apps.abp.io/VoloDocs/VoloDocs.osx-x64.zip - **MacOS** + +http://apps.abp.io/VoloDocs/VoloDocs.linux-x64.zip - **Linux** + +上面所有的release都是自包含运行时的部署文件. 包含所有的第三方依赖与.Net Core Runtime,所以你不需要安装任何.Net Core SDK/Runtime. + +## 目录结构 + +解压 `VoloDocs.*.zip` 文件, 你会得到一个 `Web` 文件夹和 `Migrator` 文件夹. `Web` 文件夹中包含网站文件, `Migrator` 文件夹中包含构建数据库的应用程序. 在发布网站之前需要创建数据库或将现有的数据库更新到最新迁移. 如果这是你第一次安装VoloDocs, `Migrator` 会创建一个新数据库. 如果是升级已有的VoloDocs则会将数据库升级到最新的迁移. 使用 `Migrator` 你需要在 `appsettings.json` 文件中更改 `ConnectionString`. 参阅下一节了解如何配置VoloDocs应用程序. + +## 逐步部署 + +- ### 数据库迁移 + + 进入 `Migrator` 目录中创建或更新数据库. + + 打开 `appsettings.json` 文件设置连接字符串,如果你不清楚如何编写连接字符串,可以查看 https://www.connectionstrings.com/. + + 设置连接字符串后运行 `Migrate.bat` 如果是Linux或MacOS运行 `DotNet VoloDocs.Migrator.dll` 命令. + +- ### 配置网站 + + 进入 `Web` 目录下的VoloDocs文件夹. 打开 `appsettings.json` 文件设置连接字符串(与 `Migrator` 的 `appsettings.json` 相同). 你也可以为网站设置你想要的 `title`,它会显示在网站的左上角. 做完这些现在可以发布网站了. + +- ### 部署网站 + + 在上一步我们创建/更新了数据库(确保数据库链接字符串正确). + + - #### 部署到IIS + + - 移动 `Web` 文件夹到你的 `wwwroot ` 文件夹中. + - 重命名 `Web` 文件夹为 `VoloDocs` (现在我们有了 `C:\inetpub\wwwroot\VoloDocs`).![Add IIS Website](../images/volodocs-iis-add-website.png) + - 创建网站 `VoloDocs` 会自动创建相同名称的应用程序池. 打开 **应用程序池** 并双击 `VoloDocs` 应用程序池做以下设置 + - **.NET CLR 版本**: `无托管代码` + - **托管管道模式**: `集成` + + ![Add IIS Website](../images/volodocs-iis-application-pool.png) + + + + - 如果发生发生发现错误,表示未在服务器安装托管捆绑包. 请参阅文档 [this document](https://docs.microsoft.com/aspnet/core/host-and-deploy/iis/#install-the-net-core-hosting-bundle) 了解如何安装或[下载托管捆绑包](https://www.microsoft.com/net/permalink/dotnetcore-current-windows-runtime-bundle-installer). + + ``` + Handler "aspNetCore" has a bad module "AspNetCoreModuleV2" in its module list using IIS + ``` + + - 关于托管VoloDocs的更多信息,请参阅 [在IIS上托管ASP.NET Core应用程序的微软官方文档](https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/iis). + + - #### 部署到Azure + + 微软有一篇关于将ASP.NET Core应用程序部署到Azure App Service的文档. 我们建议你此[文档](https://docs.microsoft.com/en-us/azure/app-service/app-service-web-get-started-dotnet). + + - #### 使用命令行运行应用程序 + + 你可以从命令行运行应用程序,进入 `VoloDocs\Web` 文件夹并运行 `VoloDocs.Web.exe`,如果是Linux或MacOS运行 `DotNet VoloDocs.Web.dll` 命令. + +- ### 首次运行 + + 打开浏览器导航到你的网址. + + 首次运行网站,我们需要创建一个项目. + + #### 创建项目 + + 跳转到以下网址创建项目 + + - `http:///Account/Login?returnUrl=/Docs/Admin/Projects` + + ##### 默认凭据 + + 使用管理员身份登陆到管理后台,用户名密码如下: + + * **用户名**: `admin` + + * **密码**: `1q2w3E*` + + ##### 示例项目的定义 + + 以下是一个使用了Github源的示例项目信息. + + 配置VoloDocs展示存储在Github仓库中ABP Framework的文档. + + 这是ABP Framework文档在Github的链接: + + https://github.com/abpframework/abp/tree/master/docs/zh-Hans + + + + * **名称**: `ABP Framework` + + * **简称**: `abp` + + * **格式**: `markdown` + + * **默认文档名称**: `Index` + + * **文档导航名称**: `docs-nav.json` ([参见示例](https://github.com/abpframework/abp/blob/master/docs/zh-Hans/docs-nav.json)) + + * **最小版本**: *留空* *(隐藏之前的版本)* + + * **主网站网址**: `/` + + * **最新版本分支名称**: 留空 + + * **GitHub链接**: `https://github.com/abpframework/abp/tree/{version}/docs/zh-Hans/` + + * **GitHub访问令牌**: [参见如何创建Github访问令牌](#retrieving-github-access-token) + + * **GitHub用户名称**: [参见如何找到自己的Github用户名称](#learn-your-github-username) + + ![Creating a new project](../images/docs-create-project.jpg) + + ##### 创建访问令牌 + + 在Github页右上角找到 `Settings`,然后在左侧导航中点击 `Developer Settings`,在这里选择 `Personal access tokens`. 点击创建新token,输入名称与描述并勾选repo复选框. 如果已有访问令牌但已经忘记,可以选择[重新生成](https://github.com/settings/tokens/new). + + ###### 创建仅授权访问公共仓库的token + + 想要仅授权访问公共仓库,仅勾选 `public_repo` 就可以了,然后点击页面底部的 `Generate Token` 按钮完成操作. + + ![Retrieve GitHub Access Token for Public Repo](../images/github-access-token-public-repo.jpg) + + ###### 创建可访问私有仓库的token + + 想要授权访问私有仓库,勾选 `repo` 下的所有选项. 然后点击页面底部的 `Generate Token` 按钮完成操作. + + ![Retrieve GitHub Access Token for Private Repo](../images/github-access-token-private-repo.jpg) + + ###### 查看你的Github用户名称 + + 在Github页面右上角点击头像图片,"Signed in as ..." 后面就是你的用户名称 + + ![Your GitHub Username](../images/github-myusername.jpg) + + + +保存项目后转到网站根地址,你会看到文档已经正常显示. + +`http:///documents` + +### 发现问题? + +如果你在安装,使用时遇到问题或者发现bug,请发起issues与我们联系: + +https://github.com/abpframework/abp/issues/new \ No newline at end of file diff --git a/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md b/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md index e0db48397e..0c6017e6e7 100644 --- a/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md +++ b/docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md @@ -5,4 +5,4 @@ * **推荐** 定义 **public getter 和 setter** 的DTO成员 . * **推荐** 使用 **data annotations** **验证** service输入DTO的属性. * **不推荐** 在DTO中添加任何 **逻辑**, 在必要的时候可以实现 `IValidatableObject` 接口. -* **推荐** 为所有的DTO标记 **[Serializable]** Attribute. 因为它们已经是可序列化的, 开人发员可能会希望进行二进制序列化. \ No newline at end of file +* **推荐** 为所有的DTO标记 **[Serializable]** Attribute. 因为它们已经是可序列化的, 开发人员可能会希望进行二进制序列化. diff --git a/docs/zh-Hans/Best-Practices/Entities.md b/docs/zh-Hans/Best-Practices/Entities.md index 637ecaef6d..fd709ef35f 100644 --- a/docs/zh-Hans/Best-Practices/Entities.md +++ b/docs/zh-Hans/Best-Practices/Entities.md @@ -64,7 +64,7 @@ public class Issue : FullAuditedAggregateRoot //使用Guid作为键/标识 protected Issue() { /* 此构造函数是提供给ORM用来从数据库中获取实体. - * - 无需初始化Lanels集合 + * - 无需初始化Labels集合 因为它会被来自数据库的值覆盖. - It's protected since proxying and deserialization tools 可能不适用于私有构造函数. @@ -150,4 +150,4 @@ public class IssueLabel : Entity ### 参考文献 * Effective Aggregate Design by Vaughn Vernon - http://dddcommunity.org/library/vernon_2011 \ No newline at end of file + http://dddcommunity.org/library/vernon_2011 diff --git a/docs/zh-Hans/Dependency-Injection.md b/docs/zh-Hans/Dependency-Injection.md index b46c602c4c..381b77ec35 100644 --- a/docs/zh-Hans/Dependency-Injection.md +++ b/docs/zh-Hans/Dependency-Injection.md @@ -319,4 +319,4 @@ public class AppModule : AbpModule ### 请参阅 -* [ASP.NET Core依赖注入最佳实践,提示和技巧](https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96) +* [ASP.NET Core依赖注入最佳实践,提示和技巧](https://cn.abp.io/blog/Abp/asp-net-core-dependency-injection-best-practices-tips-tricks) diff --git a/docs/zh-Hans/Domain-Driven-Design.md b/docs/zh-Hans/Domain-Driven-Design.md new file mode 100644 index 0000000000..d4e51a152c --- /dev/null +++ b/docs/zh-Hans/Domain-Driven-Design.md @@ -0,0 +1,33 @@ +# 领取驱动设计 + +## 什么是DDD? + +ABP框架提供了**基础设施**使基础**DDD**的开发更易实现. DDD在[维基百科中的定义](https://zh.wikipedia.org/wiki/%E5%9F%9F%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91)如下: + +> **领域驱动设计(DDD)** 是一种通过将实现连接到持续进化的模型来满足复杂需求的软件开发方法. 领域驱动设计的前提是: +> +> - 把项目的主要重点放在核心领域和领域逻辑上 +> - 把复杂的设计放在领域模型上 +> - 发起技术专家和领域专家之间的创造性协作,以迭代方式完善解决特定领域问题的概念模型 + +### 分层 + +ABP框架遵循DDD原则和模式去实现分层应用程序模型,该模型由四个基本层组成: + +- **表示层**: 为用户提供接口. 使用*应用层*实现与用户交互. +- **应用层**: 表示层与领域层的中介,编排业务对象执行特定的应用程序任务. 使用应用程序逻辑实现用例. +- **领域层**: 包含业务对象以及业务规则. 是应用程序的核心. +- **基础设施层**: 提供通用的技术功能,支持更高的层,主要使用第三方类库. + +## 内容 + +* **领域层** + * [实体与聚合根](Entities.md) + * 值对象 + * [仓储](Repositories.md) + * 领域服务 + * 规约 +* **应用层** + * [应用服务](Application-Services.md) + * [数据传输对象(DTO)](Data-Transfer-Objects.md) + * 工作单元 \ No newline at end of file diff --git a/docs/zh-Hans/Exception-Handling.md b/docs/zh-Hans/Exception-Handling.md index ecb4acf5e7..a251c50f61 100644 --- a/docs/zh-Hans/Exception-Handling.md +++ b/docs/zh-Hans/Exception-Handling.md @@ -70,7 +70,7 @@ ABP提供了用于处理Web应用程序异常的标准模型. "code": "App:010046", "message": "Your request is not valid, please correct and try again!", "validationErrors": [{ - "message": "Username should be minimum lenght of 3.", + "message": "Username should be minimum length of 3.", "members": ["userName"] }, { diff --git a/docs/zh-Hans/Getting-Started-AspNetCore-Application.md b/docs/zh-Hans/Getting-Started-AspNetCore-Application.md index cf9ac3f66f..db6e73f35c 100644 --- a/docs/zh-Hans/Getting-Started-AspNetCore-Application.md +++ b/docs/zh-Hans/Getting-Started-AspNetCore-Application.md @@ -77,11 +77,11 @@ namespace BasicAspNetCoreApplication { public class Startup { - public IServiceProvider ConfigureServices(ServiceConfigurationContext context) + public IServiceProvider ConfigureServices(IServiceCollection services) { - context.Services.AddApplication(); + services.AddApplication(); - return context.Services.BuildServiceProviderFromFactory(); + return services.BuildServiceProviderFromFactory(); } public void Configure(IApplicationBuilder app) diff --git a/docs/zh-Hans/Multi-Tenancy.md b/docs/zh-Hans/Multi-Tenancy.md index 6364428ec1..911803b1be 100644 --- a/docs/zh-Hans/Multi-Tenancy.md +++ b/docs/zh-Hans/Multi-Tenancy.md @@ -90,32 +90,6 @@ namespace MyCompany.MyProject TODO: ... -### Volo.Abp.MultiTenancy - -Volo.Abp.MultiTenancy 才是让你的程序实现多租户的真正的包.使用PMC将它安装到你的项目中: - -```` -Install-Package Volo.Abp.MultiTenancy -```` - -然后添加 **AbpMultiTenancyModule** 依赖到你的模块中: - -````C# -using Volo.Abp.Modularity; -using Volo.Abp.MultiTenancy; - -namespace MyCompany.MyProject -{ - [DependsOn(typeof(AbpMultiTenancyModule))] - public class MyModule : AbpModule - { - //... - } -} -```` - -> 如果你添加了AbpMultiTenancyModule依赖,就不需要再另外添加AbpMultiTenancyModule依赖了,因为AbpMultiTenancyModule已经依赖它了. - #### 确定当前租户 多租户的应用程序运行的时候首先要做的就是确定当前租户. diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 6b98655e85..8e88cf6921 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -67,8 +67,7 @@ "path": "Exception-Handling.md" }, { - "text": "验证", - "path": "Validation.md" + "text": "验证" }, { "text": "授权" @@ -145,6 +144,7 @@ }, { "text": "领域驱动设计", + "path": "Domain-Driven-Design.md", "items": [ { "text": "领域层", @@ -180,8 +180,7 @@ "text": "数据传输对象(DTO)" }, { - "text": "工作单元", - "path": "Unit-Of-Work.md" + "text": "工作单元" } ] } diff --git a/docs/zh-Hans/images/docs-create-project.jpg b/docs/zh-Hans/images/docs-create-project.jpg new file mode 100644 index 0000000000..742f5e307f Binary files /dev/null and b/docs/zh-Hans/images/docs-create-project.jpg differ diff --git a/docs/zh-Hans/images/github-access-token-private-repo.jpg b/docs/zh-Hans/images/github-access-token-private-repo.jpg new file mode 100644 index 0000000000..5bc53cc63d Binary files /dev/null and b/docs/zh-Hans/images/github-access-token-private-repo.jpg differ diff --git a/docs/zh-Hans/images/github-access-token-public-repo.jpg b/docs/zh-Hans/images/github-access-token-public-repo.jpg new file mode 100644 index 0000000000..b909c2cfe5 Binary files /dev/null and b/docs/zh-Hans/images/github-access-token-public-repo.jpg differ diff --git a/docs/zh-Hans/images/github-myusername.jpg b/docs/zh-Hans/images/github-myusername.jpg new file mode 100644 index 0000000000..4ac57eeed4 Binary files /dev/null and b/docs/zh-Hans/images/github-myusername.jpg differ diff --git a/docs/zh-Hans/images/microservice-sample-update-database-authserver.png b/docs/zh-Hans/images/microservice-sample-update-database-authserver.png new file mode 100644 index 0000000000..689019b587 Binary files /dev/null and b/docs/zh-Hans/images/microservice-sample-update-database-authserver.png differ diff --git a/docs/zh-Hans/images/microservice-sample-update-database-products.png b/docs/zh-Hans/images/microservice-sample-update-database-products.png new file mode 100644 index 0000000000..b49c2a8f8e Binary files /dev/null and b/docs/zh-Hans/images/microservice-sample-update-database-products.png differ diff --git a/docs/zh-Hans/images/volodocs-iis-add-website.png b/docs/zh-Hans/images/volodocs-iis-add-website.png new file mode 100644 index 0000000000..878b3e8f0c Binary files /dev/null and b/docs/zh-Hans/images/volodocs-iis-add-website.png differ diff --git a/docs/zh-Hans/images/volodocs-iis-application-pool.png b/docs/zh-Hans/images/volodocs-iis-application-pool.png new file mode 100644 index 0000000000..cc5186f50b Binary files /dev/null and b/docs/zh-Hans/images/volodocs-iis-application-pool.png differ diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index d63ef20752..e1af7720f9 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -226,6 +226,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.FluentValidation.T EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Cli.Tests", "test\Volo.Abp.Cli.Tests\Volo.Abp.Cli.Tests.csproj", "{92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EntityFrameworkCore.Sqlite", "src\Volo.Abp.EntityFrameworkCore.Sqlite\Volo.Abp.EntityFrameworkCore.Sqlite.csproj", "{58CF8957-5045-4F81-884D-72DF48F721CC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -672,6 +674,10 @@ Global {92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU {92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF}.Release|Any CPU.Build.0 = Release|Any CPU + {58CF8957-5045-4F81-884D-72DF48F721CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58CF8957-5045-4F81-884D-72DF48F721CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58CF8957-5045-4F81-884D-72DF48F721CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58CF8957-5045-4F81-884D-72DF48F721CC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -787,6 +793,7 @@ Global {43D5FE61-ECBF-4B16-AD95-0043E18EB93A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {E9E1714F-7ED2-4BD1-BA4A-BA06E398288A} = {447C8A77-E5F0-4538-8687-7383196D04EA} {92B70EFF-C1B1-4D1D-8BCE-D116908FC6FF} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {58CF8957-5045-4F81-884D-72DF48F721CC} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index cdf1f30788..dc2f04b623 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs @@ -35,10 +35,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form TagHelper.AspFor.Name, SurroundInnerHtmlAndGet(context, output, innerHtml, isCheckbox), order, - out var surpress + out var suppress ); - if (surpress) + if (suppress) { output.SuppressOutput(); } @@ -389,10 +389,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form return idAttr != null ? "for=\"" + idAttr.Value + "\"" : ""; } - protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool surpress) + protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool suppress) { var list = context.GetValue>(FormGroupContents) ?? new List(); - surpress = list == null; + suppress = list == null; if (list != null && !list.Any(igc => igc.HtmlContent.Contains("id=\"" + propertyName.Replace('.', '_') + "\""))) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs index 6ec2911714..f89d3c1fee 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs @@ -29,9 +29,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form var html = GetHtml(context, output, selectItems); - AddGroupToFormGroupContents(context, TagHelper.AspFor.Name, html, order, out var surpress); + AddGroupToFormGroupContents(context, TagHelper.AspFor.Name, html, order, out var suppress); - if (surpress) + if (suppress) { output.SuppressOutput(); } @@ -157,10 +157,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form return TagHelper.AspFor.ModelExplorer.Model?.ToString(); } - protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool surpress) + protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool suppress) { var list = context.GetValue>(FormGroupContents) ?? new List(); - surpress = list == null; + suppress = list == null; if (list != null && !list.Any(igc => igc.HtmlContent.Contains("id=\"" + propertyName.Replace('.', '_') + "\""))) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs index cd3294d66f..2c7e6ad1cf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs @@ -33,9 +33,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder(); - AddGroupToFormGroupContents(context, TagHelper.AspFor.Name, SurroundInnerHtmlAndGet(context, output, innerHtml), order, out var surpress); + AddGroupToFormGroupContents(context, TagHelper.AspFor.Name, SurroundInnerHtmlAndGet(context, output, innerHtml), order, out var suppress); - if (surpress) + if (suppress) { output.SuppressOutput(); } @@ -304,10 +304,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form return idAttr != null ? "for=\"" + idAttr.Value + "\"" : ""; } - protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool surpress) + protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool suppress) { var list = context.GetValue>(FormGroupContents) ?? new List(); - surpress = list == null; + suppress = list == null; if (list != null && !list.Any(igc => igc.HtmlContent.Contains("id=\"" + propertyName.Replace('.', '_') + "\""))) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml index 4864f2dafe..1cd530d021 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml @@ -28,9 +28,12 @@ @(await Component.InvokeAsync()) - +
@(await Component.InvokeAsync()) +
+ @RenderSection("content_toolbar", false) +
@RenderBody()
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs index 8fd16f5864..62258329ad 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -21,19 +22,43 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages { public abstract class AbpPageModel : PageModel { - public IClock Clock { get; set; } + public IServiceProvider ServiceProvider { get; set; } + protected readonly object ServiceProviderLock = new object(); + protected TService LazyGetRequiredService(ref TService reference) + { + if (reference == null) + { + lock (ServiceProviderLock) + { + if (reference == null) + { + reference = ServiceProvider.GetRequiredService(); + } + } + } + + return reference; + } + + public IClock Clock => LazyGetRequiredService(ref _clock); + private IClock _clock; public AlertList Alerts => AlertManager.Alerts; - public IUnitOfWorkManager UnitOfWorkManager { get; set; } + public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); + private IUnitOfWorkManager _unitOfWorkManager; - public IObjectMapper ObjectMapper { get; set; } + public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); + private IObjectMapper _objectMapper; - public IGuidGenerator GuidGenerator { get; set; } + public IGuidGenerator GuidGenerator => LazyGetRequiredService(ref _guidGenerator); + private IGuidGenerator _guidGenerator; - public ILoggerFactory LoggerFactory { get; set; } + public ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); + private ILoggerFactory _loggerFactory; - public IStringLocalizerFactory StringLocalizerFactory { get; set; } + public IStringLocalizerFactory StringLocalizerFactory => LazyGetRequiredService(ref _stringLocalizerFactory); + private IStringLocalizerFactory _stringLocalizerFactory; public IStringLocalizer L { @@ -56,17 +81,23 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages protected Type LocalizationResourceType { get; set; } - public ICurrentUser CurrentUser { get; set; } + public ICurrentUser CurrentUser => LazyGetRequiredService(ref _currentUser); + private ICurrentUser _currentUser; - public ICurrentTenant CurrentTenant { get; set; } + public ICurrentTenant CurrentTenant => LazyGetRequiredService(ref _currentTenant); + private ICurrentTenant _currentTenant; - public ISettingProvider SettingProvider { get; set; } + public ISettingProvider SettingProvider => LazyGetRequiredService(ref _settingProvider); + private ISettingProvider _settingProvider; - public IModelStateValidator ModelValidator { get; set; } + public IModelStateValidator ModelValidator => LazyGetRequiredService(ref _modelValidator); + private IModelStateValidator _modelValidator; - public IAuthorizationService AuthorizationService { get; set; } + public IAuthorizationService AuthorizationService => LazyGetRequiredService(ref _authorizationService); + private IAuthorizationService _authorizationService; - public IAlertManager AlertManager { get; set; } + public IAlertManager AlertManager => LazyGetRequiredService(ref _alertManager); + private IAlertManager _alertManager; protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj index e99572852e..4ee308e591 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj @@ -23,7 +23,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs index a5d206cf55..f0ee490ed1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Aspects; @@ -18,27 +19,55 @@ namespace Volo.Abp.AspNetCore.Mvc { public abstract class AbpController : Controller, IAvoidDuplicateCrossCuttingConcerns { - public IUnitOfWorkManager UnitOfWorkManager { get; set; } + public IServiceProvider ServiceProvider { get; set; } + protected readonly object ServiceProviderLock = new object(); + protected TService LazyGetRequiredService(ref TService reference) + { + if (reference == null) + { + lock (ServiceProviderLock) + { + if (reference == null) + { + reference = ServiceProvider.GetRequiredService(); + } + } + } + + return reference; + } + + public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); + private IUnitOfWorkManager _unitOfWorkManager; - public IObjectMapper ObjectMapper { get; set; } + public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); + private IObjectMapper _objectMapper; - public IGuidGenerator GuidGenerator { get; set; } + public IGuidGenerator GuidGenerator => LazyGetRequiredService(ref _guidGenerator); + private IGuidGenerator _guidGenerator; - public ILoggerFactory LoggerFactory { get; set; } + public ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); + private ILoggerFactory _loggerFactory; - public ICurrentUser CurrentUser { get; set; } + public ICurrentUser CurrentUser => LazyGetRequiredService(ref _currentUser); + private ICurrentUser _currentUser; - public ICurrentTenant CurrentTenant { get; set; } + public ICurrentTenant CurrentTenant => LazyGetRequiredService(ref _currentTenant); + private ICurrentTenant _currentTenant; - public IAuthorizationService AuthorizationService { get; set; } + public IAuthorizationService AuthorizationService => LazyGetRequiredService(ref _authorizationService); + private IAuthorizationService _authorizationService; protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current; - public IClock Clock { get; set; } + public IClock Clock => LazyGetRequiredService(ref _clock); + private IClock _clock; - public IModelStateValidator ModelValidator { get; set; } + public IModelStateValidator ModelValidator => LazyGetRequiredService(ref _modelValidator); + private IModelStateValidator _modelValidator; - public IFeatureChecker FeatureChecker { get; set; } + public IFeatureChecker FeatureChecker => LazyGetRequiredService(ref _featureChecker); + private IFeatureChecker _featureChecker; public List AppliedCrossCuttingConcerns { get; } = new List(); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs index 2274f0a9b6..d9de135e7f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs @@ -39,6 +39,11 @@ namespace Volo.Abp.AspNetCore.Mvc return; } + if (context.Key.Name.IsNullOrWhiteSpace()) + { + return; + } + if (_localizationOptions.Value.Value.DataAnnotationLocalizerProvider == null) { return; diff --git a/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj b/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj index 37c728f175..fb85cbb3ec 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj +++ b/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj @@ -29,7 +29,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs index 502fbda5bb..f36a7f4860 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs @@ -36,7 +36,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling // We can't do anything if the response has already started, just abort. if (httpContext.Response.HasStarted) { - _logger.LogWarning("An exception occured, but response has already started!"); + _logger.LogWarning("An exception occurred, but response has already started!"); throw; } diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index ae384414a3..029669c348 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -18,7 +18,7 @@
- + \ No newline at end of file diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProviderFactory.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProviderFactory.cs index 8e0d4f574d..21a7ca331d 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProviderFactory.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacServiceProviderFactory.cs @@ -38,7 +38,7 @@ namespace Autofac.Extensions.DependencyInjection /// /// Initializes a new instance of the class. /// - /// Action on a that adds component registrations to the conatiner. + /// Action on a that adds component registrations to the container. public AutofacServiceProviderFactory(Action configurationAction = null) { _configurationAction = configurationAction ?? (builder => { }); diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/ServiceCollectionExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/ServiceCollectionExtensions.cs index 5552cda7b2..1195cb9fb1 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/ServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/ServiceCollectionExtensions.cs @@ -37,7 +37,7 @@ namespace Autofac.Extensions.DependencyInjection /// Adds the to the service collection. /// /// The service collection to add the factory to. - /// Action on a that adds component registrations to the conatiner. + /// Action on a that adds component registrations to the container. /// The service collection. public static IServiceCollection AddAutofac(this IServiceCollection services, Action configurationAction = null) { diff --git a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj index c8737bbfeb..3e68488105 100644 --- a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj +++ b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs index 7e1154ec7e..6241bc81f9 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs @@ -42,7 +42,7 @@ namespace Volo.Abp.BackgroundJobs public virtual DateTime? LastTryTime { get; set; } /// - /// This is true if this job is continously failed and will not be executed again. + /// This is true if this job is continuously failed and will not be executed again. /// public virtual bool IsAbandoned { get; set; } diff --git a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs index 70f13c6b18..6be122be8f 100644 --- a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs +++ b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs @@ -10,11 +10,13 @@ namespace Volo.Abp.Caching /// Global Cache entry options. /// public DistributedCacheEntryOptions GlobalCacheEntryOptions { get; set; } + /// /// List of all cache configurators. /// (func argument:Name of cache) /// public List> CacheConfigurators { get; set; } //TODO list item use a configurator interface instead? + public CacheOptions() { CacheConfigurators = new List>(); diff --git a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs index 9ec056d4d7..e4d2c70ba5 100644 --- a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs +++ b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs @@ -12,6 +12,10 @@ using Volo.Abp.Threading; namespace Volo.Abp.Caching { + /// + /// Represents a distributed cache of type. + /// + /// The type of cache item being cached. public class DistributedCache : IDistributedCache where TCacheItem : class { @@ -57,6 +61,12 @@ namespace Volo.Abp.Caching SetDefaultOptions(); } + /// + /// Gets a cache item with the given key. If no cache item is found for the given key then returns null. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The cache item, or null. public virtual TCacheItem Get( string key, bool? hideErrors = null) @@ -88,6 +98,13 @@ namespace Volo.Abp.Caching return Serializer.Deserialize(cachedBytes); } + /// + /// Gets a cache item with the given key. If no cache item is found for the given key then returns null. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The cache item, or null. public virtual async Task GetAsync( string key, bool? hideErrors = null, @@ -123,6 +140,15 @@ namespace Volo.Abp.Caching return Serializer.Deserialize(cachedBytes); } + /// + /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item + /// provided by delegate and returns the provided cache item. + /// + /// The key of cached item to be retrieved from the cache. + /// The factory delegate is used to provide the cache item when no cache item is found for the given . + /// The cache options for the factory delegate. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The cache item. public TCacheItem GetOrAdd( string key, Func factory, @@ -150,6 +176,16 @@ namespace Volo.Abp.Caching return value; } + /// + /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item + /// provided by delegate and returns the provided cache item. + /// + /// The key of cached item to be retrieved from the cache. + /// The factory delegate is used to provide the cache item when no cache item is found for the given . + /// The cache options for the factory delegate. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The cache item. public async Task GetOrAddAsync( string key, Func> factory, @@ -179,6 +215,13 @@ namespace Volo.Abp.Caching return value; } + /// + /// Sets the cache item value for the provided key. + /// + /// The key of cached item to be retrieved from the cache. + /// The cache item value to set in the cache. + /// The cache options for the value. + /// Indicates to throw or hide the exceptions for the distributed cache. public virtual void Set( string key, TCacheItem value, @@ -207,6 +250,15 @@ namespace Volo.Abp.Caching } } + /// + /// Sets the cache item value for the provided key. + /// + /// The key of cached item to be retrieved from the cache. + /// The cache item value to set in the cache. + /// The cache options for the value. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The indicating that the operation is asynchronous. public virtual async Task SetAsync( string key, TCacheItem value, @@ -237,6 +289,11 @@ namespace Volo.Abp.Caching } } + /// + /// Refreshes the cache value of the given key, and resets its sliding expiration timeout. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. public virtual void Refresh( string key, bool? hideErrors = null) @@ -259,6 +316,13 @@ namespace Volo.Abp.Caching } } + /// + /// Refreshes the cache value of the given key, and resets its sliding expiration timeout. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The indicating that the operation is asynchronous. public virtual async Task RefreshAsync( string key, bool? hideErrors = null, @@ -282,6 +346,12 @@ namespace Volo.Abp.Caching } } + + /// + /// Removes the cache item for given key from cache. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. public virtual void Remove( string key, bool? hideErrors = null) @@ -303,6 +373,13 @@ namespace Volo.Abp.Caching } } + /// + /// Removes the cache item for given key from cache. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The indicating that the operation is asynchronous. public virtual async Task RemoveAsync( string key, bool? hideErrors = null, diff --git a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/IDistributedCache.cs b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/IDistributedCache.cs index 1567bfca30..23bd6f4cf2 100644 --- a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/IDistributedCache.cs +++ b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/IDistributedCache.cs @@ -6,20 +6,46 @@ using Microsoft.Extensions.Caching.Distributed; namespace Volo.Abp.Caching { + /// + /// Represents a distributed cache of type. + /// + /// The type of cache item being cached. public interface IDistributedCache where TCacheItem : class { + /// + /// Gets a cache item with the given key. If no cache item is found for the given key then returns null. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The cache item, or null. TCacheItem Get( string key, bool? hideErrors = null ); + /// + /// Gets a cache item with the given key. If no cache item is found for the given key then returns null. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The cache item, or null. Task GetAsync( [NotNull] string key, bool? hideErrors = null, CancellationToken token = default ); + /// + /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item + /// provided by delegate and returns the provided cache item. + /// + /// The key of cached item to be retrieved from the cache. + /// The factory delegate is used to provide the cache item when no cache item is found for the given . + /// The cache options for the factory delegate. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The cache item. TCacheItem GetOrAdd( string key, Func factory, @@ -27,6 +53,16 @@ namespace Volo.Abp.Caching bool? hideErrors = null ); + /// + /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item + /// provided by delegate and returns the provided cache item. + /// + /// The key of cached item to be retrieved from the cache. + /// The factory delegate is used to provide the cache item when no cache item is found for the given . + /// The cache options for the factory delegate. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The cache item. Task GetOrAddAsync( [NotNull] string key, Func> factory, @@ -35,6 +71,13 @@ namespace Volo.Abp.Caching CancellationToken token = default ); + /// + /// Sets the cache item value for the provided key. + /// + /// The key of cached item to be retrieved from the cache. + /// The cache item value to set in the cache. + /// The cache options for the value. + /// Indicates to throw or hide the exceptions for the distributed cache. void Set( string key, TCacheItem value, @@ -42,6 +85,15 @@ namespace Volo.Abp.Caching bool? hideErrors = null ); + /// + /// Sets the cache item value for the provided key. + /// + /// The key of cached item to be retrieved from the cache. + /// The cache item value to set in the cache. + /// The cache options for the value. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The indicating that the operation is asynchronous. Task SetAsync( [NotNull] string key, [NotNull] TCacheItem value, @@ -50,22 +102,46 @@ namespace Volo.Abp.Caching CancellationToken token = default ); + /// + /// Refreshes the cache value of the given key, and resets its sliding expiration timeout. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. void Refresh( string key, bool? hideErrors = null ); + /// + /// Refreshes the cache value of the given key, and resets its sliding expiration timeout. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The indicating that the operation is asynchronous. Task RefreshAsync( string key, bool? hideErrors = null, CancellationToken token = default ); + /// + /// Removes the cache item for given key from cache. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. void Remove( string key, bool? hideErrors = null ); + /// + /// Removes the cache item for given key from cache. + /// + /// The key of cached item to be retrieved from the cache. + /// Indicates to throw or hide the exceptions for the distributed cache. + /// The for the task. + /// The indicating that the operation is asynchronous. Task RemoveAsync( string key, bool? hideErrors = null, diff --git a/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs b/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs index a7cf7c763e..31e7f257d4 100644 --- a/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs @@ -84,11 +84,11 @@ namespace System } /// - /// Gets index of nth occurence of a char in a string. + /// Gets index of nth occurrence of a char in a string. /// /// source string to be searched /// Char to search in - /// Count of the occurence + /// Count of the occurrence public static int NthIndexOf(this string str, char c, int n) { Check.NotNull(str, nameof(str)); diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index 71d48038e2..e5355a19c1 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -14,16 +14,16 @@ - + - + - + diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/ReflectionHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/ReflectionHelper.cs index 1c4b162b21..b314ca6b84 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/ReflectionHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/ReflectionHelper.cs @@ -165,5 +165,41 @@ namespace Volo.Abp.Reflection property = currentType.GetProperty(properties.Last()); property.SetValue(obj, value); } + + + /// + /// Get all the constant values in the specified type (including the base type). + /// + /// + /// + public static string[] GetPublicConstantsRecursively(Type type) + { + const int maxRecursiveParameterValidationDepth = 8; + + var publicConstants = new List(); + + void Recursively(List constants, Type targetType, int currentDepth) + { + if (currentDepth > maxRecursiveParameterValidationDepth) + { + return; + } + + constants.AddRange(targetType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy) + .Where(x => x.IsLiteral && !x.IsInitOnly) + .Select(x => x.GetValue(null).ToString())); + + var nestedTypes = targetType.GetNestedTypes(BindingFlags.Public); + + foreach (var nestedType in nestedTypes) + { + Recursively(constants, nestedType, currentDepth + 1); + } + } + + Recursively(publicConstants, type, 1); + + return publicConstants.ToArray(); + } } } diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs index b3ed6a23cb..0931d090f3 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs @@ -9,7 +9,9 @@ namespace Volo.Abp.Application.Dtos [Serializable] public class LimitedResultRequestDto : ILimitedResultRequest { + public static int DefaultMaxResultCount { get; set; } = 10; + [Range(1, int.MaxValue)] - public virtual int MaxResultCount { get; set; } = 10; + public virtual int MaxResultCount { get; set; } = DefaultMaxResultCount; } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs index 3b2bbc7582..909ad40940 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs @@ -1,5 +1,6 @@ using JetBrains.Annotations; using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -31,31 +32,59 @@ namespace Volo.Abp.Application.Services IAuditingEnabled, ITransientDependency { + public IServiceProvider ServiceProvider { get; set; } + protected readonly object ServiceProviderLock = new object(); + protected TService LazyGetRequiredService(ref TService reference) + { + if (reference == null) + { + lock (ServiceProviderLock) + { + if (reference == null) + { + reference = ServiceProvider.GetRequiredService(); + } + } + } + + return reference; + } + public static string[] CommonPostfixes { get; set; } = { "AppService", "ApplicationService", "Service" }; public List AppliedCrossCuttingConcerns { get; } = new List(); - public IUnitOfWorkManager UnitOfWorkManager { get; set; } + public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); + private IUnitOfWorkManager _unitOfWorkManager; - public IObjectMapper ObjectMapper { get; set; } + public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); + private IObjectMapper _objectMapper; public IGuidGenerator GuidGenerator { get; set; } - public ILoggerFactory LoggerFactory { get; set; } + public ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); + private ILoggerFactory _loggerFactory; - public ICurrentTenant CurrentTenant { get; set; } + public ICurrentTenant CurrentTenant => LazyGetRequiredService(ref _currentTenant); + private ICurrentTenant _currentTenant; - public ICurrentUser CurrentUser { get; set; } + public ICurrentUser CurrentUser => LazyGetRequiredService(ref _currentUser); + private ICurrentUser _currentUser; - public ISettingProvider SettingProvider { get; set; } + public ISettingProvider SettingProvider => LazyGetRequiredService(ref _settingProvider); + private ISettingProvider _settingProvider; - public IClock Clock { get; set; } + public IClock Clock => LazyGetRequiredService(ref _clock); + private IClock _clock; - public IAuthorizationService AuthorizationService { get; set; } + public IAuthorizationService AuthorizationService => LazyGetRequiredService(ref _authorizationService); + private IAuthorizationService _authorizationService; - public IFeatureChecker FeatureChecker { get; set; } + public IFeatureChecker FeatureChecker => LazyGetRequiredService(ref _featureChecker); + private IFeatureChecker _featureChecker; - public IStringLocalizerFactory StringLocalizerFactory { get; set; } + public IStringLocalizerFactory StringLocalizerFactory => LazyGetRequiredService(ref _stringLocalizerFactory); + private IStringLocalizerFactory _stringLocalizerFactory; public IStringLocalizer L => _localizer ?? (_localizer = StringLocalizerFactory.Create(LocalizationResource)); private IStringLocalizer _localizer; diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs index 36c4780672..6e3b476b5c 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs @@ -20,8 +20,8 @@ namespace Volo.Abp.Application.Services } } - public abstract class AsyncCrudAppService - : AsyncCrudAppService + public abstract class AsyncCrudAppService + : AsyncCrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { @@ -32,8 +32,8 @@ namespace Volo.Abp.Application.Services } } - public abstract class AsyncCrudAppService - : AsyncCrudAppService + public abstract class AsyncCrudAppService + : AsyncCrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { @@ -44,9 +44,9 @@ namespace Volo.Abp.Application.Services } } - public abstract class AsyncCrudAppService - : CrudAppServiceBase, - IAsyncCrudAppService + public abstract class AsyncCrudAppService + : CrudAppServiceBase, + IAsyncCrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { @@ -66,9 +66,9 @@ namespace Volo.Abp.Application.Services return MapToEntityDto(entity); } - public virtual async Task> GetListAsync(TGetAllInput input) + public virtual async Task> GetListAsync(TGetListInput input) { - await CheckGetAllPolicyAsync(); + await CheckGetListPolicyAsync(); var query = CreateFilteredQuery(input); @@ -128,9 +128,9 @@ namespace Volo.Abp.Application.Services await CheckPolicyAsync(GetPolicyName); } - protected virtual async Task CheckGetAllPolicyAsync() + protected virtual async Task CheckGetListPolicyAsync() { - await CheckPolicyAsync(GetAllPolicyName); + await CheckPolicyAsync(GetListPolicyName); } protected virtual async Task CheckCreatePolicyAsync() diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs index 8127e88f23..1fd6f869ff 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs @@ -17,8 +17,8 @@ namespace Volo.Abp.Application.Services } } - public abstract class CrudAppService - : CrudAppService + public abstract class CrudAppService + : CrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { @@ -29,8 +29,8 @@ namespace Volo.Abp.Application.Services } } - public abstract class CrudAppService - : CrudAppService + public abstract class CrudAppService + : CrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto where TCreateInput : IEntityDto @@ -42,9 +42,9 @@ namespace Volo.Abp.Application.Services } } - public abstract class CrudAppService - : CrudAppServiceBase, - ICrudAppService + public abstract class CrudAppService + : CrudAppServiceBase, + ICrudAppService where TEntity : class, IEntity where TEntityDto : IEntityDto { @@ -62,9 +62,9 @@ namespace Volo.Abp.Application.Services return MapToEntityDto(entity); } - public virtual PagedResultDto GetAll(TGetAllInput input) + public virtual PagedResultDto GetList(TGetListInput input) { - CheckGetAllPolicy(); + CheckGetListPolicy(); var query = CreateFilteredQuery(input); @@ -122,9 +122,9 @@ namespace Volo.Abp.Application.Services CheckPolicy(GetPolicyName); } - protected virtual void CheckGetAllPolicy() + protected virtual void CheckGetListPolicy() { - CheckPolicy(GetAllPolicyName); + CheckPolicy(GetListPolicyName); } protected virtual void CheckCreatePolicy() diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs index eb4c7a200f..4d878ad6c3 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppServiceBase.cs @@ -12,7 +12,7 @@ namespace Volo.Abp.Application.Services /// This is a common base class for CrudAppService and AsyncCrudAppService classes. /// Inherit either from CrudAppService or AsyncCrudAppService, not from this class. /// - public abstract class CrudAppServiceBase : + public abstract class CrudAppServiceBase : ApplicationService where TEntity : class, IEntity where TEntityDto : IEntityDto @@ -21,7 +21,7 @@ namespace Volo.Abp.Application.Services protected virtual string GetPolicyName { get; set; } - protected virtual string GetAllPolicyName { get; set; } + protected virtual string GetListPolicyName { get; set; } protected virtual string CreatePolicyName { get; set; } @@ -39,7 +39,7 @@ namespace Volo.Abp.Application.Services /// /// The query. /// The input. - protected virtual IQueryable ApplySorting(IQueryable query, TGetAllInput input) + protected virtual IQueryable ApplySorting(IQueryable query, TGetListInput input) { //Try to sort query if available var sortInput = input as ISortedResultRequest; @@ -66,7 +66,7 @@ namespace Volo.Abp.Application.Services /// /// The query. /// The input. - protected virtual IQueryable ApplyPaging(IQueryable query, TGetAllInput input) + protected virtual IQueryable ApplyPaging(IQueryable query, TGetListInput input) { //Try to use paging if available var pagedInput = input as IPagedResultRequest; @@ -93,7 +93,7 @@ namespace Volo.Abp.Application.Services /// methods. /// /// The input. - protected virtual IQueryable CreateFilteredQuery(TGetAllInput input) + protected virtual IQueryable CreateFilteredQuery(TGetListInput input) { return Repository; } diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs index 9f06c63aea..7e8b96b9f8 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ICrudAppService.cs @@ -29,7 +29,7 @@ namespace Volo.Abp.Application.Services { TEntityDto Get(TKey id); - PagedResultDto GetAll(TGetListInput input); + PagedResultDto GetList(TGetListInput input); TEntityDto Create(TCreateInput input); diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs index aa2a6e1c8f..d5f0a7dc2d 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityEto.cs @@ -5,6 +5,8 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed [Serializable] public class EntityEto : EtoBase { + public string EntityType { get; set; } + public string KeysAsString { get; set; } public EntityEto() @@ -12,8 +14,9 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed } - public EntityEto(string keysAsString) + public EntityEto(string entityType, string keysAsString) { + EntityType = entityType; KeysAsString = keysAsString; } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs index 354f72dddc..5b386599ef 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs @@ -1,6 +1,5 @@ -using System; +using Microsoft.Extensions.Options; using System.Collections.Generic; -using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.DynamicProxy; using Volo.Abp.EventBus.Distributed; @@ -28,7 +27,7 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed var entity = entityObj as IEntity; if (entity == null) { - throw new ArgumentException($"{nameof(entityObj)} should be an entity and implement the '{typeof(IEntity).AssemblyQualifiedName}' interface!"); + return null; } var entityType = ProxyHelper.UnProxy(entity).GetType(); @@ -36,10 +35,10 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed if (etoType == null) { var keys = entity.GetKeys().JoinAsString(","); - return new EntityEto(keys); + return new EntityEto(entityType.FullName, keys); } - //TODO: Also add KeysAsString property to resulting json for compability with the EntityEto! + //TODO: Also add KeysAsString property to resulting json for compatibility with the EntityEto! return ObjectMapper.Map(entityType, etoType, entityObj); } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs index e33e6751e8..ceefb311ef 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IEntityToEtoMapper.cs @@ -1,7 +1,10 @@ -namespace Volo.Abp.Domain.Entities.Events.Distributed +using JetBrains.Annotations; + +namespace Volo.Abp.Domain.Entities.Events.Distributed { public interface IEntityToEtoMapper { + [CanBeNull] object Map(object entityObj); } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs index dc4edea364..c9219feffc 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs @@ -48,35 +48,95 @@ namespace Volo.Abp.Domain.Entities.Events public virtual async Task TriggerEntityCreatingEventAsync(object entity) { - await TriggerEventWithEntity(LocalEventBus, typeof(EntityCreatingEventData<>), entity, true); + await TriggerEventWithEntity( + LocalEventBus, + typeof(EntityCreatingEventData<>), + entity, + true + ); } public virtual async Task TriggerEntityCreatedEventOnUowCompletedAsync(object entity) { - await TriggerEventWithEntity(LocalEventBus, typeof(EntityCreatedEventData<>), entity, false); - await TriggerEventWithEntity(DistributedEventBus, typeof(EntityCreatedEto<>), EntityToEtoMapper.Map(entity), false); + await TriggerEventWithEntity( + LocalEventBus, + typeof(EntityCreatedEventData<>), + entity, + false + ); + + var eto = EntityToEtoMapper.Map(entity); + if (eto != null) + { + await TriggerEventWithEntity( + DistributedEventBus, + typeof(EntityCreatedEto<>), + eto, + false + ); + } } public virtual async Task TriggerEntityUpdatingEventAsync(object entity) { - await TriggerEventWithEntity(LocalEventBus, typeof(EntityUpdatingEventData<>), entity, true); + await TriggerEventWithEntity( + LocalEventBus, + typeof(EntityUpdatingEventData<>), + entity, + true + ); } public virtual async Task TriggerEntityUpdatedEventOnUowCompletedAsync(object entity) { - await TriggerEventWithEntity(LocalEventBus, typeof(EntityUpdatedEventData<>), entity, false); - await TriggerEventWithEntity(DistributedEventBus, typeof(EntityUpdatedEto<>), EntityToEtoMapper.Map(entity), false); + await TriggerEventWithEntity( + LocalEventBus, + typeof(EntityUpdatedEventData<>), + entity, + false + ); + + var eto = EntityToEtoMapper.Map(entity); + if (eto != null) + { + await TriggerEventWithEntity( + DistributedEventBus, + typeof(EntityUpdatedEto<>), + eto, + false + ); + } } public virtual async Task TriggerEntityDeletingEventAsync(object entity) { - await TriggerEventWithEntity(LocalEventBus, typeof(EntityDeletingEventData<>), entity, true); + await TriggerEventWithEntity( + LocalEventBus, + typeof(EntityDeletingEventData<>), + entity, + true + ); } public virtual async Task TriggerEntityDeletedEventOnUowCompletedAsync(object entity) { - await TriggerEventWithEntity(LocalEventBus, typeof(EntityDeletedEventData<>), entity, false); - await TriggerEventWithEntity(DistributedEventBus, typeof(EntityDeletedEto<>), EntityToEtoMapper.Map(entity), false); + await TriggerEventWithEntity( + LocalEventBus, + typeof(EntityDeletedEventData<>), + entity, + false + ); + + var eto = EntityToEtoMapper.Map(entity); + if (eto != null) + { + await TriggerEventWithEntity( + DistributedEventBus, + typeof(EntityDeletedEto<>), + EntityToEtoMapper.Map(entity), + false + ); + } } protected virtual async Task TriggerEventsInternalAsync(EntityChangeReport changeReport) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/DomainService.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/DomainService.cs index ea94690d61..14e8a64131 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/DomainService.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/DomainService.cs @@ -1,4 +1,5 @@ using System; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Guids; @@ -9,13 +10,34 @@ namespace Volo.Abp.Domain.Services { public abstract class DomainService : IDomainService { - public IClock Clock { get; set; } + public IServiceProvider ServiceProvider { get; set; } + protected readonly object ServiceProviderLock = new object(); + protected TService LazyGetRequiredService(ref TService reference) + { + if (reference == null) + { + lock (ServiceProviderLock) + { + if (reference == null) + { + reference = ServiceProvider.GetRequiredService(); + } + } + } + + return reference; + } + + public IClock Clock => LazyGetRequiredService(ref _clock); + private IClock _clock; public IGuidGenerator GuidGenerator { get; set; } - public ILoggerFactory LoggerFactory { get; set; } + public ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); + private ILoggerFactory _loggerFactory; - public ICurrentTenant CurrentTenant { get; set; } + public ICurrentTenant CurrentTenant => LazyGetRequiredService(ref _currentTenant); + private ICurrentTenant _currentTenant; protected ILogger Logger => _lazyLogger.Value; private Lazy _lazyLogger => new Lazy(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj index 5b33186509..2f5cdfb4fb 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj new file mode 100644 index 0000000000..cf6dad2b43 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj @@ -0,0 +1,24 @@ + + + + + + netstandard2.0 + Volo.Abp.EntityFrameworkCore.Sqlite + Volo.Abp.EntityFrameworkCore.Sqlite + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + + + + + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs new file mode 100644 index 0000000000..6fd69fa42e --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs @@ -0,0 +1,25 @@ +using System; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Volo.Abp.EntityFrameworkCore.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore +{ + public static class AbpDbContextConfigurationContextSqliteExtensions + { + public static DbContextOptionsBuilder UseSqlite( + [NotNull] this AbpDbContextConfigurationContext context, + [CanBeNull] Action sqliteOptionsAction = null) + { + if (context.ExistingConnection != null) + { + return context.DbContextOptions.UseSqlite(context.ExistingConnection, sqliteOptionsAction); + } + else + { + return context.DbContextOptions.UseSqlite(context.ConnectionString, sqliteOptionsAction); + } + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsSqliteExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsSqliteExtensions.cs new file mode 100644 index 0000000000..68944194d1 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsSqliteExtensions.cs @@ -0,0 +1,30 @@ +using System; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Volo.Abp.EntityFrameworkCore +{ + public static class AbpDbContextOptionsSqliteExtensions + { + public static void UseSqlite( + [NotNull] this AbpDbContextOptions options, + [CanBeNull] Action sqliteOptionsAction = null) + { + options.Configure(context => + { + context.UseSqlite(sqliteOptionsAction); + }); + } + + public static void UseSqlite( + [NotNull] this AbpDbContextOptions options, + [CanBeNull] Action sqliteOptionsAction = null) + where TDbContext : AbpDbContext + { + options.Configure(context => + { + context.UseSqlite(sqliteOptionsAction); + }); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/Sqlite/AbpEntityFrameworkCoreSqliteModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/Sqlite/AbpEntityFrameworkCoreSqliteModule.cs new file mode 100644 index 0000000000..8be6927e79 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/Sqlite/AbpEntityFrameworkCoreSqliteModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.EntityFrameworkCore.Sqlite +{ + [DependsOn( + typeof(AbpEntityFrameworkCoreModule) + )] + public class AbpEntityFrameworkCoreSqliteModule : AbpModule + { + + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj index 65dda178a5..bfbf0cdf49 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj b/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj index 12084177a9..fe8a6a4192 100644 --- a/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj +++ b/framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationModule.cs b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationModule.cs index bbd5d2c888..ffe6162197 100644 --- a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationModule.cs +++ b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationModule.cs @@ -13,13 +13,5 @@ namespace Volo.Abp.FluentValidation { context.Services.AddConventionalRegistrar(new AbpFluentValidationConventionalRegistrar()); } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.MethodValidationContributors.Add(); - }); - } } } diff --git a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentMethodInvocationValidator.cs b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentMethodInvocationValidator.cs deleted file mode 100644 index 0868093181..0000000000 --- a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentMethodInvocationValidator.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using FluentValidation; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Validation; - -namespace Volo.Abp.FluentValidation -{ - public class FluentMethodInvocationValidator : IMethodInvocationValidator, ITransientDependency - { - private readonly IServiceProvider _serviceProvider; - - public FluentMethodInvocationValidator( - IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public void Validate(MethodInvocationValidationContext context) - { - var validationResult = new AbpValidationResult(); - - foreach (var parameterValue in context.ParameterValues) - { - var serviceType = typeof(IValidator<>).MakeGenericType(parameterValue.GetType()); - var validator = _serviceProvider.GetService(serviceType) as IValidator; - if (validator == null) - { - continue; - } - - var result = validator.Validate(parameterValue); - if (!result.IsValid) - { - validationResult.Errors.AddRange( - result.Errors.Select( - error => - new ValidationResult(error.ErrorMessage) - ) - ); - } - } - - if (validationResult.Errors.Any()) - { - //TODO: How to localize messages? - throw new AbpValidationException( - "Method arguments are not valid! See ValidationErrors for details.", - context.Errors - ); - } - } - } -} diff --git a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs new file mode 100644 index 0000000000..f926782e2d --- /dev/null +++ b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs @@ -0,0 +1,41 @@ +using FluentValidation; +using System; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Validation; + +namespace Volo.Abp.FluentValidation +{ + public class FluentObjectValidationContributor : IObjectValidationContributor, ITransientDependency + { + private readonly IServiceProvider _serviceProvider; + + public FluentObjectValidationContributor( + IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public void AddErrors(ObjectValidationContext context) + { + var serviceType = typeof(IValidator<>).MakeGenericType(context.ValidatingObject.GetType()); + var validator = _serviceProvider.GetService(serviceType) as IValidator; + if (validator == null) + { + return; + } + + var result = validator.Validate(context.ValidatingObject); + if (!result.IsValid) + { + context.Errors.AddRange( + result.Errors.Select( + error => + new ValidationResult(error.ErrorMessage) + ) + ); + } + } + } +} diff --git a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj index e418ca03e5..e4b9db1c7b 100644 --- a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj +++ b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj index d16fac5ba0..fcfff3fcb5 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj +++ b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj b/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj index 39b92cc428..8964f2f4fe 100644 --- a/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj +++ b/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj b/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj index b429defa2d..65ceed101e 100644 --- a/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj +++ b/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj index f2f59a9a64..9492e6fbf3 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj +++ b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionOptions.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionOptions.cs index 91768d37e8..67eae167c3 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionOptions.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionOptions.cs @@ -15,7 +15,7 @@ namespace Volo.Abp.Security.Encryption /// /// Default password to encrypt/decrypt texts. - /// It's recommented to set to another value for security. + /// It's recommended to set to another value for security. /// Default value: "gsKnGZ041HLL4IM8" /// public string DefaultPassPhrase { get; set; } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/zh-Hans.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/zh-Hans.json new file mode 100644 index 0000000000..bfac148af4 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "culture": "zh-Hans", + "texts": { + "Menu:Administration": "管理" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs index 4218a9693f..df867c2320 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs @@ -9,7 +9,7 @@ namespace Volo.Abp.Uow public class UnitOfWorkFailedEventArgs : UnitOfWorkEventArgs { /// - /// Exception that caused failure. This is set only if an error occured during . + /// Exception that caused failure. This is set only if an error occurred during . /// Can be null if there is no exception, but is not called. /// Can be null if another exception occurred during the UOW. /// diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationModule.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationModule.cs index f47594a88a..bb2d41f927 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationModule.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationModule.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; namespace Volo.Abp.Validation @@ -8,13 +10,24 @@ namespace Volo.Abp.Validation public override void PreConfigureServices(ServiceConfigurationContext context) { context.Services.OnRegistred(ValidationInterceptorRegistrar.RegisterIfNeeded); + AutoAddObjectValidationContributors(context.Services); } - public override void ConfigureServices(ServiceConfigurationContext context) + private static void AutoAddObjectValidationContributors(IServiceCollection services) { - Configure(options => + var contributorTypes = new List(); + + services.OnRegistred(context => + { + if (typeof(IObjectValidationContributor).IsAssignableFrom(context.ImplementationType)) + { + contributorTypes.Add(context.ImplementationType); + } + }); + + services.Configure(options => { - options.MethodValidationContributors.Add(); + options.ObjectValidationContributors.AddIfNotContains(contributorTypes); }); } } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationOptions.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationOptions.cs index c88449da1a..d9a690181e 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationOptions.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/AbpValidationOptions.cs @@ -8,12 +8,12 @@ namespace Volo.Abp.Validation { public List IgnoredTypes { get; } - public ITypeList MethodValidationContributors { get; set; } + public ITypeList ObjectValidationContributors { get; set; } public AbpValidationOptions() { IgnoredTypes = new List(); - MethodValidationContributors = new TypeList(); + ObjectValidationContributors = new TypeList(); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs new file mode 100644 index 0000000000..5598fe7827 --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs @@ -0,0 +1,122 @@ +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Reflection; + +namespace Volo.Abp.Validation +{ + public class DataAnnotationObjectValidationContributor : IObjectValidationContributor, ITransientDependency + { + public const int MaxRecursiveParameterValidationDepth = 8; + + protected AbpValidationOptions Options { get; } + + public DataAnnotationObjectValidationContributor(IOptions options) + { + Options = options.Value; + } + + public void AddErrors(ObjectValidationContext context) + { + ValidateObjectRecursively(context.Errors, context.ValidatingObject, currentDepth: 1); + } + + protected virtual void ValidateObjectRecursively(List errors, object validatingObject, int currentDepth) + { + if (currentDepth > MaxRecursiveParameterValidationDepth) + { + return; + } + + if (validatingObject == null) + { + return; + } + + AddErrors(errors, validatingObject); + + //Validate items of enumerable + if (validatingObject is IEnumerable) + { + if (!(validatingObject is IQueryable)) + { + foreach (var item in (validatingObject as IEnumerable)) + { + ValidateObjectRecursively(errors, item, currentDepth + 1); + } + } + + return; + } + + var validatingObjectType = validatingObject.GetType(); + + //Do not recursively validate for primitive objects + if (TypeHelper.IsPrimitiveExtended(validatingObjectType)) + { + return; + } + + if (Options.IgnoredTypes.Any(t => t.IsInstanceOfType(validatingObject))) + { + return; + } + + var properties = TypeDescriptor.GetProperties(validatingObject).Cast(); + foreach (var property in properties) + { + if (property.Attributes.OfType().Any()) + { + continue; + } + + ValidateObjectRecursively(errors, property.GetValue(validatingObject), currentDepth + 1); + } + } + + public void AddErrors(List errors, object validatingObject) + { + var properties = TypeDescriptor.GetProperties(validatingObject).Cast(); + + foreach (var property in properties) + { + AddPropertyErrors(validatingObject, property, errors); + } + + if (validatingObject is IValidatableObject validatableObject) + { + errors.AddRange( + validatableObject.Validate(new ValidationContext(validatableObject)) + ); + } + } + + protected virtual void AddPropertyErrors(object validatingObject, PropertyDescriptor property, List errors) + { + var validationAttributes = property.Attributes.OfType().ToArray(); + if (validationAttributes.IsNullOrEmpty()) + { + return; + } + + var validationContext = new ValidationContext(validatingObject) + { + DisplayName = property.DisplayName, + MemberName = property.Name + }; + + foreach (var attribute in validationAttributes) + { + var result = attribute.GetValidationResult(property.GetValue(validatingObject), validationContext); + if (result != null) + { + errors.Add(result); + } + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationValidator.cs deleted file mode 100644 index 3333354937..0000000000 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationValidator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using Volo.Abp.DependencyInjection; - -namespace Volo.Abp.Validation -{ - public class DataAnnotationValidator : IDataAnnotationValidator, ITransientDependency - { - public void Validate(object validatingObject) - { - var errors = GetErrors(validatingObject); - - if (errors.Any()) - { - throw new AbpValidationException( - "Object state is not valid! See ValidationErrors for details.", - errors - ); - } - } - - /// - /// Gets all errors from properties for DataAnnotations attributes and IValidatableObject interface. - /// - public virtual List GetErrors(object validatingObject) - { - var errors = new List(); - var properties = TypeDescriptor.GetProperties(validatingObject).Cast(); - - foreach (var property in properties) - { - AddPropertyErrors(validatingObject, property, errors); - } - - if (validatingObject is IValidatableObject validatableObject) - { - errors.AddRange( - validatableObject.Validate(new ValidationContext(validatableObject)) - ); - } - - return errors; - } - - protected virtual void AddPropertyErrors(object validatingObject, PropertyDescriptor property, List errors) - { - var validationAttributes = property.Attributes.OfType().ToArray(); - if (validationAttributes.IsNullOrEmpty()) - { - return; - } - - var validationContext = new ValidationContext(validatingObject) - { - DisplayName = property.DisplayName, - MemberName = property.Name - }; - - foreach (var attribute in validationAttributes) - { - var result = attribute.GetValidationResult(property.GetValue(validatingObject), validationContext); - if (result != null) - { - errors.Add(result); - } - } - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IDataAnnotationValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IDataAnnotationValidator.cs deleted file mode 100644 index 6b14ff66b6..0000000000 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IDataAnnotationValidator.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace Volo.Abp.Validation -{ - public interface IDataAnnotationValidator - { - void Validate(object validatingObject); - - List GetErrors(object validatingObject); - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs new file mode 100644 index 0000000000..ca50901bcd --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Validation +{ + public interface IObjectValidationContributor + { + void AddErrors(ObjectValidationContext context); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs index 8388605e62..0ce723bab8 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs @@ -11,6 +11,10 @@ namespace Volo.Abp.Validation bool allowNull = false ); - List GetErrors(object validatingObject, string name = null, bool allowNull = false); + List GetErrors( + object validatingObject, + string name = null, + bool allowNull = false + ); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidationContext.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidationContext.cs new file mode 100644 index 0000000000..f2e9cd215c --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidationContext.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; + +namespace Volo.Abp.Validation +{ + public class ObjectValidationContext + { + [NotNull] + public object ValidatingObject { get; } + + public List Errors { get; } + + public ObjectValidationContext([NotNull] object validatingObject) + { + ValidatingObject = Check.NotNull(validatingObject, nameof(validatingObject)); + Errors = new List(); + } + } +} diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs index 2d92af7221..8ff3998f7e 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs @@ -1,25 +1,21 @@ -using System.Collections; +using Microsoft.Extensions.Options; using System.Collections.Generic; -using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; -using Microsoft.Extensions.Options; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; -using Volo.Abp.Reflection; namespace Volo.Abp.Validation { public class ObjectValidator : IObjectValidator, ITransientDependency { - private const int MaxRecursiveParameterValidationDepth = 8; + protected IHybridServiceScopeFactory ServiceScopeFactory { get; } + protected AbpValidationOptions Options { get; } - private readonly AbpValidationOptions _options; - private readonly IDataAnnotationValidator _dataAnnotationValidator; - - public ObjectValidator(IOptions options, IDataAnnotationValidator dataAnnotationValidator) + public ObjectValidator(IOptions options, IHybridServiceScopeFactory serviceScopeFactory) { - _dataAnnotationValidator = dataAnnotationValidator; - _options = options.Value; + ServiceScopeFactory = serviceScopeFactory; + Options = options.Value; } public virtual void Validate(object validatingObject, string name = null, bool allowNull = false) @@ -37,75 +33,35 @@ namespace Volo.Abp.Validation public virtual List GetErrors(object validatingObject, string name = null, bool allowNull = false) { - var errors = new List(); - - if (validatingObject == null && !allowNull) - { - errors.Add( - name == null - ? new ValidationResult("Given object is null!") - : new ValidationResult(name + " is null!", new[] { name }) - ); - - return errors; - } - - ValidateObjectRecursively(errors, validatingObject, currentDepth: 1); - - return errors; - } - - protected virtual void ValidateObjectRecursively(List errors, object validatingObject, int currentDepth) - { - if (currentDepth > MaxRecursiveParameterValidationDepth) - { - return; - } - if (validatingObject == null) { - return; - } - - errors.AddRange(_dataAnnotationValidator.GetErrors(validatingObject)); - - //Validate items of enumerable - if (validatingObject is IEnumerable) - { - if (!(validatingObject is IQueryable)) + if (allowNull) { - foreach (var item in (validatingObject as IEnumerable)) + return new List(); //TODO: Returning an array would be more performent + } + else + { + return new List { - ValidateObjectRecursively(errors, item, currentDepth + 1); - } + name == null + ? new ValidationResult("Given object is null!") + : new ValidationResult(name + " is null!", new[] {name}) + }; } - - return; } - var validatingObjectType = validatingObject.GetType(); + var context = new ObjectValidationContext(validatingObject); - //Do not recursively validate for primitive objects - if (TypeHelper.IsPrimitiveExtended(validatingObjectType)) + using (var scope = ServiceScopeFactory.CreateScope()) { - return; - } - - if (_options.IgnoredTypes.Any(t => t.IsInstanceOfType(validatingObject))) - { - return; - } - - var properties = TypeDescriptor.GetProperties(validatingObject).Cast(); - foreach (var property in properties) - { - if (property.Attributes.OfType().Any()) + foreach (var contributorType in Options.ObjectValidationContributors) { - continue; + var contributor = (IObjectValidationContributor) scope.ServiceProvider.GetRequiredService(contributorType); + contributor.AddErrors(context); } - - ValidateObjectRecursively(errors, property.GetValue(validatingObject), currentDepth + 1); } + + return context.Errors; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs index 3b5d519c0c..c7fedec8db 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs @@ -1,7 +1,7 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using System; +using System.Threading.Tasks; using Volo.Abp.Aspects; using Volo.Abp.DependencyInjection; using Volo.Abp.DynamicProxy; @@ -10,13 +10,11 @@ namespace Volo.Abp.Validation { public class ValidationInterceptor : AbpInterceptor, ITransientDependency { - private readonly AbpValidationOptions _abpValidationOptions; - private readonly IServiceProvider _serviceProvider; + private readonly IMethodInvocationValidator _methodInvocationValidator; - public ValidationInterceptor(IServiceProvider serviceProvider, IOptions abpValidationOptions) + public ValidationInterceptor(IMethodInvocationValidator methodInvocationValidator) { - _serviceProvider = serviceProvider; - _abpValidationOptions = abpValidationOptions.Value; + _methodInvocationValidator = methodInvocationValidator; } public override void Intercept(IAbpMethodInvocation invocation) @@ -47,18 +45,13 @@ namespace Volo.Abp.Validation protected virtual void Validate(IAbpMethodInvocation invocation) { - foreach (var validationContributor in _abpValidationOptions.MethodValidationContributors) - { - var validator = (IMethodInvocationValidator) _serviceProvider.GetRequiredService(validationContributor); - - validator.Validate( - new MethodInvocationValidationContext( - invocation.TargetObject, - invocation.Method, - invocation.Arguments - ) - ); - } + _methodInvocationValidator.Validate( + new MethodInvocationValidationContext( + invocation.TargetObject, + invocation.Method, + invocation.Arguments + ) + ); } } } diff --git a/framework/test/AbpTestBase/AbpTestBase.csproj b/framework/test/AbpTestBase/AbpTestBase.csproj index 5e9761d304..4a25e99676 100644 --- a/framework/test/AbpTestBase/AbpTestBase.csproj +++ b/framework/test/AbpTestBase/AbpTestBase.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj index 1ca29422b9..806e426f82 100644 --- a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj index b7ba4ddd36..b0d3baaad9 100644 --- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj index 551dfd9f2a..bd0a8c1ca0 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj @@ -21,7 +21,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController.cs index b9d01a86c4..6bb9a5ae94 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Shouldly; @@ -16,6 +17,14 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation return Task.FromResult(model.Value1); } + [HttpGet] + [Route("object-result-action-with-custom_validate")] + public Task ObjectResultActionWithCustomValidate(CustomValidateModel model) + { + ModelState.IsValid.ShouldBeTrue(); //AbpValidationFilter throws exception otherwise + return Task.FromResult(model.Value1); + } + [HttpGet] [Route("action-result-action")] public IActionResult ActionResultAction(ValidationTest1Model model) @@ -29,5 +38,19 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation [MinLength(2)] public string Value1 { get; set; } } + + public class CustomValidateModel : IValidatableObject + { + public string Value1 { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (Value1 != "hello") + { + yield return new ValidationResult("Value1 should be hello"); + } + } + } + } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController_Tests.cs index 19a4bcd608..5177868843 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Validation/ValidationTestController_Tests.cs @@ -47,5 +47,16 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation var result = await GetResponseAsStringAsync("/api/validation-test/action-result-action"); //Missed the value1 result.ShouldBe("ModelState.IsValid: false"); } + + [Fact] + public async Task Should_Return_Custom_Validate_Errors() + { + var result = await GetResponseAsObjectAsync( + "/api/validation-test/object-result-action-with-custom_validate?value1=abc", HttpStatusCode.BadRequest); //value1 should be hello. + + result.Error.ValidationErrors.Length.ShouldBeGreaterThan(0); + result.Error.ValidationErrors.ShouldContain(x => x.Message == "Value1 should be hello"); + } + } } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj index 9d5b607bfd..a25b7d7d8f 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj @@ -20,7 +20,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj index 3b6d429dd0..dd5e36ed14 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj @@ -17,9 +17,9 @@ - - - + + + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj index 7ee7949c19..74c0285f34 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj index 7ffebd4224..d32284ed87 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/AbpAspNetCoreMvcVersioningTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/AbpAspNetCoreMvcVersioningTestModule.cs index 728b119a19..24a76e3766 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/AbpAspNetCoreMvcVersioningTestModule.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/AbpAspNetCoreMvcVersioningTestModule.cs @@ -27,7 +27,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning opts.ApiVersions.Add(new ApiVersion(2, 0)); }); - //1.0 Compatability version + //1.0 Compatibility version options.ConventionalControllers.Create(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly, opts => { opts.TypePredicate = t => t.Namespace == typeof(Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat.TodoAppService).Namespace; diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj index 7ade7ea81b..9c7544a2f6 100644 --- a/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj b/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj index 35b66f5bfe..cb099c5168 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AuditingInterceptor_Tests.cs b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AuditingInterceptor_Tests.cs index 141bf01688..23eba6c53b 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AuditingInterceptor_Tests.cs +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AuditingInterceptor_Tests.cs @@ -37,7 +37,7 @@ namespace Volo.Abp.Auditing using (var scope = _auditingManager.BeginScope()) { - await myAuditedObject1.DoItAsync(new InputObject { Value1 = "fourty-two", Value2 = 42 }); + await myAuditedObject1.DoItAsync(new InputObject { Value1 = "forty-two", Value2 = 42 }); await scope.SaveAsync(); } diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj index 160262de19..88925bb67d 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj index 1f2757b34e..9eb89d4af9 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj b/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj index 26a16f83cc..c92d40f8be 100644 --- a/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj +++ b/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj index 8c6a8170b8..7fa0474264 100644 --- a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj +++ b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj b/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj index 49f5d2454a..2b4696092c 100644 --- a/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj +++ b/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj b/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj index c96b26d272..c5a45236c2 100644 --- a/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj +++ b/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/AbpConventionalDependencyInjectionExtensions_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/AbpConventionalDependencyInjectionExtensions_Tests.cs index 369ee98cb9..dc02cf4e2d 100644 --- a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/AbpConventionalDependencyInjectionExtensions_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/AbpConventionalDependencyInjectionExtensions_Tests.cs @@ -85,7 +85,7 @@ namespace Microsoft.Extensions.DependencyInjection //Assert - //Check descriptons in service collection + //Check descriptions in service collection var descriptions = _services.Where(s => s.ServiceType == typeof(IMyService)).ToList(); descriptions.Count.ShouldBe(2); descriptions[0].ImplementationType.ShouldBe(typeof(FirstImplOfMyService)); @@ -113,7 +113,7 @@ namespace Microsoft.Extensions.DependencyInjection //Assert - //Check descriptons in service collection + //Check descriptions in service collection var descriptions = _services.Where(s => s.ServiceType == typeof(IMyService)).ToList(); descriptions.Count.ShouldBe(1); descriptions[0].ImplementationType.ShouldBe(typeof(FirstImplOfMyService)); @@ -139,7 +139,7 @@ namespace Microsoft.Extensions.DependencyInjection //Assert - //Check descriptons in service collection + //Check descriptions in service collection var descriptions = _services.Where(s => s.ServiceType == typeof(IMyService)).ToList(); descriptions.Count.ShouldBe(1); descriptions[0].ImplementationType.ShouldBe(typeof(MyServiceReplacesIMyService)); diff --git a/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj b/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj index f043c10c13..bd58cb0d71 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj +++ b/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/ReflectionHelper_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/ReflectionHelper_Tests.cs index 842940cfaf..333ea2e84a 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/ReflectionHelper_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/ReflectionHelper_Tests.cs @@ -1,7 +1,102 @@ -namespace Volo.Abp.Reflection +using System.Linq; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Reflection { public class ReflectionHelper_Tests { //TODO: ... + + + [Fact] + public void GetPublicConstantsRecursively_Test() + { + var constants = ReflectionHelper.GetPublicConstantsRecursively(typeof(BaseRole)); + + constants.ShouldNotBeEmpty(); + constants.Length.ShouldBe(1); + constants.ShouldContain(x => x == "DefaultBaseRoleName"); + } + + [Fact] + public void GetPublicConstantsRecursively_Inherit_Test() + { + var constants = ReflectionHelper.GetPublicConstantsRecursively(typeof(Roles)); + + constants.ShouldNotBeEmpty(); + constants.Length.ShouldBe(2); + constants.ShouldContain(x => x == "DefaultBaseRoleName"); + constants.ShouldContain(x => x == "DefaultRoleName"); + } + + + [Fact] + public void GetPublicConstantsRecursively_NestedTypes_Test() + { + var constants = ReflectionHelper.GetPublicConstantsRecursively(typeof(IdentityPermissions)); + + constants.ShouldNotBeEmpty(); + constants.Except(IdentityPermissions.GetAll()).Count().ShouldBe(0); + } } -} + + + public class BaseRole + { + public const string BaseRoleName = "DefaultBaseRoleName"; + } + + public class Roles : BaseRole + { + public const string RoleName = "DefaultRoleName"; + } + + public static class IdentityPermissions + { + public const string GroupName = "AbpIdentity"; + + public static class Roles + { + public const string Default = GroupName + ".Roles"; + public const string Create = Default + ".Create"; + public const string Update = Default + ".Update"; + public const string Delete = Default + ".Delete"; + public const string ManagePermissions = Default + ".ManagePermissions"; + } + + public static class Users + { + public const string Default = GroupName + ".Users"; + public const string Create = Default + ".Create"; + public const string Update = Default + ".Update"; + public const string Delete = Default + ".Delete"; + public const string ManagePermissions = Default + ".ManagePermissions"; + } + + public static class UserLookup + { + public const string Default = GroupName + ".UserLookup"; + } + + public static string[] GetAll() + { + return new[] + { + GroupName, + Roles.Default, + Roles.Create, + Roles.Update, + Roles.Delete, + Roles.ManagePermissions, + Users.Default, + Users.Create, + Users.Update, + Users.Delete, + Users.ManagePermissions, + UserLookup.Default + }; + } + } + +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj b/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj index 1cef1431c2..13c9cb2ef3 100644 --- a/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj +++ b/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj b/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj index ae203870fe..ad4141f96f 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj index 5083782360..32b4f25816 100644 --- a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj index 4162f8319b..3f32baa6aa 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj @@ -20,8 +20,8 @@ - - + + \ No newline at end of file diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj b/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj index dc8ab54f51..e810d5ef76 100644 --- a/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj +++ b/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj index 3632aa2bf3..ece1f124d5 100644 --- a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj +++ b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj b/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj index ab2f82eefa..b0bc864896 100644 --- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj +++ b/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs index 467a45a999..0cde05efd4 100644 --- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs +++ b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs @@ -101,8 +101,7 @@ namespace Volo.Abp.FluentValidation output.ShouldBe("444"); } - - + [DependsOn(typeof(AbpAutofacModule))] [DependsOn(typeof(AbpFluentValidationModule))] public class TestModule : AbpModule diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj b/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj index e0a8ea60de..4997863830 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj b/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj index f5b87ab423..98a01e2fc7 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj +++ b/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj b/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj index 0a61a38420..062cfaf730 100644 --- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj +++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj index f2508f81ca..5ca5401bac 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj @@ -19,8 +19,8 @@ - - + + \ No newline at end of file diff --git a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj index 6b18627f7e..631ad1ed81 100644 --- a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj +++ b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj b/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj index 7fabca78ba..5339246c52 100644 --- a/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj +++ b/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj b/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj index a9fe791822..99db6083c2 100644 --- a/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj +++ b/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj b/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj index 7f83c36c9a..1e9bd3f4a0 100644 --- a/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj +++ b/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj b/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj index e63096f8c4..3985910708 100644 --- a/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj +++ b/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/framework/test/Volo.Abp.TestApp.Tests/Volo/Abp/TestApp/Application/PersonAppService_Tests.cs b/framework/test/Volo.Abp.TestApp.Tests/Volo/Abp/TestApp/Application/PersonAppService_Tests.cs index 9dbfc8936e..c58b1b5f85 100644 --- a/framework/test/Volo.Abp.TestApp.Tests/Volo/Abp/TestApp/Application/PersonAppService_Tests.cs +++ b/framework/test/Volo.Abp.TestApp.Tests/Volo/Abp/TestApp/Application/PersonAppService_Tests.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.TestApp.Application } [Fact] - public async Task GetAll() + public async Task GetList() { var people = await _peopleAppService.GetListAsync(new PagedAndSortedResultRequestDto()); people.Items.Count.ShouldBeGreaterThan(0); diff --git a/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj b/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj index 243bd70a8c..0cb921f63a 100644 --- a/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj +++ b/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj index b308eae3a2..10318fbf90 100644 --- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj +++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj b/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj index 40575e7b1c..f3dede4b21 100644 --- a/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj +++ b/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj b/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj index 5891413963..60308b96ae 100644 --- a/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj +++ b/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs b/framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs index 3f7b49c8b4..8ff4aa8bfd 100644 --- a/framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs +++ b/framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.Validation public ApplicationService_Validation_Tests() { - _myAppService = ServiceProvider.GetRequiredService(); + _myAppService = GetRequiredService(); } protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) diff --git a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj index 7f0be985bf..895b8231ce 100644 --- a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj +++ b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.csproj b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.csproj index 247752f848..32ee40e070 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.csproj +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj index a080318e11..8134b0c512 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj @@ -6,7 +6,7 @@ - + diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj index c823e9a53a..3540aa8e9c 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj @@ -6,7 +6,10 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs index 0c18e9f877..c3684d9cfe 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs @@ -39,7 +39,7 @@ namespace Volo.Abp.BackgroundJobs public virtual DateTime? LastTryTime { get; set; } /// - /// This is true if this job is continously failed and will not be executed again. + /// This is true if this job is continuously failed and will not be executed again. /// public virtual bool IsAbandoned { get; set; } diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj index 07501ec85f..a8ff824305 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj index 6fad02af58..722d94f88e 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj index 00c9d6ffc2..f3fb433d10 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj index 9c9e420c65..1f4db1af41 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs index 248d1433cc..84ed5d1910 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs @@ -98,7 +98,7 @@ namespace Volo.BloggingTestApp options.CustomSchemaIds(type => type.FullName); }); - var cultures = new List { new CultureInfo("en"), new CultureInfo("tr") }; + var cultures = new List { new CultureInfo("en"), new CultureInfo("tr"),new CultureInfo("zh-Hans") }; Configure(options => { options.DefaultRequestCulture = new RequestCulture("en"); diff --git a/modules/blogging/app/Volo.BloggingTestApp/Branding/BloggingTestAppBrandingProvider.cs b/modules/blogging/app/Volo.BloggingTestApp/Branding/BloggingTestAppBrandingProvider.cs new file mode 100644 index 0000000000..e5a8046ff7 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/Branding/BloggingTestAppBrandingProvider.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Mvc.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components; +using Volo.Abp.DependencyInjection; +using Volo.Blogging.Localization; + +namespace Volo.BloggingTestApp.Branding +{ + [Dependency(ReplaceServices = true)] + public class BloggingTestAppBrandingProvider : DefaultBrandingProvider + { + public IHtmlLocalizer L { get; set; } + public BloggingTestAppBrandingProvider(IHtmlLocalizer localizer) + { + L = localizer; + } + public override string AppName => L["Blogs"].Value; + } +} diff --git a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj index 040cfaf4a8..7b88e297f4 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj +++ b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj @@ -16,7 +16,7 @@ - + diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissions.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissions.cs index e73dc334da..fae85acf88 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissions.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissions.cs @@ -1,4 +1,6 @@ -namespace Volo.Blogging +using Volo.Abp.Reflection; + +namespace Volo.Blogging { public class BloggingPermissions { @@ -39,27 +41,7 @@ public static string[] GetAll() { - return new[] - { - GroupName, - Blogs.Default, - Blogs.Management, - Blogs.Delete, - Blogs.Update, - Blogs.Create, - Posts.Default, - Posts.Delete, - Posts.Update, - Posts.Create, - Tags.Default, - Tags.Delete, - Tags.Update, - Tags.Create, - Comments.Default, - Comments.Delete, - Comments.Update, - Comments.Create - }; + return ReflectionHelper.GetPublicConstantsRecursively(typeof(BloggingPermissions)); } } } diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs index d8b9273f0c..b188fe4c3e 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs @@ -23,6 +23,17 @@ namespace Volo.Blogging.Files { Check.NotNullOrWhiteSpace(name, nameof(name)); + if (!Directory.Exists(Options.FileUploadLocalFolder)) + { + Directory.CreateDirectory(Options.FileUploadLocalFolder); + return Task.FromResult( + new RawFileDto + { + Bytes = new byte[0] + } + ); + } + var filePath = Path.Combine(Options.FileUploadLocalFolder, name); return Task.FromResult( @@ -53,6 +64,11 @@ namespace Volo.Blogging.Files var uniqueFileName = GenerateUniqueFileName(Path.GetExtension(input.Name)); var filePath = Path.Combine(Options.FileUploadLocalFolder, uniqueFileName); + if (!Directory.Exists(Options.FileUploadLocalFolder)) + { + Directory.CreateDirectory(Options.FileUploadLocalFolder); + } + File.WriteAllBytes(filePath, input.Bytes); //TODO: Previously was using WriteAllBytesAsync, but it's only in .netcore. return Task.FromResult(new FileUploadOutputDto diff --git a/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs b/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs index ac7cc9e210..20678ddc37 100644 --- a/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs +++ b/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; +using Localization.Resources.AbpUi; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; @@ -44,10 +45,13 @@ namespace Volo.Blogging Configure(options => { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Resources .Get() .AddBaseTypes(typeof(AbpValidationResource)) - .AddBaseTypes(typeof(AbpUiModule)) + .AddBaseTypes(typeof(AbpUiResource)) .AddVirtualJson("/Localization/Resources/Blogging/Web"); }); diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json index 444c3d80af..b84b1f2483 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json @@ -36,6 +36,12 @@ "CoverImage": "Cover Image", "CreateANewPost": "Create A New Post", "CreateANewBlog": "Create A New Blog", - "WhatIsNew": "What is new?" + "WhatIsNew": "What is new?", + "Name": "Name", + "ShortName": "Short Name", + "CreationTime": "Creation Time", + "Description": "Description", + "Blogs": "Blogs", + "Tags": "Tags" } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pt-BR.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pt-BR.json index cf98e56b06..62416f49a5 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pt-BR.json +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/pt-BR.json @@ -36,6 +36,12 @@ "CoverImage": "Imagem de Capa", "CreateANewPost": "Criar uma nova Postagem", "CreateANewBlog": "Criar um novo Blog", - "WhatIsNew": "O que há de novo?" + "WhatIsNew": "O que há de novo?", + "Name": "Nome", + "ShortName": "Nome Curto", + "CreationTime": "Hora da criação", + "Description": "Descrição", + "Blogs": "Blogs", + "Tags": "Etiquetas" } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json index dc5df7f0d0..7747638587 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json @@ -36,6 +36,12 @@ "CoverImage": "Kapak resmi", "CreateANewPost": "Yeni Yazı oluştur", "CreateANewBlog": "Yeni Blog Ekle", - "WhatIsNew": "Yeniler" + "WhatIsNew": "Yeniler", + "Name": "İsim", + "ShortName": "Kısa isim", + "CreationTime": "Oluşturulma zamanı", + "Description": "Açıklama", + "Blogs": "Bloglar", + "Tags": "Etiketler" } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/zh-Hans.json b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/zh-Hans.json index a67e325497..2ea614b648 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/zh-Hans.json +++ b/modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/zh-Hans.json @@ -36,6 +36,12 @@ "CoverImage": "封面图", "CreateANewPost": "创建一个新帖子", "CreateANewBlog": "创建一个新博客", - "WhatIsNew": "最新消息" - } - } \ No newline at end of file + "WhatIsNew": "最新消息", + "Name": "名称", + "ShortName": "简称", + "CreationTime": "创建时间", + "Description": "描述", + "Blogs": "博客", + "Tags": "标签" + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/BloggingPage.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/BloggingPage.cs index 03214d1ee3..88133e0e84 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/BloggingPage.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/BloggingPage.cs @@ -55,6 +55,11 @@ namespace Volo.Blogging.Pages.Blog public IHtmlContent RenderMarkdownToHtml(string content) { + if(content.IsNullOrWhiteSpace()) + { + return new HtmlString(""); + } + byte[] bytes = Encoding.Default.GetBytes(content); var utf8Content = Encoding.UTF8.GetString(bytes); diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Index.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Index.cshtml index fadaaab269..97f06b6dc0 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Index.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Index.cshtml @@ -1,12 +1,12 @@ @page @using Volo.Blogging.Pages.Blog -@*inherits BloggingPage*@ +@inherits BloggingPage @model IndexModel @{ ViewBag.PageTitle = "Blog"; }

- Blogs + @L["Blogs"]