零框架多租户设计方案

This commit is contained in:
administrator committed 2024-04-28 16:00:15 +08:00
1 parent b7caaa2d0c
commit b4a704526d
42 files changed
+1002 -1

No files matched your search

@@ -0,0 +1,28 @@
namespace MultiTenancySample.ServiceDefaults
{
public class CurrentTenant : ICurrentTenant
{
public string? TenantId { get; private set; }
public IDisposable SetTenant(string? tenantId)
{
string? parentTenantId = TenantId;
TenantId = tenantId;
return new DisposeAction(() =>
{
TenantId = parentTenantId;
});
}
public class DisposeAction(Action action) : IDisposable
{
void IDisposable.Dispose()
{
action();
GC.SuppressFinalize(this);
}
}
}
}
@@ -0,0 +1,9 @@
namespace MultiTenancySample.ServiceDefaults
{
public interface ICurrentTenant
{
string? TenantId { get; }
IDisposable SetTenant(string? tenantId);
}
}
@@ -0,0 +1,7 @@
namespace MultiTenancySample.ServiceDefaults
{
public interface ITenantIdProvider
{
Task<string?> GetTenantIdAsync();
}
}
@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace MultiTenancySample.ServiceDefaults
{
public static class MultiTenancyExtensions
{
public static IServiceCollection AddMultiTenancy(this IServiceCollection services)
{
services.AddScoped<ICurrentTenant, CurrentTenant>();
services.AddScoped<ITenantIdProvider, TenantIdProvider>();
return services.AddScoped<TenantMiddleware>();
}
public static IApplicationBuilder UseMultiTenancy(this IApplicationBuilder app)
{
app.UseMiddleware<TenantMiddleware>();
return app;
}
}
}
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
@@ -0,0 +1,12 @@
{
"profiles": {
"MultiTenancySample.ServiceDefaults": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:61544;http://localhost:61545"
}
}
}
@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Http;
namespace MultiTenancySample.ServiceDefaults
{
public class TenantIdProvider(IHttpContextAccessor httpContextAccessor) : ITenantIdProvider
{
public async Task<string?> GetTenantIdAsync()
{
HttpContext httpContext = httpContextAccessor.HttpContext ?? new DefaultHttpContext();
const string tenantKey = "tenant";
if (httpContext.Request.Headers.TryGetValue(tenantKey, out var headerValues))
{
return headerValues.First();
}
if (httpContext.Request.Query.TryGetValue(tenantKey, out var queryValues))
{
return queryValues.First();
}
if (httpContext.Request.Cookies.TryGetValue(tenantKey, out var cookieValue))
{
return cookieValue;
}
if (httpContext.Request.RouteValues.TryGetValue(tenantKey, out var routeValue))
{
return routeValue?.ToString();
}
return await Task.FromResult<string?>(null);
}
}
}
@@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Http;
namespace MultiTenancySample.ServiceDefaults
{
public class TenantMiddleware(ICurrentTenant currentTenant, ITenantIdProvider tenantProvider) : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
string? tenantId = await tenantProvider.GetTenantIdAsync();
using (currentTenant.SetTenant(tenantId))
{
await next(context);
}
}
}
}