asp.net-core – aspnet核心应用程序中的Autofac.Multitenant似
我正在升级使用Autofac.Multitenant框架的Multitenant dotnet核心解决方案.我没有很多运气让租约解决方案正常工作.我在这里创建了一个简单的问题演示:
https://github.com/SaltyDH/AutofacMultitenancy1
此repo演示了注册InstancePerTenant作用域依赖关系TestMultitenancyContext,该关系在Home Controller中解析.由于使用IHttpContextAccessor的问题,我使用自定义RequestMiddleware类来捕获当前的HttpContext对象,以便我可以在MultitenantIdentificationStrategy中的当前HttpContext请求对象上执行逻辑. 最后,TestFixture提供了一个简单的xUnit测试,至少在我的机器上为两个租户返回“tenant1”. 有没有我在这里错过的或者这只是目前没有工作? 解决方法
更新10/6/2017:
We released Autofac.AspNetCore.Multitenant以更易于使用的软件包结束解决方案.我会在这里留下原始答案/解释给后人,但是如果你打这个,你可以抓住那个包然后继续前进.
我认为你遇到了时间问题. 如果在中间件中弹出HttpContext上的调试器,则可以看到在名为ServiceProvidersFeature的属性上有一个RequestServicesFeature对象. That’s what’s responsible for creating the per-request scope.范围在第一次访问时创建. 似乎订单大致如下: > 所有这些都会导致已经确定每个请求范围是针对默认租户的情况,并且您无法真正更改它. 要解决此问题,您需要自己设置请求服务,以便它们考虑多租户. 听起来比实际情况更糟糕. 首先,我们需要对应用程序容器的引用.我们需要能够从应用程序级服务而不是请求服务来解析某些东西.我通过向您的Startup类添加静态属性并将容器保留在那里来做到这一点. public static IContainer ApplicationContainer { get; private set; } 接下来,我们将更改您的中间件看起来更像RequestServicesContainerMiddleware.您需要先设置HttpContext,以便您的租户ID策略有效.之后,您可以获取IServiceScopeFactory并遵循它们在RequestServicesContainerMiddleware中执行的相同模式. public class RequestMiddleware { private static readonly AsyncLocal<HttpContext> _context = new AsyncLocal<HttpContext>(); private readonly RequestDelegate _next; public RequestMiddleware(RequestDelegate next) { this._next = next; } public static HttpContext Context => _context.Value; public async Task Invoke(HttpContext context) { _context.Value = context; var existingFeature = context.Features.Get<IServiceProvidersFeature>(); using (var feature = new RequestServicesFeature(Startup.ApplicationContainer.Resolve<IServiceScopeFactory>())) { try { context.Features.Set<IServiceProvidersFeature>(feature); await this._next.Invoke(context); } finally { context.Features.Set(existingFeature); _context.Value = null; } } } } 现在,您需要一个启动过滤器来获取中间件.您需要一个启动过滤器,否则RequestServicesContainerMiddleware将在管道中运行得太早,并且已经开始从错误的租户范围开始解析. public class RequestStartupFilter : IStartupFilter { public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) { return builder => { builder.UseMiddleware<RequestMiddleware>(); next(builder); }; } } 将启动筛选器添加到服务集合的最开头.您需要在AutoRequestServicesStartupFilter之前运行启动过滤器. ConfigureServices最终看起来像这样: public IServiceProvider ConfigureServices(IServiceCollection services) { services.Insert(0,new ServiceDescriptor(typeof(IStartupFilter),typeof(RequestStartupFilter),ServiceLifetime.Transient)); services.AddMvc(); var builder = new ContainerBuilder(); builder.RegisterType<TestMultitenancyContext>().InstancePerTenant(); builder.Populate(services); var container = new MultitenantContainer(new MultitenantIdentificationStrategy(),builder.Build()); ApplicationContainer = container; return new AutofacServiceProvider(container); } 请注意插入呼叫,以便在启动过滤器之前将服务注册置于顶部. 新的运营顺序将是: >在app启动时…… >您的启动过滤器会将您的自定义请求服务中间件添加到管道中. >在请求期间…… >您的自定义请求中间件将根据入站请求信息设置请求服务. 我通过将租户ID切换为来自查询字符串而不是主机名来本地测试这个(因此我没有设置主机文件条目和所有爵士乐)并且我能够通过切换查询字符串参数来切换租户. 现在,您可以稍微简化一下.例如,通过直接对Program类中的Web主机构建器执行某些操作,您可以在没有启动过滤器的情况下逃脱.您可以在调用builder.Populate并跳过该Insert调用之前,使用ContainerBuilder注册您的启动过滤器.如果您不希望Autofac在系统中传播,则可以将IServiceProvider存储在Startup类属性中.如果您创建中间件实例并自己将容器作为构造函数参数传递,则可以在没有静态容器属性的情况下离开.不幸的是,我已经花了很多时间试图找出解决方法所以我将不得不将“优化它”作为读者的练习. 再次,对不起,这不清楚. I’ve filed an issue on your behalf to get the docs updated and maybe figure out a better way to do this that’s a little more straightforward. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – URL没有可用扩展名时重定向
- 在ASP.NET中,您如何处理会话和多个标签?
- dependency-injection – 从作用域服务工厂获取主机名
- ASP.NET Core 新建项目(Windows) - ASP.NET Core 基础教程
- asp.net-mvc – 如何自定义简单的成员资格提供者来处理我自
- asp.net字符串分割函数使用方法分享
- asp.net-mvc – 我可以在asp.net mvc中拥有多个site.master
- asp.net-mvc – 在MVC 3项目中使用T4MVC生成的代码编译错误
- asp.net – 从Google财经,雅虎金融或交易所获取股票报价
- asp.net-mvc – 具有指定操作的Response.RedirectToRoute