我正在尝试在我的WebAPI项目中实现多租户。
在我的Startup.Auth.cs中,我将选定的Tenant对象添加到IOwinContext中。
app.Use(async (ctx, next) =>
{
Tenant tenant = GetTenantBasedUrl(ctx.Request.Uri.Host);
if (tenant == null)
{
throw new ApplicationException("tenant not found");
}
ctx.Environment.Add("MultiTenant", tenant);
await next();
}
GetTenantBaseUrl函数返回给我们所选的Tenant对象。 我已经创建了一个实现ApiController的类,我将为我的每个控制器实现它以获取Tenant对象。
public class MultiTenantWebApiController : ApiController
{
public Tenant Tenant
{
get
{
object multiTenant;
IDictionary<string, object> dic = HttpContext.Current.GetOwinContext().Environment;
if (!HttpContext.Current.GetOwinContext().Environment.TryGetValue("MultiTenant", out multiTenant))
{
throw new ApplicationException("Could Not Find Tenant");
}
return (Tenant)multiTenant;
}
}
}
在我的控制器中,我从OwinContext环境获取“MultiTenant”键,但我尝试从ApplicationOAuthProvider类获取相同的内容,它在我的OwinContext环境中不显示“MultiTenant”键,即:getEnvironment变量如下:
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private readonly string _publicClientId;
// some code here
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
try
{
**IDictionary getEnvironment = HttpContext.Current.GetOwinContext().Environment;**
// some code
有人知道为什么我没有在ApplicationOAuthProvider的OwinContext.Environment中获得“MultiTenant”键,而我在控制器中获取它?
谢谢!
答案 0 :(得分:0)
我建议您可以使用注入每个api控制器的上下文,以便跨层可以看到租户及其上下文。上下文提供程序可能看起来像这样
public class ClaimsContextDataProvider : IUserContextDataProvider
{
public Guid UserId
{
get
{
var userId = (Thread.CurrentPrincipal as ClaimsPrincipal)?.FindFirst(ClaimTypes.Sid)?.Value;
return TryGetGuidFromString(userId);
}
}
}
然后在DI框架中注册上下文提供程序[使用Autofac的示例如下]
builder.RegisterType<ClaimsContextDataProvider>().As<IUserContextDataProvider>();
然后有一个类似下面代码片段的BaseApiController
public Guid TenantId { get { return _userContext.TenantId; } }
public BaseApiController(IMapper mapper, IUserContextDataProvider userContext)
{
_mapper = mapper;
_userContext = userContext;
}
在派生控制器[CountriesController.cs]中访问BaseApiController的TenantId属性
// POST api/countries
public async Task<HttpResponseMessage> PostCountry(CountryRequestModel requestModel)
{
Country country = _mapper.Map<CountryRequestModel, Country>(requestModel);
country.CreatedOn = DateTimeOffset.Now;
country.TenantId = TenantId;
await _countryService.AddAsync(country);
CountryDto countryDto = _mapper.Map<Country, CountryDto>(country);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, countryDto);
response.Headers.Location = GetCountryLink(country.Id);
return response;
}
您可以查看示例应用和以下链接中提供的模板
这里有点深入解释,请随时阅读文档here