Browse Source

Merge branch 'master' of https://github.com/volosoft/abp

pull/926/head
Alper Ebicoglu 7 years ago
parent
commit
51be90e9e8
  1. 2
      abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/Components/Header/Default.cshtml
  2. 1
      build-all.ps1
  3. 2
      common.props
  4. 10
      docs/en/Getting-Started-AspNetCore-MVC-Template.md
  5. 6
      docs/en/Tutorials/AspNetCore-Mvc/Part-I.md
  6. 2
      docs/en/Tutorials/AspNetCore-Mvc/Part-III.md
  7. BIN
      docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png
  8. BIN
      docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png
  9. BIN
      docs/en/images/bookstore-visual-studio-solution-v2.png
  10. BIN
      docs/en/images/pcm-update-database-v2.png
  11. 54
      docs/zh-Hans/Blog-Posts/2019-02-22/Post.md
  12. BIN
      docs/zh-Hans/Blog-Posts/2019-02-22/scott-and-jon.png
  13. 20
      docs/zh-Hans/Getting-Started-AspNetCore-Application.md
  14. 10
      docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md
  15. 1433
      docs/zh-Hans/Samples/Microservice-Demo.md
  16. 4
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
  17. 1
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md
  18. BIN
      docs/zh-Hans/images/bookstore-visual-studio-solution-v2.png
  19. BIN
      docs/zh-Hans/images/microservice-sample-authserver-home.png
  20. BIN
      docs/zh-Hans/images/microservice-sample-authserver-login.png
  21. BIN
      docs/zh-Hans/images/microservice-sample-backend-ui-permissions.png
  22. BIN
      docs/zh-Hans/images/microservice-sample-backend-ui.png
  23. BIN
      docs/zh-Hans/images/microservice-sample-blogservice-permission-in-database.png
  24. BIN
      docs/zh-Hans/images/microservice-sample-diagram-2.png
  25. BIN
      docs/zh-Hans/images/microservice-sample-kibana-1.png
  26. BIN
      docs/zh-Hans/images/microservice-sample-kibana-2.png
  27. BIN
      docs/zh-Hans/images/microservice-sample-product-module-in-solution.png
  28. BIN
      docs/zh-Hans/images/microservice-sample-public-product-list.png
  29. BIN
      docs/zh-Hans/images/microservice-sample-solution.png
  30. BIN
      docs/zh-Hans/images/pcm-update-database-v2.png
  31. 4
      framework/Volo.Abp.sln
  32. 2
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj
  33. 2
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs
  34. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs
  35. 16
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs
  36. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs
  37. 40
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs
  38. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributerBase.cs
  39. 9
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/ITenantResolveResultAccessor.cs
  40. 51
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
  41. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs
  42. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs
  43. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/tenant-switch.js
  44. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj
  45. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/AbpAspNetCoreMvcUiMultiTenancyModule.cs
  46. 17
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml
  47. 51
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/TenantSwitchViewComponent.cs
  48. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/_ViewImports.cshtml
  49. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json
  50. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json
  51. 21
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/MultiTenancyToolbarContributor.cs
  52. 2
      framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj
  53. 2
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingModule.cs
  54. 2
      framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj
  55. 2
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs
  56. 27
      framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataModule.cs
  57. 1
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataFilter.cs
  58. 48
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs
  59. 9
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContributorList.cs
  60. 12
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedOptions.cs
  61. 37
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeeder.cs
  62. 13
      framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeederExtensions.cs
  63. 9
      framework/src/Volo.Abp.Data/Volo/Abp/Data/IDataSeedContributor.cs
  64. 9
      framework/src/Volo.Abp.Data/Volo/Abp/Data/IDataSeeder.cs
  65. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
  66. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs
  67. 2
      framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj
  68. 2
      framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs
  69. 15
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AbpMultiTenancyAbstractionsModule.cs
  70. 21
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantIdAccessor.cs
  71. 30
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ConfigurationStore/ConfigurationTenantStore.cs
  72. 12
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ConfigurationStore/ConfigurationTenantStoreOptions.cs
  73. 34
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentTenant.cs
  74. 13
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ICurrentTenantIdAccessor.cs
  75. 18
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantIdWrapper.cs
  76. 4
      framework/src/Volo.Abp.MultiTenancy/Volo.Abp.MultiTenancy.csproj
  77. 21
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyModule.cs
  78. 8
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ActionTenantResolveContributor.cs
  79. 21
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs
  80. 27
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/BasicTenantInfo.cs
  81. 29
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs
  82. 12
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStoreOptions.cs
  83. 13
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs
  84. 36
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenant.cs
  85. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenantExtensions.cs
  86. 5
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenant.cs
  87. 12
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenantAccessor.cs
  88. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IMultiTenant.cs
  89. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContext.cs
  90. 2
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContributor.cs
  91. 4
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolver.cs
  92. 4
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantStore.cs
  93. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs
  94. 12
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyDatabaseStyle.cs
  95. 17
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptions.cs
  96. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs
  97. 10
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfiguration.cs
  98. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContext.cs
  99. 10
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContributorBase.cs
  100. 0
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs

2
abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/Components/Header/Default.cshtml

@ -23,7 +23,7 @@
<a class="nav-link" href="/blog/abp/">Blog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/abpframework/abp/" target="_blank">Github</a>
<a class="nav-link" href="https://github.com/abpframework/abp/" target="_blank">GitHub</a>
</li>
<li class="for-mobile">
<button type="button" class="close close-mmenu" aria-label="Close">

1
build-all.ps1

