Browse Source

Merge pull request #13 from colinin/2.9

2.9
pull/21/head
cKey 6 years ago
committed by GitHub
parent
commit
10b053c715
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN.Abp.BlobStoring.Qiniu.csproj
  2. 11
      aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/AbpBlobStoringQiniuModule.cs
  3. 24
      aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/DefaultQiniuBlobNameCalculator.cs
  4. 9
      aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/IQiniuBlobNameCalculator.cs
  5. 25
      aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/QiniuBlobContainerConfigurationExtensions.cs
  6. 50
      aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/QiniuBlobProvider.cs
  7. 85
      aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/QiniuBlobProviderConfiguration.cs
  8. 44
      aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/QiniuBlobProviderConfigurationNames.cs
  9. 5
      aspnet-core/modules/common/LINGYUN.Abp.DistributedLock/LINGYUN/Abp/Distributed/DistributedLockException.cs
  10. 10
      aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling.Emailing/LINGYUN.Abp.ExceptionHandling.Emailing.csproj
  11. 10
      aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling.Notifications/LINGYUN.Abp.ExceptionHandling.Notifications.csproj
  12. 9
      aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling/LINGYUN.Abp.ExceptionHandling.csproj
  13. 4
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN.Abp.FileStorage.Qiniu.csproj
  14. 21
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/LINGYUN.Abp.MultiTenancy.DbFinder.csproj
  15. 14
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/LINGYUN/Abp/MultiTenancy/DbFinder/AbpDbFinderMultiTenancyModule.cs
  16. 26
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/LINGYUN/Abp/MultiTenancy/DbFinder/TenantConfigurationCacheItem.cs
  17. 146
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/LINGYUN/Abp/MultiTenancy/DbFinder/TenantStore.cs
  18. 39
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/README.md
  19. 24
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/LINGYUN.Abp.MultiTenancy.RemoteService.csproj
  20. 13
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/LINGYUN/Abp/MultiTenancy/RemoteService/AbpRemoteServiceMultiTenancyModule.cs
  21. 26
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/LINGYUN/Abp/MultiTenancy/RemoteService/TenantConfigurationCacheItem.cs
  22. 136
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/LINGYUN/Abp/MultiTenancy/RemoteService/TenantStore.cs
  23. 47
      aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/README.md
  24. 18
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN.Abp.TenantManagement.Application.Contracts.csproj
  25. 16
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/AbpTenantManagementApplicationContractsModule.cs
  26. 18
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/Dto/TenantGetByNameInputDto.cs
  27. 2
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/ITenantAppService.cs
  28. 7
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/Localization/Resources/en.json
  29. 7
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/Localization/Resources/zh-Hans.json
  30. 17
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN/Abp/TenantManagement/TenantAppService.cs
  31. 24
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi.Client/LINGYUN.Abp.TenantManagement.HttpApi.Client.csproj
  32. 22
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi.Client/LINGYUN/Abp/TenantManagement/AbpTenantManagementHttpApiClientModule.cs

20
aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN.Abp.BlobStoring.Qiniu.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace /><GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.9.0</Version>
<Authors>LINGYUN</Authors>
<Description>阿里云Oss对象存储Abp集成</Description>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Qiniu.Shared" Version="7.2.15" />
<PackageReference Include="Volo.Abp.BlobStoring" Version="2.9.0" />
</ItemGroup>
</Project>

11
aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/AbpBlobStoringQiniuModule.cs

@ -0,0 +1,11 @@
using System;
using Volo.Abp.BlobStoring;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.BlobStoring.Qiniu
{
[DependsOn(typeof(AbpBlobStoringModule))]
public class AbpBlobStoringQiniuModule : AbpModule
{
}
}

24
aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/DefaultQiniuBlobNameCalculator.cs

@ -0,0 +1,24 @@
using Volo.Abp.BlobStoring;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.BlobStoring.Qiniu
{
public class DefaultQiniuBlobNameCalculator : IQiniuBlobNameCalculator, ITransientDependency
{
protected ICurrentTenant CurrentTenant { get; }
public DefaultQiniuBlobNameCalculator(
ICurrentTenant currentTenant)
{
CurrentTenant = currentTenant;
}
public string Calculate(BlobProviderArgs args)
{
return CurrentTenant.Id == null
? $"host/{args.BlobName}"
: $"tenants/{CurrentTenant.Id.Value:D}/{args.BlobName}";
}
}
}

9
aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/IQiniuBlobNameCalculator.cs

