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
.
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>();
and my strategy looks like this
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; } }
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.
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.
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; } }
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%" ] } }