@ -9,6 +9,7 @@ $solutionPaths = (
"modules/users",
"modules/permission-management",
"modules/setting-management",
"modules/feature-management",
"modules/identity",
"modules/identityserver",
"modules/tenant-management",

2
common.props

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.14.0</Version>
<Version>0.15.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io</PackageProjectUrl>

10
docs/en/Getting-Started-AspNetCore-MVC-Template.md

@ -19,9 +19,9 @@ The downloaded project requires;
### The Solution Structure
Extract the zip file downloaded and open in **Visual Studio 2017 (15.7.0+)**:
Extract the zip file downloaded and open in **Visual Studio 2017 (15.9.0+)**:
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png)
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
The solution has a layered structure (based on Domain Driven Design) where;
@ -30,6 +30,8 @@ The solution has a layered structure (based on Domain Driven Design) where;
* ``.Web`` is the presentation layer.
* ``.EntityFrameworkCore`` is the EF Core integration package.
EF Core database migrations are separated to a project named `.EntityFrameworkCore.DbMigrations`.
The solution also contains unit & integration test projects properly configured to work with **EF Core** & **SQLite in-memory** database.
### Creating the Database
@ -50,9 +52,9 @@ Right click to the `.Web` project and select **Set as StartUp Project**:
![set-as-startup-project](images/set-as-startup-project.png)
Open the **Package Manager Console**, select `.EntityFrameworkCore` project as the **Default Project** and run the `Update-Database` command:
Open the **Package Manager Console**, select `.EntityFrameworkCore.DbMigrations` project as the **Default Project** and run the `Update-Database` command:
![pcm-update-database](images/pcm-update-database.png)
![pcm-update-database](images/pcm-update-database-v2.png)
This will create a new database based on the configured connection string.

6
docs/en/Tutorials/AspNetCore-Mvc/Part-I.md

@ -20,7 +20,7 @@ Go to the [startup template page](https://abp.io/Templates) and download a new p
This is the how the layered solution structure looks after it's created from the startup template:
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png)
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
### Create the Book Entity
@ -91,9 +91,9 @@ EF Core requires you to relate entities with your DbContext. The easiest way to
#### Add New Migration & Update the Database
The Startup template uses [EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) to create and maintain the database schema. Open the **Package Manager Console (PMC)** (under the *Tools/Nuget Package Manager* menu), select the `Acme.BookStore.EntityFrameworkCore` as the **default project** and execute the following command:
The Startup template uses [EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) to create and maintain the database schema. Open the **Package Manager Console (PMC)** (under the *Tools/Nuget Package Manager* menu), select the `Acme.BookStore.EntityFrameworkCore.DbMigrations` as the **default project** and execute the following command:
![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration.png)
![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration-v2.png)
This will create a new migration class inside the `Migrations` folder. Then execute the `Update-Database` command to update the database schema:

2
docs/en/Tutorials/AspNetCore-Mvc/Part-III.md

