如何将IHttpContextAccessor注入Autofac TenantIdentificationStrategy [英] How to inject IHttpContextAccessor into Autofac TenantIdentificationStrategy

查看:642
本文介绍了如何将IHttpContextAccessor注入Autofac TenantIdentificationStrategy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将多租户应用程序从Webapi迁移到aspnet核心.在webapi版本中,我使用的是TenantIdentificationStrategy,它根据HttpContext上的请求路径来标识租户.

I am migrating my multitenant application from Webapi to aspnet core. In webapi version I was using TenantIdentificationStrategy that identified tenants based on request path on HttpContext.

移动到aspnet核心,我能够成功连接autofac.我无法弄清楚如何捆绑租户策略.我尝试将ConfigureServices中的IHttpContextAccessor作为

Moving to aspnet core, I am able to wire-up autofac successfully. I am not able to figure out how to wireup the tenant strategy. I tried injecting IHttpContextAccessor in ConfigureServices as

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 

我的策略看起来像这样

public class AssetClassIdentificationStrategy: ITenantIdentificationStrategy {
    private readonly IHttpContextAccessor _accessor;
    public AssetClassIdentificationStrategy(IHttpContextAccessor httpContextAccessor)
    {
        _accessor = httpContextAccessor;
    }
    public bool TryIdentifyTenant(out object tenantId) {
        tenantId = null;
        var context = _accessor.HttpContext;
        if (context != null && context.Request != null )){
            var matchRegex = new Regex(@"\/[\d,\.,\w]*\/(\w*)\/.*");
            var match = matchRegex.Match(context.Request.Path.ToString());
            if (match.Success) {
                tenantId = match.Groups[1].Value.ToLower();
            }
        }
        return tenantId != null;
    }
}

我看到的是HttpContextAccessor被正确注入,其中的HttpContext始终为null.因此,所有多租户服务都无法解决.

What I am seeing is that HttpContextAccessor is being injected correctly, where as HttpContext within it always null. As a result of this none of the multitenant services are being resolved.

四处寻找样本,但找不到适合该问题的任何东西. Autofacv3中曾经有一个RequestParameterTenantIdentificationStrategy,不再受支持.感谢任何帮助.

Looked around for samples, but couldn't find anything that fits the problem. There used to be a RequestParameterTenantIdentificationStrategy in Autofacv3 which is no longer supported. Appreciate any help with this.

修改 修复了代码和按要求添加Startup.cs的问题.

Edit Fixed issue with code and adding Startup.cs as requested.

public class Startup
{
    public Startup(IHostingEnvironment env) {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.Configure<CacheConfig>(Configuration.GetSection("Caching"),false);
        services.AddMvc();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddTransient<ITenantIdentificationStrategy,AssetClassIdentificationStrategy>();

        var builder = new ContainerBuilder();
        builder.Populate(services);
        builder.RegisterType<TenantInfo>().WithProperty("TenantName", "unknown").As<ITenantInfo>();

        var container = builder.Build();

        ITenantIdentificationStrategy tenantIdentificationStrategy;
        bool isMultiTenant = container.TryResolve(out tenantIdentificationStrategy);

        var mtc = new MultitenantContainer(tenantIdentificationStrategy, container);
        mtc.ConfigureTenant("pesonalLoans", b => {
            b.RegisterType<TenantInfo>().WithProperty("TenantName","pesonalLoans") .As<ITenantInfo>();
        });
        mtc.ConfigureTenant("retirement", b => {
            b.RegisterType<TenantInfo>().WithProperty("TenantName", "retirement").As<ITenantInfo>();
        });

        return mtc.Resolve<IServiceProvider>();

    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        LoggingConfig.Register(Configuration, loggerFactory);
        app.UseMvc();
    }
}


public class ValuesController : Controller {
    private ITenantInfo _tenant;
    public ValuesController(ITenantInfo tenant) {
        _tenant = tenant;
    }

    [HttpGet]
    public string Get()
    {
        return  _tenant.TenantName;
    }
}


public interface ITenantInfo {
    string TenantName { get; set; }
}
public class TenantInfo: ITenantInfo
{
    public string TenantName { get; set; }
}

编辑3 project.json

Edit 3 project.json

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.0-rc2-3002702",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Mvc": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc2-final",
    "Autofac": "4.0.0-rc2-240",
    "Autofac.Multitenant": "4.0.0-beta8-219",
    "System.IdentityModel.Tokens.Jwt": "5.0.0-rc2-305061149",
    "Autofac.Extensions.DependencyInjection": "4.0.0-rc2-240",
    "System.Reflection": "4.1.0-rc2-24027",
    "System.Reflection.Primitives": "4.0.1-rc2-24027",
    "System.Reflection.Extensions": "4.0.1-rc2-24027",
    "System.Reflection.TypeExtensions": "4.1.0-rc2-24027",
    "System.Reflection.Emit": "4.0.1-rc2-24027",
    "System.Reflection.Context": "4.0.1-rc2-24027",
    "System.Reflection.DispatchProxy": "4.0.1-rc2-24027",
    "System.Reflection.Emit.ILGeneration": "4.0.1-rc2-24027",
    "Microsoft.AspNetCore.Diagnostics": "1.0.0-rc2-final",
    "Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.Formatters.Json": "6.0.0-rc1-final",
  },

  "tools": {
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": {
      "version": "1.0.0-preview1-final",
      "imports": "portable-net45+win8+dnxcore50"
    }
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "dnxcore50",
        "portable-net45+win8"
      ]
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "runtimeOptions": {
    "gcServer": true
  },

  "scripts": {
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

推荐答案

当前还没有一种将内容注入租户识别策略的方法,因为该策略本身并不通过DI管道.

There's not currently a way to inject things into a tenant identification strategy because the strategy itself doesn't go through the DI pipeline.

IHttpContextAccessor通常仅支持 HttpContextAccessor 仍然是单例,通过从异步/线程本地上下文中获取信息来起作用.在启动时,您可以直接使用以下策略之一来重新制定策略:

IHttpContextAccessor is usually just backed with HttpContextAccessor which is a singleton anyway and acts by getting info from async/thread local context. You could just new-up your strategy with one of these directly when you're in startup:

var strat = new MyStrategy(new HttpContextAccessor());

请注意,最初提出该问题时,多租户与ASP.NET Core IServiceProvider系统交互的方式存在问题,也就是说没有.

Note that at the time the question was originally asked there was an issue with the way multitenancy interacted with the ASP.NET Core IServiceProvider system, which is to say, it didn't.

从那时起,我们发布了 4.0.0-rc3-309解决该问题的Autofac.Extensions.DependencyInjection软件包.

Since then, we've released 4.0.0-rc3-309 for the Autofac.Extensions.DependencyInjection package which remedies the issue.

更改是您需要将ConfigureServices更新为return new AutofacServiceProvider(mtc); ,并且不再执行return mtc.Resolve<IServiceProvider>();.

这篇关于如何将IHttpContextAccessor注入Autofac TenantIdentificationStrategy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