2017-01-26 1 views
0

Мне нелегко получить пакет Autofac.Extras.Multitenancy для работы между двумя реализациями интерфейса.Autofac Web Api multi tenant не получает HTTPContext.Current

Я пытаюсь подключиться к отдельным базам данных на основе идентификатора арендатора, но мой ITenantIdentificationStrategy, который я взял из примера Autofac, не получает HttpContext.Current, поэтому я не могу ничего получить от HTTP-вызова, чтобы принять решение. У меня две конфигурации вроде этого.

var mtc = new MultitenantContainer(tenantIdStrategy, builder.Build()); 

mtc.ConfigureTenant(Guid.Parse("00000000-0000-0000-0000-000000000001"), b => b.RegisterInstance<DatabaseConnection>(connectionOne).As<IDatabaseConnection>().SingleInstance());     
mtc.ConfigureTenant(Guid.Parse("00000000-0000-0000-0000-000000000002"), b => b.RegisterInstance<DatabaseConnection>(connectionTwo).As<IDatabaseConnection>().SingleInstance()); 

var resolver = new AutofacWebApiDependencyResolver(mtc); 

config.DependencyResolver = resolver; 

appBuilder.UseWebApi(config); 

Поэтому у меня есть два подключения к базе данных я создаю экземпляр, и я хочу, чтобы эти экземпляры, которые будут использоваться для каждого арендатора соответственно

Моего жильца Id довольно просто

public class RequestParameterStrategy : ITenantIdentificationStrategy 
{ 
    public bool TryIdentifyTenant(out object tenantId) 
    { 
     tenantId = null; 
     try 
     { 
      var context = HttpContext.Current; 

      if (context != null && context.Request != null) 
      { 
       tenantId = HttpContext.Current.Request.RequestContext.RouteData.Values["tenantId"]; 
      } 
     } 
     catch (HttpException) 
     { 
      // Happens at app startup in IIS 7.0 
     } 
     return tenantId != null; 
    } 
} 

Я добавил простой контроллер проверьте это, что должно быть в конвейере ASP.NET.

public IHttpActionResult Get(IMongoDBAdapter adapter, string memberId= null) { 
    return Ok() 
} 

Это пример прямо из веб-сайта Autofac. но HttpContext.Current всегда утратившая Id арендатор не установлена, а затем он жалуется, что мои контроллера не получает DatabaseConnection

EDIT Я думаю, моя проблема может быть, что этот проект не прошел в IIS. Это самообслуживаемая служба Windows и даже в контроллере HttpContext.Current имеет значение null. Похоже, эта идея может оказаться невозможной для самостоятельных сервисов?

+0

Когда вы разрешаете объект, который не работает? (Пожалуйста, обновите тело вопроса.) Если он не находится внутри запроса (например, конвейер ASP.NET еще не установил HttpContext.Current), этого мало что можно сделать. Этот пример doc является лишь примером и имеет больше об отказе от него, чем вы можете встряхнуть палку. Возможно, вам придется сделать некоторые изменения для ваших личных потребностей, чтобы справиться с вашими исключительными случаями. –

+0

[Я обновил документ с еще несколькими отказами от ответственности], чтобы избежать путаницы.] (Http://autofac.readthedocs.io/en/latest/advanced/multitenant.html) –

+0

@TravisIllig благодарит за ответ и обновление документации. Однако большая часть, о которой я не думал упоминать, заключалась в том, что она сама размещена в службе Windows. а не через IIS. Кажется, HttpContext.Current всегда будет null, поэтому ... bummer .... – ThrowsException

ответ

2

Вы правильно - you won't get HttpContext in a self hosted environment

Вы могли бы try writing a custom DelegatingHandler, который сидит первый в вашем самопринятый запроса трубопровода и устанавливает переменную контекста таким образом, подобно тому, как ASP.NET Core has an HttpContextAccessor

который должен сказать, ваш DelegatingHandler придется ...

  • Читайте в различных запросов на основе параметров вы заинтересованы.
  • Продлайт жилец идентификации и хранения значения с помощью CallContext.LogicalSetData

Тогда ваш арендатор стратегии ID будет считывать значение с помощью CallContext.LogicalGetData.

Посмотрите, как ASP.NET Core gets/sets HttpContext.Current doing a very, very similar thing Поскольку ASP.NET Core также не поддерживает HttpContext.Current.

Это на самом деле потенциально некоторый хитрый код, чтобы получить правильный, поэтому я поставил очень, очень грубый образец здесь, но не просто копировать/вставить это и предположить, что это будет 100% совершенен. Я не делаю для этого обширного тестирования, я просто пытаюсь дать вам представление.

Вот что обработчик может выглядеть следующим образом:

public class TenantIdentityHandler : DelegatingHandler 
{ 
    protected async override Task<HttpResponseMessage> SendAsync(
     HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     var id = request.Headers.GetValues("X-Tenant-ID").FirstOrDefault(); 
     CallContext.LogicalSetData("TenantIdentification" + AppDomain.CurrentDomain.Id, new ObjectHandle(id)); 
     return await base.SendAsync(request, cancellationToken); 
    } 
} 

Вот что ваша стратегия ID может выглядеть следующим образом:

public class CallContextStrategy : ITenantIdentificationStrategy 
{ 
    public bool TryIdentifyTenant(out object tenantId) 
    { 
     var handle = CallContext.LogicalGetData("TenantIdentification" + AppDomain.CurrentDomain.Id) as ObjectHandle; 
     var tenantId = handle?.Unwrap() as string; 
     return tenantId != null; 
    } 
} 

Опять же, я не пробовал, так что вы, возможно, придется настроить это, но, надеюсь, это поможет вам начать.

+0

Awesome. Похоже, я могу по крайней мере начать правильно. – ThrowsException

Смежные вопросы