@ -14,8 +14,6 @@ You can download the **source code** of the application [from here](https://gith
There are two test projects in the solution:
![bookstore-test-projects](images/bookstore-test-projects.png)
* `Acme.BookStore.Application.Tests` is for unit & integration tests. You can write tests for application service methods. It uses **EF Core SQLite in-memory** database.
* `Acme.BookStore.Web.Tests` is for full stack integration tests including the web layer. So, you can write tests for UI pages too.

BIN
docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
docs/en/images/bookstore-visual-studio-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
docs/en/images/pcm-update-database-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

54
docs/zh-Hans/Blog-Posts/2019-02-22/Post.md

@ -0,0 +1,54 @@
# 微服务演示,项目状态和路线图
在ABP vNext上的[第一个公告](https://cn.abp.io/blog/abp/Abp-vNext-Announcement)之后,我们对代码库进行了很多改进([GitHub存储库](https://github.com/abpframework/abp)上的1100多次提交).我们已经创建了功能,示例,文档等等.在这篇文章中,我想告诉你一些新闻和项目的状态.
## 微服务演示解决方案
ABP框架的主要目标之一是提供[创建微服务解决方案的便利基础设施](https://cn.abp.io/documents/abp/latest/Microservice-Architecture).
我们一直在努力开发微服务解决方案演示.初始版本已完成并[文档化](https://cn.abp.io/documents/abp/latest/Samples/Microservice-Demo).该示例解决方案旨在演示一个简单而完整的微服务解决方案;
- 具有多个独立的,可自我部署的**微服务**.
- 多个**Web应用程序**,每个都使用不同的API网关.
- 使用[Ocelot](https://github.com/ThreeMammals/Ocelot)库开发了多个**网关** / BFF(后端为前端(Backend for Frontends)).
- 使用[IdentityServer](https://identityserver.io/)框架开发**身份验证服务**.它也是一个带有必要UI的SSO(单点登录)应用程序.
- 有**多个数据库**.一些微服务有自己的数据库,而一些服务/应用程序共享一个数据库(以演示不同的用例).
- 具有不同类型的数据库:**SQL Server**(使用**Entity Framework Core** ORM)和**MongoDB**.
- 有一个**控制台应用程序**来显示通过身份验证使用服务的最简单方法.
- 使用[Redis](https://redis.io/)进行**分布式缓存**.
- 使用[RabbitMQ](https://www.rabbitmq.com/)进行服务到服务(service-to-service)的**消息传递**.
- 使用[Docker](https://www.docker.com/)和[Kubernates](https://kubernetes.io/)**部署**并运行所有服务和应用程序.
- 使用[Elasticsearch](https://www.elastic.co/products/elasticsearch)和[Kibana](https://www.elastic.co/products/kibana)存储和可视化日志(使用[Serilog](https://serilog.net/)编写).
有关解决方案的详细说明,请参阅[其文档](https://cn.abp.io/documents/abp/latest/Samples/Microservice-Demo).
## 改进/功能
我们已经开发了许多功能,包括**分布式事件总线**(与RabbitMQ集成),**IdentityServer4集成**以及几乎所有功能的增强.我们不断重构和添加测试,以使框架更稳定和生产就绪.它正在[快速增长](https://github.com/abpframework/abp/graphs/contributors).
## 路线图
在第一个稳定版本(v1.0)之前还有很多工作要做.您可以在GitHub仓库上看到[优先的积压项目](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3ABacklog).
根据我们的估计,我们计划在2019年第二季度(可能在五月或六月)发布v1.0.所以,不用等待太长时间了.我们也对第一个稳定版本感到非常兴奋.
我们还将完善[文档](https://cn.abp.io/documents/abp/latest),因为它现在还远未完成.
第一个版本可能不包含SPA模板.但是,如果可能的话,我们想要准备一个简单些的.SPA框架还没有确定下来.备选有:**Angular,React和Blazor**.请将您的想法写为对此帖的评论.
## 中文网
中国有一个大型的ABP社区.他们创建了一个中文版的abp.io网站:https://cn.abp.io/. 他们一直在保持更新.感谢中国的开发人员,特别是[Liming Ma](https://github.com/maliming).
## NDC {London} 2019
很高兴作为合作伙伴参加[NDC {London}](https://ndc-london.com/)2019 .我们已经与许多开发人员讨论过当前的ASP.NET Boilerplate和ABP vNext,我们得到了很好的反馈.
我们还有机会与[Scott Hanselman](https://twitter.com/shanselman)和[Jon Galloway](https://twitter.com/jongalloway)交谈.他们参观了我们的展位,我们谈到了ABP vNext的想法.他们喜欢新的ABP框架的功能,方法和目标.在twitter上查看一些照片和评论:
![scott-and-jon](scott-and-jon.png)
## 跟上步伐
* 您可以标星并关注**GitHub**存储库:https://github.com/abpframework/abp
* 您可以关注官方**Twitter**帐户获取新闻:https://twitter.com/abpframework

BIN
docs/zh-Hans/Blog-Posts/2019-02-22/scott-and-jon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

20
docs/zh-Hans/Getting-Started-AspNetCore-Application.md

@ -156,6 +156,26 @@ services.AddApplication<AppModule>(options =>
});
````
4. 更新 `Program.cs`代码, 不再使用`WebHost.CreateDefaultBuilder()`方法(因为它使用默认的DI容器):
````csharp
public class Program
{
public static void Main(string[] args)
{
BuildWebHostInternal(args).Run();
}
public static IWebHost BuildWebHostInternal(string[] args) =>
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
}
````
### 源码
从[此处](../samples/BasicAspNetCoreApplication)获取本教程中创建的示例项目的源代码.

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

@ -12,14 +12,14 @@
下载的项目需要:
* [Visual Studio 2017 (v15.7.0+)](https://visualstudio.microsoft.com/tr/downloads/)
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/)
* [.NET Core 2.1.1+](https://www.microsoft.com/net/download/dotnet-core/)
### 解决方案结构
下载后解压文件并在 **Visual Studio 2017(15.7.0 +)** 中打开:
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png)
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
该解决方案具有分层结构(基于域驱动设计), 其中:
@ -28,6 +28,8 @@
* ``.Web`` 为是表示层.
* ``.EntityFrameworkCore`` 是EF Core集成.
EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项目中.
解决方案还包含配置好的的单元&集成测试项目, 以便与 **EF Core****SQLite内存中** 数据库配合使用.
### 创建数据库
@ -48,9 +50,9 @@
![set-as-startup-project](images/set-as-startup-project.png)
打开**包管理器控制台(Package Manager Console)**, 选择`.EntityFrameworkCore`项目作为**默认项目**并运行`Update-Database`命令:
打开**包管理器控制台(Package Manager Console)**, 选择`.EntityFrameworkCore.DbMigrations`项目作为**默认项目**并运行`Update-Database`命令:
![pcm-update-database](images/pcm-update-database.png)
![pcm-update-database](images/pcm-update-database-v2.png)
这将基于配置的连接字符串创建新数据库.

1433
docs/zh-Hans/Samples/Microservice-Demo.md

File diff suppressed because it is too large

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

@ -20,7 +20,7 @@
下面的图片展示了从启动模板创建的项目是如何分层的.
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png)
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
### 创建Book实体
@ -93,7 +93,7 @@ public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
这个启动模板使用了[EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/)来创建并维护数据库结构.打开 **Package Manager Console (PMC)** (工具/Nuget包管理器菜单),选择 `Acme.BookStore.EntityFrameworkCore`作为默认的项目然后执行下面的命令:
![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration.png)
![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration-v2.png)
这样就会在`Migrations`文件夹中创建一个新的migration类.然后执行`Update-Database`命令更新数据库结构.

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

@ -14,7 +14,6 @@
本解决方案中有两个测试项目:
![bookstore-test-projects](images/bookstore-test-projects.png)
* `Acme.BookStore.Application.Tests` 项目用于单元测试和集成测试.你可以在这个项目中为Application Service方法写测试代码.这个项目使用了 **EF Core SQLite in-memory** 数据库.
* `Acme.BookStore.Web.Tests` 项目用于包含Web层的完整集成测试.所以,你也可以在这里写关于UI页面的测试.

BIN
docs/zh-Hans/images/bookstore-visual-studio-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
docs/zh-Hans/images/microservice-sample-authserver-home.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/zh-Hans/images/microservice-sample-authserver-login.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/zh-Hans/images/microservice-sample-backend-ui-permissions.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
docs/zh-Hans/images/microservice-sample-backend-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/zh-Hans/images/microservice-sample-blogservice-permission-in-database.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
docs/zh-Hans/images/microservice-sample-diagram-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

BIN
docs/zh-Hans/images/microservice-sample-kibana-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
docs/zh-Hans/images/microservice-sample-kibana-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/zh-Hans/images/microservice-sample-product-module-in-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/zh-Hans/images/microservice-sample-public-product-list.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/zh-Hans/images/microservice-sample-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/zh-Hans/images/pcm-update-database-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

4
framework/Volo.Abp.sln

@ -87,7 +87,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Data", "src\Volo.A
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Data.Tests", "test\Volo.Abp.Data.Tests\Volo.Abp.Data.Tests.csproj", "{5D2275B7-0745-420A-AF1C-32C563DAB5C8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy.Abstractions", "src\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj", "{10EB789E-C993-4BE8-BA43-C419936C7233}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy", "src\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj", "{10EB789E-C993-4BE8-BA43-C419936C7233}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectMapping", "src\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj", "{8D22063D-88DE-4F7A-A917-C81AB4ACE601}"
EndProject
@ -213,7 +213,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.Con
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Features", "src\Volo.Abp.Features\Volo.Abp.Features.csproj", "{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Features.Tests", "test\Volo.Abp.Features.Tests\Volo.Abp.Features.Tests.csproj", "{575BEFA1-19C2-49B1-8D31-B5D4472328DE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Features.Tests", "test\Volo.Abp.Features.Tests\Volo.Abp.Features.Tests.csproj", "{575BEFA1-19C2-49B1-8D31-B5D4472328DE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

2
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj

@ -15,7 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore\Volo.Abp.AspNetCore.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
</ItemGroup>
</Project>

2
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs

@ -5,7 +5,7 @@ using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
[DependsOn(
typeof(AbpMultiTenancyAbstractionsModule),
typeof(AbpMultiTenancyModule),
typeof(AbpAspNetCoreModule)
)]
public class AbpAspNetCoreMultiTenancyModule : AbpModule

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs

@ -5,6 +5,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class CookieTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "Cookie";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
return httpContext.Request?.Cookies[context.GetAspNetCoreMultiTenancyOptions().TenantKey];

16
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs

@ -9,23 +9,33 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
public class DomainTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "Domain";
public override string Name => ContributorName;
private static readonly string[] ProtocolPrefixes = { "http://", "https://" };
private readonly string _domainFormat;
public DomainTenantResolveContributor(string domainFormat)
{
_domainFormat = domainFormat.RemovePreFix("http://", "https://");
_domainFormat = domainFormat.RemovePreFix(ProtocolPrefixes);
}
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
protected override string GetTenantIdOrNameFromHttpContextOrNull(
ITenantResolveContext context,
HttpContext httpContext)
{
if (httpContext.Request?.Host == null)
{
return null;
}
var hostName = httpContext.Request.Host.Host.RemovePreFix("http://", "https://");
var hostName = httpContext.Request.Host.Host.RemovePreFix(ProtocolPrefixes);
var extractResult = FormattedStringValueExtracter.Extract(hostName, _domainFormat, ignoreCase: true);
context.Handled = true;
if (!extractResult.IsMatch)
{
return null;

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs

@ -9,6 +9,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class HeaderTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "Header";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
if (httpContext.Request == null || httpContext.Request.Headers.IsNullOrEmpty())

40
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs

@ -0,0 +1,40 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class HttpContextTenantResolveResultAccessor : ITenantResolveResultAccessor, ITransientDependency
{
[CanBeNull]
public TenantResolveResult Result
{
get
{
if (_httpContextAccessor.HttpContext == null)
{
return null;
}
return _httpContextAccessor.HttpContext.Items[""] as TenantResolveResult;
}
set
{
if (_httpContextAccessor.HttpContext == null)
{
return;
}
_httpContextAccessor.HttpContext.Items[""] = value;
}
}
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextTenantResolveResultAccessor(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
}
}

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributerBase.cs

@ -7,9 +7,9 @@ using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
public abstract class HttpTenantResolveContributorBase : ITenantResolveContributor
public abstract class HttpTenantResolveContributorBase : TenantResolveContributorBase
{
public virtual void Resolve(ITenantResolveContext context)
public override void Resolve(ITenantResolveContext context)
{
var httpContext = context.GetHttpContext();
if (httpContext == null)

9
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/ITenantResolveResultAccessor.cs

@ -0,0 +1,9 @@
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
public interface ITenantResolveResultAccessor
{
TenantResolveResult Result { get; set; }
}
}

51
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs

@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http;
using Volo.Abp.MultiTenancy;
@ -12,46 +11,48 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
private readonly ITenantResolver _tenantResolver;
private readonly ITenantStore _tenantStore;
private readonly ICurrentTenantIdAccessor _currentTenantIdAccessor;
private readonly ICurrentTenant _currentTenant;
private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor;
public MultiTenancyMiddleware(
RequestDelegate next,
ITenantResolver tenantResolver,
ITenantStore tenantStore,
ICurrentTenantIdAccessor currentTenantIdAccessor)
ICurrentTenant currentTenant,
ITenantResolveResultAccessor tenantResolveResultAccessor)
{
_next = next;
_tenantResolver = tenantResolver;
_tenantStore = tenantStore;
_currentTenantIdAccessor = currentTenantIdAccessor;
_currentTenant = currentTenant;
_tenantResolveResultAccessor = tenantResolveResultAccessor;
}
public async Task Invoke(HttpContext httpContext)
{
using (SetCurrentTenant(await ResolveCurrentTenantAsync()))
{
await _next(httpContext);
}
}
var resolveResult = _tenantResolver.ResolveTenantIdOrName();
_tenantResolveResultAccessor.Result = resolveResult;
private async Task<TenantInfo> ResolveCurrentTenantAsync()
{
var tenantIdOrName = _tenantResolver.ResolveTenantIdOrName();
if (tenantIdOrName == null)
TenantConfiguration tenant = null;
if (resolveResult.TenantIdOrName != null)
{
return null;
tenant = await FindTenantAsync(resolveResult.TenantIdOrName);
if (tenant == null)
{
//TODO: A better exception?
throw new AbpException(
"There is no tenant with given tenant id or name: " + resolveResult.TenantIdOrName
);
}
}
var tenant = await FindTenantAsync(tenantIdOrName);
if (tenant == null)
using (_currentTenant.Change(tenant?.Id, tenant?.Name))
{
throw new AbpException("There is no tenant with given tenant id or name: " + tenantIdOrName);
await _next(httpContext);
}
return tenant;
}
private async Task<TenantInfo> FindTenantAsync(string tenantIdOrName)
private async Task<TenantConfiguration> FindTenantAsync(string tenantIdOrName)
{
if (Guid.TryParse(tenantIdOrName, out var parsedTenantId))
{
@ -62,15 +63,5 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
return await _tenantStore.FindAsync(tenantIdOrName);
}
}
private IDisposable SetCurrentTenant([CanBeNull] TenantInfo tenant)
{
var parentScope = _currentTenantIdAccessor.Current;
_currentTenantIdAccessor.Current = new TenantIdWrapper(tenant?.Id);
return new DisposeAction(() =>
{
_currentTenantIdAccessor.Current = parentScope;
});
}
}
}

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs

@ -5,6 +5,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class QueryStringTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "QueryString";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
if (httpContext.Request == null || !httpContext.Request.QueryString.HasValue)

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs

@ -7,6 +7,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
public class RouteTenantResolveContributor : HttpTenantResolveContributorBase
{
public const string ContributorName = "Route";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{
var tenantId = httpContext.GetRouteValue(context.GetAspNetCoreMultiTenancyOptions().TenantKey);

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/tenant-switch.js

@ -3,7 +3,7 @@
var tenantSwitchModal = new abp.ModalManager(abp.appPath + 'Abp/MultiTenancy/TenantSwitchModal');
$(function() {
$('#TenantSwitchToolbarLink').click(function(e) {
$('#AbpTenantSwitchLink').click(function(e) {
e.preventDefault();
tenantSwitchModal.open();
});

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj

@ -18,11 +18,9 @@
<ItemGroup>
<EmbeddedResource Include="Pages\**\*.cshtml" />
<EmbeddedResource Include="Pages\**\*.js" />
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Components\**\*.cshtml" />
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" />
<Content Remove="Pages\**\*.cshtml" />
<Content Remove="Pages\**\*.js" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Components\**\*.cshtml" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" />
</ItemGroup>

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/AbpAspNetCoreMvcUiMultiTenancyModule.cs

@ -1,11 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
@ -36,11 +34,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiMultiTenancyModule>();
});
Configure<ToolbarOptions>(options =>
{
options.Contributors.Add(new MultiTenancyToolbarContributor());
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources

17
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml

@ -1,17 +0,0 @@
@using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch
@model TenantSwitchViewComponent.TenantSwitchViewModel
@if (!Model.CurrentUser.IsAuthenticated)
{
<li class="nav-item">
<a abp-button="Link" id="TenantSwitchToolbarLink" href="#">
@if (Model.Tenant == null)
{
<text>@@host</text>
}
else
{
<text>@@@Model.Tenant.Name</text>
}
</a>
</li>
}

51
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/TenantSwitchViewComponent.cs

@ -1,51 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch
{
public class TenantSwitchViewComponent : AbpViewComponent
{
/// <summary>
/// -1,000,000
/// </summary>
public const int Order = -1_000_000;
protected ITenantStore TenantStore { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ICurrentUser CurrentUser { get; }
public TenantSwitchViewComponent(
ITenantStore tenantStore,
ICurrentTenant currentTenant,
ICurrentUser currentUser)
{
TenantStore = tenantStore;
CurrentTenant = currentTenant;
CurrentUser = currentUser;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var model = new TenantSwitchViewModel
{
CurrentUser = CurrentUser
};
if (CurrentTenant.Id.HasValue)
{
model.Tenant = await TenantStore.FindAsync(CurrentTenant.GetId());
}
return View("~/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml", model);
}
public class TenantSwitchViewModel
{
public TenantInfo Tenant { get; set; }
public ICurrentUser CurrentUser { get; set; }
}
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/_ViewImports.cshtml

@ -1,3 +0,0 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json

@ -1,9 +1,11 @@
{
{
"culture": "en",
"texts": {
"GivenTenantIsNotAvailable": "Given tenant is not available: {0}",
"SwitchTenant": "Switch tenant",
"Tenant": "Tenant",
"Switch": "switch",
"Name": "Name",
"SwitchTenantHint": "Leave the name field blank to switch to the host side."
"SwitchTenantHint": "Leave the name field blank to switch to the host side.",
"NotSelected": "Not selected"
}
}

6
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json

@ -2,8 +2,10 @@
"culture": "tr",
"texts": {
"GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}",
"SwitchTenant": "Müşteri değiştir",
"Tenant": "Müşteri",
"Switch": "değiştir",
"Name": "İsim",
"SwitchTenantHint": "Host tarafına geçmek için isim alanını boş bırakın."
"SwitchTenantHint": "Host tarafına geçmek için isim alanını boş bırakın.",
"NotSelected": "Seçili değil"
}
}

21
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/MultiTenancyToolbarContributor.cs

@ -1,21 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy
{
public class MultiTenancyToolbarContributor : IToolbarContributor
{
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
{
if (context.Toolbar.Name != StandardToolbars.Main)
{
return Task.CompletedTask;
}
context.Toolbar.Items.Add(new ToolbarItem(typeof(TenantSwitchViewComponent), TenantSwitchViewComponent.Order));
return Task.CompletedTask;
}
}
}

2
framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj

@ -16,7 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />

2
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingModule.cs

@ -15,7 +15,7 @@ namespace Volo.Abp.Auditing
typeof(AbpTimingModule),
typeof(AbpSecurityModule),
typeof(AbpThreadingModule),
typeof(AbpMultiTenancyAbstractionsModule)
typeof(AbpMultiTenancyModule)
)]
public class AbpAuditingModule : AbpModule
{

2
framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj

@ -18,7 +18,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.Serialization\Volo.Abp.Serialization.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
</ItemGroup>

2
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs

@ -9,7 +9,7 @@ namespace Volo.Abp.Caching
{
[DependsOn(typeof(AbpThreadingModule))]
[DependsOn(typeof(AbpSerializationModule))]
[DependsOn(typeof(AbpMultiTenancyAbstractionsModule))]
[DependsOn(typeof(AbpMultiTenancyModule))]
public class AbpCachingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

27
framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataModule.cs

@ -1,10 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Data
{
public class AbpDataModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
AutoAddDataSeedContributors(context.Services);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
@ -13,5 +20,23 @@ namespace Volo.Abp.Data
context.Services.AddSingleton(typeof(IDataFilter<>), typeof(DataFilter<>));
}
private static void AutoAddDataSeedContributors(IServiceCollection services)
{
var contributors = new List<Type>();
services.OnRegistred(context =>
{
if (typeof(IDataSeedContributor).IsAssignableFrom(context.ImplementationType))
{
contributors.Add(context.ImplementationType);
}
});
services.Configure<DataSeedOptions>(options =>
{
options.Contributors.AddIfNotContains(contributors);
});
}
}
}

1
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataFilter.cs

@ -8,6 +8,7 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Data
{
//TODO: Create a Volo.Abp.Data.Filtering namespace?
public class DataFilter : IDataFilter, ISingletonDependency
{
private readonly ConcurrentDictionary<Type, object> _filters;

48
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.Data
{
public class DataSeedContext
{
public Guid? TenantId { get; set; }
/// <summary>
/// Gets/sets a key-value on the <see cref="Properties"/>.
/// </summary>
/// <param name="name">Name of the property</param>
/// <returns>
/// Returns the value in the <see cref="Properties"/> dictionary by given <see cref="name"/>.
/// Returns null if given <see cref="name"/> is not present in the <see cref="Properties"/> dictionary.
/// </returns>
[CanBeNull]
public object this[string name]
{
get => Properties.GetOrDefault(name);
set => Properties[name] = value;
}
/// <summary>
/// Can be used to get/set custom properties.
/// </summary>
[NotNull]
public Dictionary<string, object> Properties { get; }
public DataSeedContext(Guid? tenantId = null)
{
TenantId = tenantId;
Properties = new Dictionary<string, object>();
}
/// <summary>
/// Sets a property in the <see cref="Properties"/> dictionary.
/// This is a shortcut for nested calls on this object.
/// </summary>
public virtual DataSeedContext WithProperty(string key, object value)
{
Properties[key] = value;
return this;
}
}
}

9
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContributorList.cs

@ -0,0 +1,9 @@
using Volo.Abp.Collections;
namespace Volo.Abp.Data
{
public class DataSeedContributorList : TypeList<IDataSeedContributor>
{
}
}

12
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedOptions.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.Data
{
public class DataSeedOptions
{
public DataSeedContributorList Contributors { get; }
public DataSeedOptions()
{
Contributors = new DataSeedContributorList();
}
}
}

37
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeeder.cs

@ -0,0 +1,37 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Data
{
//TODO: Create a Volo.Abp.Data.Seeding namespace?
public class DataSeeder : IDataSeeder, ITransientDependency
{
protected IHybridServiceScopeFactory ServiceScopeFactory { get; }
protected DataSeedOptions Options { get; }
public DataSeeder(
IOptions<DataSeedOptions> options,
IHybridServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
Options = options.Value;
}
public async Task SeedAsync(DataSeedContext context)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
foreach (var contributorType in Options.Contributors)
{
var contributor = (IDataSeedContributor) scope
.ServiceProvider
.GetRequiredService(contributorType);
await contributor.SeedAsync(context);
}
}
}
}
}

13
framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeederExtensions.cs

@ -0,0 +1,13 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.Data
{
public static class DataSeederExtensions
{
public static Task SeedAsync(this IDataSeeder seeder, Guid? tenantId = null)
{
return seeder.SeedAsync(new DataSeedContext(tenantId));
}
}
}

9
framework/src/Volo.Abp.Data/Volo/Abp/Data/IDataSeedContributor.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.Data
{
public interface IDataSeedContributor
{
Task SeedAsync(DataSeedContext context);
}
}

9
framework/src/Volo.Abp.Data/Volo/Abp/Data/IDataSeeder.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.Data
{
public interface IDataSeeder
{
Task SeedAsync(DataSeedContext context);
}
}

2
framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj

@ -18,7 +18,7 @@
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.Domain
typeof(AbpDataModule),
typeof(AbpEventBusModule),
typeof(AbpGuidsModule),
typeof(AbpMultiTenancyAbstractionsModule),
typeof(AbpMultiTenancyModule),
typeof(AbpThreadingModule),
typeof(AbpTimingModule),
typeof(AbpUnitOfWorkModule),

2
framework/src/Volo.Abp.Features/Volo.Abp.Features.csproj

@ -15,7 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.Validation\Volo.Abp.Validation.csproj" />
</ItemGroup>

2
framework/src/Volo.Abp.Features/Volo/Abp/Features/AbpFeaturesModule.cs

@ -10,7 +10,7 @@ namespace Volo.Abp.Features
{
[DependsOn(
typeof(AbpLocalizationAbstractionsModule),
typeof(AbpMultiTenancyAbstractionsModule),
typeof(AbpMultiTenancyModule),
typeof(AbpValidationModule)
)]
public class AbpFeaturesModule : AbpModule

15
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AbpMultiTenancyAbstractionsModule.cs

@ -1,15 +0,0 @@
using Volo.Abp.Data;
using Volo.Abp.Modularity;
using Volo.Abp.Security;
namespace Volo.Abp.MultiTenancy
{
[DependsOn(
typeof(AbpDataModule),
typeof(AbpSecurityModule)
)]
public class AbpMultiTenancyAbstractionsModule : AbpModule //TODO: Rename to AbpMultiTenancyModule?
{
}
}

21
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantIdAccessor.cs

@ -1,21 +0,0 @@
using System.Threading;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class AsyncLocalCurrentTenantIdAccessor : ICurrentTenantIdAccessor, ISingletonDependency
{
public TenantIdWrapper Current
{
get => _currentScope.Value;
set => _currentScope.Value = value;
}
private readonly AsyncLocal<TenantIdWrapper> _currentScope;
public AsyncLocalCurrentTenantIdAccessor()
{
_currentScope = new AsyncLocal<TenantIdWrapper>();
}
}
}

30
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ConfigurationStore/ConfigurationTenantStore.cs

@ -1,30 +0,0 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy.ConfigurationStore
{
//TODO: Move to another package.
[Dependency(TryRegister = true)]
public class ConfigurationTenantStore : ITenantStore, ITransientDependency
{
private readonly ConfigurationTenantStoreOptions _options;
public ConfigurationTenantStore(IOptionsSnapshot<ConfigurationTenantStoreOptions> options)
{
_options = options.Value;
}
public Task<TenantInfo> FindAsync(string name)
{
return Task.FromResult(_options.Tenants.FirstOrDefault(t => t.Name == name));
}
public Task<TenantInfo> FindAsync(Guid id)
{
return Task.FromResult(_options.Tenants.FirstOrDefault(t => t.Id == id));
}
}
}

12
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ConfigurationStore/ConfigurationTenantStoreOptions.cs

@ -1,12 +0,0 @@
namespace Volo.Abp.MultiTenancy.ConfigurationStore
{
public class ConfigurationTenantStoreOptions
{
public TenantInfo[] Tenants { get; set; }
public ConfigurationTenantStoreOptions()
{
Tenants = new TenantInfo[0];
}
}
}

34
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentTenant.cs

@ -1,34 +0,0 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class CurrentTenant : ICurrentTenant, ITransientDependency
{
public virtual bool IsAvailable => Id.HasValue;
public virtual Guid? Id => _currentTenantIdAccessor.Current?.TenantId;
private readonly ICurrentTenantIdAccessor _currentTenantIdAccessor;
public CurrentTenant(ICurrentTenantIdAccessor currentTenantIdAccessor)
{
_currentTenantIdAccessor = currentTenantIdAccessor;
}
public IDisposable Change(Guid? id)
{
return SetCurrent(id);
}
private IDisposable SetCurrent(Guid? tenantId)
{
var parentScope = _currentTenantIdAccessor.Current;
_currentTenantIdAccessor.Current = new TenantIdWrapper(tenantId);
return new DisposeAction(() =>
{
_currentTenantIdAccessor.Current = parentScope;
});
}
}
}

13
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ICurrentTenantIdAccessor.cs

@ -1,13 +0,0 @@
namespace Volo.Abp.MultiTenancy
{
/* Uses TenantScopeTenantInfoWrapper instead of TenantInfo because being null of Current is different that being null of Current.Tenant.
* A null Current indicates that we haven't set it explicitly.
* A null Current.Tenant indicates that we have set null tenant value explicitly.
* A non-null Current.Tenant indicates that we have set a tenant value explicitly.
*/
public interface ICurrentTenantIdAccessor
{
TenantIdWrapper Current { get; set; }
}
}

18
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantIdWrapper.cs

@ -1,18 +0,0 @@
using System;
namespace Volo.Abp.MultiTenancy
{
public class TenantIdWrapper
{
/// <summary>
/// Null indicates the host.
/// Not null value for a tenant.
/// </summary>
public Guid? TenantId { get; }
public TenantIdWrapper(Guid? tenantId)
{
TenantId = tenantId;
}
}
}

4
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo.Abp.MultiTenancy.Abstractions.csproj → framework/src/Volo.Abp.MultiTenancy/Volo.Abp.MultiTenancy.csproj

@ -4,8 +4,8 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.MultiTenancy.Abstractions</AssemblyName>
<PackageId>Volo.Abp.MultiTenancy.Abstractions</PackageId>
<AssemblyName>Volo.Abp.MultiTenancy</AssemblyName>
<PackageId>Volo.Abp.MultiTenancy</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>

21
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyModule.cs

@ -0,0 +1,21 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy.ConfigurationStore;
using Volo.Abp.Security;
namespace Volo.Abp.MultiTenancy
{
[DependsOn(
typeof(AbpDataModule),
typeof(AbpSecurityModule)
)]
public class AbpMultiTenancyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<DefaultTenantStoreOptions>(configuration);
}
}
}

8
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ActionTenantResolveContributor.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ActionTenantResolveContributor.cs

@ -3,8 +3,12 @@ using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy
{
public class ActionTenantResolveContributor : ITenantResolveContributor
public class ActionTenantResolveContributor : TenantResolveContributorBase
{
public const string ContributorName = "Action";
public override string Name => ContributorName;
private readonly Action<ITenantResolveContext> _resolveAction;
public ActionTenantResolveContributor([NotNull] Action<ITenantResolveContext> resolveAction)
@ -14,7 +18,7 @@ namespace Volo.Abp.MultiTenancy
_resolveAction = resolveAction;
}
public void Resolve(ITenantResolveContext context)
public override void Resolve(ITenantResolveContext context)
{
_resolveAction(context);
}

21
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs

@ -0,0 +1,21 @@
using System.Threading;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class AsyncLocalCurrentTenantAccessor : ICurrentTenantAccessor, ISingletonDependency
{
public BasicTenantInfo Current
{
get => _currentScope.Value;
set => _currentScope.Value = value;
}
private readonly AsyncLocal<BasicTenantInfo> _currentScope;
public AsyncLocalCurrentTenantAccessor()
{
_currentScope = new AsyncLocal<BasicTenantInfo>();
}
}
}

27
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/BasicTenantInfo.cs

@ -0,0 +1,27 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy
{
public class BasicTenantInfo
{
/// <summary>
/// Null indicates the host.
/// Not null value for a tenant.
/// </summary>
[CanBeNull]
public Guid? TenantId { get; }
/// <summary>
/// Name of the tenant if <see cref="TenantId"/> is not null.
/// </summary>
[CanBeNull]
public string Name { get; }
public BasicTenantInfo(Guid? tenantId, string name = null)
{
TenantId = tenantId;
Name = name;
}
}
}

29
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs

@ -0,0 +1,29 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy.ConfigurationStore
{
[Dependency(TryRegister = true)]
public class DefaultTenantStore : ITenantStore, ITransientDependency
{
private readonly DefaultTenantStoreOptions _options;
public DefaultTenantStore(IOptionsSnapshot<DefaultTenantStoreOptions> options)
{
_options = options.Value;
}
public Task<TenantConfiguration> FindAsync(string name)
{
return Task.FromResult(_options.Tenants?.FirstOrDefault(t => t.Name == name));
}
public Task<TenantConfiguration> FindAsync(Guid id)
{
return Task.FromResult(_options.Tenants?.FirstOrDefault(t => t.Id == id));
}
}
}

12
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStoreOptions.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.MultiTenancy.ConfigurationStore
{
public class DefaultTenantStoreOptions
{
public TenantConfiguration[] Tenants { get; set; }
public DefaultTenantStoreOptions()
{
Tenants = new TenantConfiguration[0];
}
}
}

13
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs

@ -4,9 +4,13 @@ using Volo.Abp.Security.Claims;
namespace Volo.Abp.MultiTenancy
{
public class CurrentClaimsPrincipalTenantResolveContributor : ITenantResolveContributor
public class CurrentClaimsPrincipalTenantResolveContributor : TenantResolveContributorBase
{
public void Resolve(ITenantResolveContext context)
public const string ContributorName = "CurrentClaims";
public override string Name => ContributorName;
public override void Resolve(ITenantResolveContext context)
{
var principal = context.ServiceProvider.GetRequiredService<ICurrentPrincipalAccessor>().Principal;
if (principal?.Identity?.IsAuthenticated != true)
@ -14,8 +18,11 @@ namespace Volo.Abp.MultiTenancy
return;
}
context.TenantIdOrName = principal.Claims.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId)?.Value;
context.Handled = true;
context.TenantIdOrName = principal
.Claims
.FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId)
?.Value;
}
}
}

36
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenant.cs

@ -0,0 +1,36 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy
{
public class CurrentTenant : ICurrentTenant, ITransientDependency
{
public virtual bool IsAvailable => Id.HasValue;
public virtual Guid? Id => _currentTenantAccessor.Current?.TenantId;
public string Name => _currentTenantAccessor.Current?.Name;
private readonly ICurrentTenantAccessor _currentTenantAccessor;
public CurrentTenant(ICurrentTenantAccessor currentTenantAccessor)
{
_currentTenantAccessor = currentTenantAccessor;
}
public IDisposable Change(Guid? id, string name = null)
{
return SetCurrent(id, name);
}
private IDisposable SetCurrent(Guid? tenantId, string name = null)
{
var parentScope = _currentTenantAccessor.Current;
_currentTenantAccessor.Current = new BasicTenantInfo(tenantId, name);
return new DisposeAction(() =>
{
_currentTenantAccessor.Current = parentScope;
});
}
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/CurrentTenantExtensions.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentTenantExtensions.cs

5
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ICurrentTenant.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenant.cs

@ -10,6 +10,9 @@ namespace Volo.Abp.MultiTenancy
[CanBeNull]
Guid? Id { get; }
IDisposable Change(Guid? id);
[CanBeNull]
string Name { get; }
IDisposable Change(Guid? id, string name = null);
}
}

12
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ICurrentTenantAccessor.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.MultiTenancy
{
/* A null Current indicates that we haven't set it explicitly.
* A null Current.TenantId indicates that we have set null tenant id value explicitly.
* A non-null Current.TenantId indicates that we have set a tenant id value explicitly.
*/
public interface ICurrentTenantAccessor
{
BasicTenantInfo Current { get; set; }
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IMultiTenant.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IMultiTenant.cs

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantResolveContext.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContext.cs

2
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantResolveContributor.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolveContributor.cs

@ -2,6 +2,8 @@ namespace Volo.Abp.MultiTenancy
{
public interface ITenantResolveContributor
{
string Name { get; }
void Resolve(ITenantResolveContext context);
}
}

4
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantResolver.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantResolver.cs

@ -10,7 +10,7 @@ namespace Volo.Abp.MultiTenancy
/// <returns>
/// Tenant id, unique name or null (if could not resolve).
/// </returns>
[CanBeNull]
string ResolveTenantIdOrName();
[NotNull]
TenantResolveResult ResolveTenantIdOrName();
}
}

4
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ITenantStore.cs

@ -5,8 +5,8 @@ namespace Volo.Abp.MultiTenancy
{
public interface ITenantStore
{
Task<TenantInfo> FindAsync(string name);
Task<TenantConfiguration> FindAsync(string name);
Task<TenantInfo> FindAsync(Guid id);
Task<TenantConfiguration> FindAsync(Guid id);
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs

12
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyDatabaseStyle.cs

@ -0,0 +1,12 @@
using System;
namespace Volo.Abp.MultiTenancy
{
[Flags]
public enum MultiTenancyDatabaseStyle
{
Shared = 1,
PerTenant = 2,
Hybrid = Shared | PerTenant
}
}

17
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptions.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.MultiTenancy
{
public class MultiTenancyOptions
{
/// <summary>
/// A central point to enable/disable multi-tenancy.
/// Default: false.
/// </summary>
public bool IsEnabled { get; set; }
/// <summary>
/// Database style for tenants.
/// Default: <see cref="MultiTenancyDatabaseStyle.Hybrid"/>.
/// </summary>
public MultiTenancyDatabaseStyle DatabaseStyle { get; set; } = MultiTenancyDatabaseStyle.Hybrid;
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantConnectionStringResolver.cs

10
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantInfo.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfiguration.cs

@ -5,20 +5,20 @@ using Volo.Abp.Data;
namespace Volo.Abp.MultiTenancy
{
[Serializable]
public class TenantInfo //TODO: Add a custom data to TenantInfo and make it available in ICurrentTenant
public class TenantConfiguration
{
public Guid Id { get; }
public Guid Id { get; set; }
public string Name { get; }
public string Name { get; set; }
public ConnectionStrings ConnectionStrings { get; }
private TenantInfo()
public TenantConfiguration()
{
}
public TenantInfo(Guid id, [NotNull] string name)
public TenantConfiguration(Guid id, [NotNull] string name)
{
Check.NotNull(name, nameof(name));

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantResolveContext.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContext.cs

10
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveContributorBase.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.MultiTenancy
{
public abstract class TenantResolveContributorBase : ITenantResolveContributor
{
public abstract string Name { get; }
//TODO: We can make this async
public abstract void Resolve(ITenantResolveContext context);
}
}

0
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantResolveOptions.cs → framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save