@ -0,0 +1,9 @@
using Volo.Abp.BlobStoring;
namespace LINGYUN.Abp.BlobStoring.Qiniu
{
public interface IQiniuBlobNameCalculator
{
string Calculate(BlobProviderArgs args);
}
}

25
aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/QiniuBlobContainerConfigurationExtensions.cs

@ -0,0 +1,25 @@
using System;
using Volo.Abp.BlobStoring;
namespace LINGYUN.Abp.BlobStoring.Qiniu
{
public static class QiniuBlobContainerConfigurationExtensions
{
public static QiniuBlobProviderConfiguration GetQiniuConfiguration(
this BlobContainerConfiguration containerConfiguration)
{
return new QiniuBlobProviderConfiguration(containerConfiguration);
}
public static BlobContainerConfiguration UseQiniu(
this BlobContainerConfiguration containerConfiguration,
Action<QiniuBlobProviderConfiguration> qiniuConfigureAction)
{
containerConfiguration.ProviderType = typeof(QiniuBlobProvider);
qiniuConfigureAction(new QiniuBlobProviderConfiguration(containerConfiguration));
return containerConfiguration;
}
}
}

50
aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/QiniuBlobProvider.cs

@ -0,0 +1,50 @@
using Qiniu.Util;
using System;
using System.IO;
using System.Threading.Tasks;
using Volo.Abp.BlobStoring;
using Volo.Abp.DependencyInjection;
using QiniuConfig = Qiniu.Common.Config;
namespace LINGYUN.Abp.BlobStoring.Qiniu
{
public class QiniuBlobProvider : BlobProviderBase, ITransientDependency
{
protected IQiniuBlobNameCalculator QiniuBlobNameCalculator { get; }
public override Task<bool> DeleteAsync(BlobProviderDeleteArgs args)
{
throw new NotImplementedException();
}
public override Task<bool> ExistsAsync(BlobProviderExistsArgs args)
{
throw new NotImplementedException();
}
public override Task<Stream> GetOrNullAsync(BlobProviderGetArgs args)
{
throw new NotImplementedException();
}
public override Task SaveAsync(BlobProviderSaveArgs args)
{
throw new NotImplementedException();
}
private Mac GetMac(BlobProviderArgs args)
{
var configuration = args.Configuration.GetQiniuConfiguration();
return new Mac(configuration.AccessKey, configuration.SecretKey);
}
private string GetAndInitBucketName(BlobProviderArgs args)
{
var configuration = args.Configuration.GetQiniuConfiguration();
var bucketName = configuration.BucketName.IsNullOrWhiteSpace()
? args.ContainerName
: configuration.BucketName;
QiniuConfig.AutoZone(configuration.AccessKey, bucketName, true);
return bucketName;
}
}
}

85
aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/QiniuBlobProviderConfiguration.cs

