OwinContext Environment不包含已添加的元素

时间:2017-03-21 07:22:59

标签: c# asp.net-mvc asp.net-web-api owin multi-tenant

我正在尝试在我的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”键,而我在控制器中获取它?

谢谢!

1 个答案:

答案 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;
        }

您可以查看示例应用和以下链接中提供的模板

Multi-Tenant dev template

这里有点深入解释,请随时阅读文档here