@ -0,0 +1,85 @@
using Volo.Abp;
using Volo.Abp.BlobStoring;
namespace LINGYUN.Abp.BlobStoring.Qiniu
{
public class QiniuBlobProviderConfiguration
{
/// <summary>
/// Api授权码
/// </remarks>
public string AccessKey
{
get => _containerConfiguration.GetConfiguration<string>(QiniuBlobProviderConfigurationNames.AccessKey);
set => _containerConfiguration.SetConfiguration(QiniuBlobProviderConfigurationNames.AccessKey, Check.NotNullOrWhiteSpace(value, nameof(value)));
}
/// <summary>
/// Api密钥
/// </summary>
public string SecretKey
{
get => _containerConfiguration.GetConfiguration<string>(QiniuBlobProviderConfigurationNames.SecretKey);
set => _containerConfiguration.SetConfiguration(QiniuBlobProviderConfigurationNames.SecretKey, Check.NotNullOrWhiteSpace(value, nameof(value)));
}
/// <summary>
/// 默认的Bucket名称
/// </summary>
public string BucketName
{
get => _containerConfiguration.GetConfigurationOrDefault(QiniuBlobProviderConfigurationNames.BucketName, "");
set => _containerConfiguration.SetConfiguration(QiniuBlobProviderConfigurationNames.BucketName, value ?? "");
}
/// <summary>
/// 默认自动删除该文件天数
/// 默认 0,不删除
/// </summary>
public int DeleteAfterDays
{
get => _containerConfiguration.GetConfigurationOrDefault(QiniuBlobProviderConfigurationNames.DeleteAfterDays, 0);
set => _containerConfiguration.SetConfiguration(QiniuBlobProviderConfigurationNames.DeleteAfterDays, value);
}
/// <summary>
/// 上传成功后,七牛云向业务服务器发送 POST 请求的 URL。
/// 必须是公网上可以正常进行 POST 请求并能响应 HTTP/1.1 200 OK 的有效 URL
/// </summary>
public string UploadCallbackUrl
{
get => _containerConfiguration.GetConfigurationOrDefault(QiniuBlobProviderConfigurationNames.UploadCallbackUrl, "");
set => _containerConfiguration.SetConfiguration(QiniuBlobProviderConfigurationNames.UploadCallbackUrl, value ?? "");
}
/// <summary>
/// 上传成功后,七牛云向业务服务器发送回调通知时的 Host 值。
/// 与 callbackUrl 配合使用,仅当设置了 callbackUrl 时才有效。
/// </summary>
public string UploadCallbackHost
{
get => _containerConfiguration.GetConfigurationOrDefault(QiniuBlobProviderConfigurationNames.UploadCallbackHost, "");
set => _containerConfiguration.SetConfiguration(QiniuBlobProviderConfigurationNames.UploadCallbackHost, value ?? "");
}
/// <summary>
/// 上传成功后,七牛云向业务服务器发送回调通知 callbackBody 的 Content-Type。
/// 默认为 application/x-www-form-urlencoded,也可设置为 application/json。
/// </summary>
public string UploadCallbackBodyType
{
get => _containerConfiguration.GetConfigurationOrDefault(QiniuBlobProviderConfigurationNames.UploadCallbackBodyType, "");
set => _containerConfiguration.SetConfiguration(QiniuBlobProviderConfigurationNames.UploadCallbackBodyType, value ?? "");
}
/// <summary>
/// 上传成功后,自定义七牛云最终返回給上传端(在指定 returnUrl 时是携带在跳转路径参数中)的数据。
/// 支持魔法变量和自定义变量。returnBody 要求是合法的 JSON 文本。
/// 例如 {"key": $(key), "hash": $(etag), "w": $(imageInfo.width), "h": $(imageInfo.height)}。
/// </summary>
public string UploadCallbackBody
{
get => _containerConfiguration.GetConfigurationOrDefault(QiniuBlobProviderConfigurationNames.UploadCallbackBody, "");
set => _containerConfiguration.SetConfiguration(QiniuBlobProviderConfigurationNames.UploadCallbackBody, value ?? "");
}
private readonly BlobContainerConfiguration _containerConfiguration;
public QiniuBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration)
{
_containerConfiguration = containerConfiguration;
}
}
}

44
aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Qiniu/LINGYUN/Abp/BlobStoring/Qiniu/QiniuBlobProviderConfigurationNames.cs

@ -0,0 +1,44 @@
namespace LINGYUN.Abp.BlobStoring.Qiniu
{
public static class QiniuBlobProviderConfigurationNames
{
/// <summary>
/// Api授权码
/// </summary>
public const string AccessKey = "Qiniu:OSS:AccessKey";
/// <summary>
/// Api密钥
/// </summary>
public const string SecretKey = "Qiniu:OSS:SecretKey";
/// <summary>
/// 默认的Bucket名称
/// </summary>
public const string BucketName = "Qiniu:OSS:BucketName";
/// <summary>
/// 默认自动删除该文件天数
/// 默认 0,不删除
/// </summary>
public const string DeleteAfterDays = "Qiniu:OSS:DeleteAfterDays";
/// <summary>
/// 上传成功后,七牛云向业务服务器发送 POST 请求的 URL。
/// 必须是公网上可以正常进行 POST 请求并能响应 HTTP/1.1 200 OK 的有效 URL
/// </summary>
public const string UploadCallbackUrl = "Qiniu:OSS:UploadCallbackUrl";
/// <summary>
/// 上传成功后,七牛云向业务服务器发送回调通知时的 Host 值。
/// 与 callbackUrl 配合使用,仅当设置了 callbackUrl 时才有效。
/// </summary>
public const string UploadCallbackHost = "Qiniu:OSS:UploadCallbackHost";
/// <summary>
/// 上传成功后,七牛云向业务服务器发送回调通知 callbackBody 的 Content-Type。
/// 默认为 application/x-www-form-urlencoded,也可设置为 application/json。
/// </summary>
public const string UploadCallbackBodyType = "Qiniu:OSS:UploadCallbackBodyType";
/// <summary>
/// 上传成功后,自定义七牛云最终返回給上传端(在指定 returnUrl 时是携带在跳转路径参数中)的数据。
/// 支持魔法变量和自定义变量。returnBody 要求是合法的 JSON 文本。
/// 例如 {"key": $(key), "hash": $(etag), "w": $(imageInfo.width), "h": $(imageInfo.height)}。
/// </summary>
public const string UploadCallbackBody = "Qiniu:OSS:UploadCallbackBody";
}
}

5
aspnet-core/modules/common/LINGYUN.Abp.DistributedLock/LINGYUN/Abp/Distributed/DistributedLockException.cs

@ -1,8 +1,9 @@
using System; using LINGYUN.Abp.ExceptionHandling;
using System;
namespace LINGYUN.Abp.Distributed namespace LINGYUN.Abp.Distributed
{ {
public class DistributedLockException : Exception public class DistributedLockException : Exception, IHasNotifierErrorMessage
{ {
public DistributedLockException(string message) public DistributedLockException(string message)
: base(message) : base(message)

10
aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling.Emailing/LINGYUN.Abp.ExceptionHandling.Emailing.csproj

@ -1,8 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace /> <RootNamespace /><GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.9.0</Version>
<Authors>LINGYUN</Authors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

10
aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling.Notifications/LINGYUN.Abp.ExceptionHandling.Notifications.csproj

@ -1,8 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace /> <RootNamespace /><GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.9.0</Version>
<Authors>LINGYUN</Authors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

9
aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling/LINGYUN.Abp.ExceptionHandling.csproj

@ -1,8 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace /> <RootNamespace />
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.9.0</Version>
<Authors>LINGYUN</Authors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

4
aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN.Abp.FileStorage.Qiniu.csproj

@ -9,10 +9,6 @@
<PackageReference Include="Qiniu.Shared" Version="7.2.15" /> <PackageReference Include="Qiniu.Shared" Version="7.2.15" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.FileStorage\LINGYUN.Abp.FileStorage.csproj" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Qiniu\Http\" /> <Folder Include="Qiniu\Http\" />
</ItemGroup> </ItemGroup>

21
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/LINGYUN.Abp.MultiTenancy.DbFinder.csproj

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.9.0</Version>
<Authors>LINGYUN</Authors>
<Company />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Caching" Version="2.9.0" />
<PackageReference Include="Volo.Abp.TenantManagement.Domain" Version="2.9.0" />
</ItemGroup>
</Project>

14
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/LINGYUN/Abp/MultiTenancy/DbFinder/AbpDbFinderMultiTenancyModule.cs

@ -0,0 +1,14 @@
using Volo.Abp.Caching;
using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement;
namespace LINGYUN.Abp.MultiTenancy.DbFinder
{
[DependsOn(
typeof(AbpCachingModule),
typeof(AbpTenantManagementDomainModule)
)]
public class AbpDbFinderMultiTenancyModule : AbpModule
{
}
}

26
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/LINGYUN/Abp/MultiTenancy/DbFinder/TenantConfigurationCacheItem.cs

@ -0,0 +1,26 @@
using System;
using Volo.Abp.Data;
namespace LINGYUN.Abp.MultiTenancy.DbFinder
{
public class TenantConfigurationCacheItem
{
public Guid Id { get; set; }
public string Name { get; set; }
// TODO: 是否需要加密存储?
public ConnectionStrings ConnectionStrings { get; set; } = new ConnectionStrings();
public TenantConfigurationCacheItem() { }
public TenantConfigurationCacheItem(Guid id, string name, ConnectionStrings connectionStrings)
{
Id = id;
Name = name;
ConnectionStrings = connectionStrings ?? ConnectionStrings;
}
public static string CalculateCacheKey(string key)
{
return "p:tenant" + ",k:" + key;
}
}
}

146
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/LINGYUN/Abp/MultiTenancy/DbFinder/TenantStore.cs

@ -0,0 +1,146 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.TenantManagement;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.MultiTenancy.DbFinder
{
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
[ExposeServices(typeof(ITenantStore))]
public class TenantStore : ITenantStore
{
public ILogger<TenantStore> Logger { protected get; set; }
private readonly IDistributedCache<TenantConfigurationCacheItem> _cache;
private readonly ITenantRepository _tenantRepository;
public TenantStore(
ITenantRepository tenantRepository,
IDistributedCache<TenantConfigurationCacheItem> cache)
{
_cache = cache;
_tenantRepository = tenantRepository;
Logger = NullLogger<TenantStore>.Instance;
}
public virtual TenantConfiguration Find(string name)
{
var tenantCacheItem = AsyncHelper.RunSync(async () => await
GetCacheItemByNameAsync(name));
return new TenantConfiguration(tenantCacheItem.Id, tenantCacheItem.Name)
{
ConnectionStrings = tenantCacheItem.ConnectionStrings
};
}
public virtual TenantConfiguration Find(Guid id)
{
var tenantCacheItem = AsyncHelper.RunSync(async () => await
GetCacheItemByIdAsync(id));
return new TenantConfiguration(tenantCacheItem.Id, tenantCacheItem.Name)
{
ConnectionStrings = tenantCacheItem.ConnectionStrings
};
}
public virtual async Task<TenantConfiguration> FindAsync(string name)
{
var tenantCacheItem = await GetCacheItemByNameAsync(name);
return new TenantConfiguration(tenantCacheItem.Id, tenantCacheItem.Name)
{
ConnectionStrings = tenantCacheItem.ConnectionStrings
};
}
public virtual async Task<TenantConfiguration> FindAsync(Guid id)
{
var tenantCacheItem = await GetCacheItemByIdAsync(id);
return new TenantConfiguration(tenantCacheItem.Id, tenantCacheItem.Name)
{
ConnectionStrings = tenantCacheItem.ConnectionStrings
};
}
protected virtual async Task<TenantConfigurationCacheItem> GetCacheItemByIdAsync(Guid id)
{
var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(id.ToString());
Logger.LogDebug($"TenantStore.GetCacheItemByIdAsync: {cacheKey}");
var cacheItem = await _cache.GetAsync(cacheKey);
if (cacheItem != null)
{
Logger.LogDebug($"Found in the cache: {cacheKey}");
return cacheItem;
}
Logger.LogDebug($"Not found in the cache, getting from the repository: {cacheKey}");
var tenant = await _tenantRepository.FindAsync(id, true);
if (tenant == null)
{
Logger.LogWarning($"Can not found tenant by id: {id}");
throw new AbpException($"Can not found tenant by id: {id}");
}
var connectionStrings = new ConnectionStrings();
foreach (var tenantConnectionString in tenant.ConnectionStrings)
{
connectionStrings[tenantConnectionString.Name] = tenantConnectionString.Value;
}
cacheItem = new TenantConfigurationCacheItem(tenant.Id, tenant.Name, connectionStrings);
Logger.LogDebug($"Setting the cache item: {cacheKey}");
await _cache.SetAsync(cacheKey, cacheItem);
Logger.LogDebug($"Finished setting the cache item: {cacheKey}");
return cacheItem;
}
protected virtual async Task<TenantConfigurationCacheItem> GetCacheItemByNameAsync(string name)
{
var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(name);
Logger.LogDebug($"TenantStore.GetCacheItemByNameAsync: {cacheKey}");
var cacheItem = await _cache.GetAsync(cacheKey);
if (cacheItem != null)
{
Logger.LogDebug($"Found in the cache: {cacheKey}");
return cacheItem;
}
Logger.LogDebug($"Not found in the cache, getting from the repository: {cacheKey}");
var tenant = await _tenantRepository.FindByNameAsync(name);
if (tenant == null)
{
Logger.LogWarning($"Can not found tenant by name: {name}");
throw new AbpException($"Can not found tenant by name: {name}");
}
var connectionStrings = new ConnectionStrings();
foreach (var tenantConnectionString in tenant.ConnectionStrings)
{
connectionStrings[tenantConnectionString.Name] = tenantConnectionString.Value;
}
cacheItem = new TenantConfigurationCacheItem(tenant.Id, tenant.Name, connectionStrings);
Logger.LogDebug($"Setting the cache item: {cacheKey}");
await _cache.SetAsync(cacheKey, cacheItem);
Logger.LogDebug($"Finished setting the cache item: {cacheKey}");
return cacheItem;
}
}
}

39
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.DbFinder/README.md

@ -0,0 +1,39 @@
# LINGYUN.Abp.MultiTenancy.DbFinder
abp 多租户数据库查询组件,引用此模块将首先从分布式缓存查询当前租户配置
如果缓存不存在,则调用租户仓储接口获取租户数据,并存储到分布式缓存中
## 配置使用
模块按需引用
启动项目需要引用**Volo.Abp.TenantManagement.EntityFrameworkCore**
``` shell
// .NET CLI
dotnet add package Volo.Abp.TenantManagement.EntityFrameworkCore --version 2.9.0
// Package Manager
Install-Package Volo.Abp.TenantManagement.EntityFrameworkCore -Version 2.9.0
```
事先定义**appsettings.json**文件
```json
{
"ConnectionStrings": {
"AbpTenantManagement": "Server=127.0.0.1;Database=TenantDb;User Id=root;Password=yourPassword"
}
}
```
```csharp
[DependsOn(typeof(AbpDbFinderMultiTenancyModule))]
public class YouProjectModule : AbpModule
{
// other
}
```

24
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/LINGYUN.Abp.MultiTenancy.RemoteService.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.9.0</Version>
<Authors>LINGYUN</Authors>
<Company />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Caching" Version="2.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.TenantManagement.HttpApi.Client\LINGYUN.Abp.TenantManagement.HttpApi.Client.csproj" />
</ItemGroup>
</Project>

13
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/LINGYUN/Abp/MultiTenancy/RemoteService/AbpRemoteServiceMultiTenancyModule.cs

@ -0,0 +1,13 @@
using LINGYUN.Abp.TenantManagement;
using Volo.Abp.Caching;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.MultiTenancy.RemoteService
{
[DependsOn(
typeof(AbpCachingModule),
typeof(AbpTenantManagementHttpApiClientModule))]
public class AbpRemoteServiceMultiTenancyModule : AbpModule
{
}
}

26
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/LINGYUN/Abp/MultiTenancy/RemoteService/TenantConfigurationCacheItem.cs

@ -0,0 +1,26 @@
using System;
using Volo.Abp.Data;
namespace LINGYUN.Abp.MultiTenancy.RemoteService
{
public class TenantConfigurationCacheItem
{
public Guid Id { get; set; }
public string Name { get; set; }
// TODO: 是否需要加密存储?
public ConnectionStrings ConnectionStrings { get; set; } = new ConnectionStrings();
public TenantConfigurationCacheItem() { }
public TenantConfigurationCacheItem(Guid id, string name, ConnectionStrings connectionStrings)
{
Id = id;
Name = name;
ConnectionStrings = connectionStrings ?? ConnectionStrings;
}
public static string CalculateCacheKey(string key)
{
return "p:tenant" + ",k:" + key;
}
}
}

136
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/LINGYUN/Abp/MultiTenancy/RemoteService/TenantStore.cs

@ -0,0 +1,136 @@
using LINGYUN.Abp.TenantManagement;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Caching;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.MultiTenancy.RemoteService
{
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
[ExposeServices(typeof(ITenantStore))]
public class TenantStore : ITenantStore
{
public ILogger<TenantStore> Logger { protected get; set; }
private readonly IDistributedCache<TenantConfigurationCacheItem> _cache;
private readonly ITenantAppService _tenantAppService;
public TenantStore(
ITenantAppService tenantAppService,
IDistributedCache<TenantConfigurationCacheItem> cache)
{
_cache = cache;
_tenantAppService = tenantAppService;
Logger = NullLogger<TenantStore>.Instance;
}
public virtual TenantConfiguration Find(string name)
{
var tenantCacheItem = AsyncHelper.RunSync(async () => await
GetCacheItemByNameAsync(name));
return new TenantConfiguration(tenantCacheItem.Id, tenantCacheItem.Name)
{
ConnectionStrings = tenantCacheItem.ConnectionStrings
};
}
public virtual TenantConfiguration Find(Guid id)
{
var tenantCacheItem = AsyncHelper.RunSync(async () => await
GetCacheItemByIdAsync(id));
return new TenantConfiguration(tenantCacheItem.Id, tenantCacheItem.Name)
{
ConnectionStrings = tenantCacheItem.ConnectionStrings
};
}
public virtual async Task<TenantConfiguration> FindAsync(string name)
{
var tenantCacheItem = await GetCacheItemByNameAsync(name);
return new TenantConfiguration(tenantCacheItem.Id, tenantCacheItem.Name)
{
ConnectionStrings = tenantCacheItem.ConnectionStrings
};
}
public virtual async Task<TenantConfiguration> FindAsync(Guid id)
{
var tenantCacheItem = await GetCacheItemByIdAsync(id);
return new TenantConfiguration(tenantCacheItem.Id, tenantCacheItem.Name)
{
ConnectionStrings = tenantCacheItem.ConnectionStrings
};
}
protected virtual async Task<TenantConfigurationCacheItem> GetCacheItemByIdAsync(Guid id)
{
var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(id.ToString());
Logger.LogDebug($"TenantStore.GetCacheItemByIdAsync: {cacheKey}");
var cacheItem = await _cache.GetAsync(cacheKey);
if (cacheItem != null)
{
Logger.LogDebug($"Found in the cache: {cacheKey}");
return cacheItem;
}
Logger.LogDebug($"Not found in the cache, getting from the remote service: {cacheKey}");
var tenantDto = await _tenantAppService.GetAsync(id);
var tenantConnectionStringsDto = await _tenantAppService.GetConnectionStringAsync(id);
var connectionStrings = new ConnectionStrings();
foreach (var tenantConnectionString in tenantConnectionStringsDto.Items)
{
connectionStrings[tenantConnectionString.Name] = tenantConnectionString.Value;
}
cacheItem = new TenantConfigurationCacheItem(tenantDto.Id, tenantDto.Name, connectionStrings);
Logger.LogDebug($"Setting the cache item: {cacheKey}");
await _cache.SetAsync(cacheKey, cacheItem);
Logger.LogDebug($"Finished setting the cache item: {cacheKey}");
return cacheItem;
}
protected virtual async Task<TenantConfigurationCacheItem> GetCacheItemByNameAsync(string name)
{
var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(name);
Logger.LogDebug($"TenantStore.GetCacheItemByNameAsync: {cacheKey}");
var cacheItem = await _cache.GetAsync(cacheKey);
if (cacheItem != null)
{
Logger.LogDebug($"Found in the cache: {cacheKey}");
return cacheItem;
}
Logger.LogDebug($"Not found in the cache, getting from the remote service: {cacheKey}");
var tenantDto = await _tenantAppService.GetAsync(new TenantGetByNameInputDto(name));
var tenantConnectionStringsDto = await _tenantAppService.GetConnectionStringAsync(tenantDto.Id);
var connectionStrings = new ConnectionStrings();
foreach(var tenantConnectionString in tenantConnectionStringsDto.Items)
{
connectionStrings[tenantConnectionString.Name] = tenantConnectionString.Value;
}
cacheItem = new TenantConfigurationCacheItem(tenantDto.Id, tenantDto.Name, connectionStrings);
Logger.LogDebug($"Setting the cache item: {cacheKey}");
await _cache.SetAsync(cacheKey, cacheItem);
Logger.LogDebug($"Finished setting the cache item: {cacheKey}");
return cacheItem;
}
}
}

47
aspnet-core/modules/tenants/LINGYUN.Abp.MultiTenancy.RemoteService/README.md

@ -0,0 +1,47 @@
# LINGYUN.Abp.MultiTenancy.RemoteService
abp 多租户远程服务组件,引用此模块将首先从分布式缓存查询当前租户配置
如果缓存不存在,则调用远程租户服务接口获取租户数据,并存储到分布式缓存中
## 配置使用
模块按需引用,因为远程服务接口定义了授权策略,需要配置接口客户端授权
具体**RemoteServices**与**IdentityClients**配置请阅读abp文档
[RemoteServices配置参阅](https://docs.abp.io/en/abp/latest/API/Dynamic-CSharp-API-Clients)
[IdentityClients配置参阅](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityClientConfiguration.cs)
事先定义**appsettings.json**文件
```json
{
"RemoteServices": {
"TenantManagement": {
"BaseUrl": "http://localhost:30000/",
"IdentityClient": "tenant-finder-client"
}
},
"IdentityClients": {
"tenant-finder-client": {
"Authority": "http://localhost:44385",
"RequireHttps": false,
"GrantType": "client_credentials",
"ClientId": "tenant-finder-client",
"Scope": "tenant-service",
"ClientSecret": "1q2w3e*"
}
}
}
```
```csharp
[DependsOn(typeof(AbpRemoteServiceMultiTenancyModule))]
public class YouProjectModule : AbpModule
{
// other
}
```

18
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN.Abp.TenantManagement.Application.Contracts.csproj

@ -3,8 +3,26 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace /> <RootNamespace />
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.9.0</Version>
<Authors>LINGYUN</Authors>
<Company />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\TenantManagement\Localization\Resources\en.json" />
<None Remove="LINGYUN\Abp\TenantManagement\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\TenantManagement\Localization\Resources\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\TenantManagement\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.9.0" /> <PackageReference Include="Volo.Abp.Ddd.Application" Version="2.9.0" />
<PackageReference Include="Volo.Abp.TenantManagement.Domain.Shared" Version="2.9.0" /> <PackageReference Include="Volo.Abp.TenantManagement.Domain.Shared" Version="2.9.0" />

16
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/AbpTenantManagementApplicationContractsModule.cs

@ -1,6 +1,9 @@
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement; using Volo.Abp.TenantManagement;
using Volo.Abp.TenantManagement.Localization;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.TenantManagement namespace LINGYUN.Abp.TenantManagement
{ {
@ -9,6 +12,19 @@ namespace LINGYUN.Abp.TenantManagement
typeof(AbpTenantManagementDomainSharedModule))] typeof(AbpTenantManagementDomainSharedModule))]
public class AbpTenantManagementApplicationContractsModule : AbpModule public class AbpTenantManagementApplicationContractsModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpTenantManagementApplicationContractsModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpTenantManagementResource>()
.AddVirtualJson("/LINGYUN/Abp/TenantManagement/Localization/Resources");
});
}
} }
} }

18
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/Dto/TenantGetByNameInputDto.cs

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.TenantManagement;
namespace LINGYUN.Abp.TenantManagement
{
public class TenantGetByNameInputDto
{
[Required]
[StringLength(TenantConsts.MaxNameLength)]
public string Name { get; set; }
public TenantGetByNameInputDto() { }
public TenantGetByNameInputDto(string name)
{
Name = name;
}
}
}

2
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/ITenantAppService.cs

@ -7,6 +7,8 @@ namespace LINGYUN.Abp.TenantManagement
{ {
public interface ITenantAppService : ICrudAppService<TenantDto, Guid, TenantGetByPagedInputDto, TenantCreateDto, TenantUpdateDto> public interface ITenantAppService : ICrudAppService<TenantDto, Guid, TenantGetByPagedInputDto, TenantCreateDto, TenantUpdateDto>
{ {
Task<TenantDto> GetAsync(TenantGetByNameInputDto tenantGetByNameInput);
Task<TenantConnectionStringDto> GetConnectionStringAsync(TenantConnectionGetByNameInputDto tenantConnectionGetByName); Task<TenantConnectionStringDto> GetConnectionStringAsync(TenantConnectionGetByNameInputDto tenantConnectionGetByName);
Task<ListResultDto<TenantConnectionStringDto>> GetConnectionStringAsync(Guid id); Task<ListResultDto<TenantConnectionStringDto>> GetConnectionStringAsync(Guid id);

7
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/Localization/Resources/en.json

@ -0,0 +1,7 @@
{
"culture": "en",
"texts": {
"TenantNotFoundById": "Tenant: {0} not found!",
"TenantNotFoundByName": "Tenant: {0} not found!"
}
}

7
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN/Abp/TenantManagement/Localization/Resources/zh-Hans.json

@ -0,0 +1,7 @@
{
"culture": "zh-Hans",
"texts": {
"TenantNotFoundById": "租户: {0} 不存在!",
"TenantNotFoundByName": "租户: {0} 不存在!"
}
}

17
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN/Abp/TenantManagement/TenantAppService.cs

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
@ -29,7 +30,21 @@ namespace LINGYUN.Abp.TenantManagement
public virtual async Task<TenantDto> GetAsync(Guid id) public virtual async Task<TenantDto> GetAsync(Guid id)
{ {
var tenant = await TenantRepository.GetAsync(id); var tenant = await TenantRepository.FindAsync(id, false);
if(tenant == null)
{
throw new UserFriendlyException(L["TenantNotFoundById", id]);
}
return ObjectMapper.Map<Tenant, TenantDto>(tenant);
}
public virtual async Task<TenantDto> GetAsync(TenantGetByNameInputDto tenantGetByNameInput)
{
var tenant = await TenantRepository.FindByNameAsync(tenantGetByNameInput.Name, false);
if (tenant == null)
{
throw new UserFriendlyException(L["TenantNotFoundByName", tenantGetByNameInput.Name]);
}
return ObjectMapper.Map<Tenant, TenantDto>(tenant); return ObjectMapper.Map<Tenant, TenantDto>(tenant);
} }

24
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi.Client/LINGYUN.Abp.TenantManagement.HttpApi.Client.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.9.0</Version>
<Authors>LINGYUN</Authors>
<Company />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Http.Client" Version="2.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.TenantManagement.Application.Contracts\LINGYUN.Abp.TenantManagement.Application.Contracts.csproj" />
</ItemGroup>
</Project>

22
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi.Client/LINGYUN/Abp/TenantManagement/AbpTenantManagementHttpApiClientModule.cs

@ -0,0 +1,22 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.TenantManagement
{
[DependsOn(
typeof(AbpTenantManagementApplicationContractsModule),
typeof(AbpHttpClientModule))]
public class AbpTenantManagementHttpApiClientModule : AbpModule
{
public const string RemoteServiceName = "TenantManagement";
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHttpClientProxies(
typeof(AbpTenantManagementApplicationContractsModule).Assembly,
RemoteServiceName
);
}
}
}
Loading…
Cancel
Save