autofac - 有没有办法使用 autofac 在 asp.net 核心中注册特定于租户的控制器?
问题描述
我正在开发一个基于 asp.net core 3.1 + Autofac 作为 DI 的应用程序。现在我想实现多租户功能。我能够注册租户特定服务,并且它按预期工作。
我想要实现的是注册特定于租户的控制器以覆盖在主/应用程序级别容器中注册的默认控制器。
我已注册自定义 IApplicationFeatureProvider 以仅注册主控制器。
这是代码。
//Startup.cs
public class StartUp
{
void ConfigureServices(IServiceCollection services)
{
services.AddControllers().ConfigureApplicationPartManager(apm =>
{
apm.FeatureProviders.RemoveAt(0); //remove default controller feature provider
apm.FeatureProviders.Add(new MyControllerFeatureProvider()); //register custom provider
}).AddControllersAsServices();
services.AddAutofacMultitenantRequestServices();
//rest of the configuration
}
public void ConfigureContainer(ContainerBuilder builder)
{
//registration of global or main services
builder.RegisterType<MyTenantIdentificationStrategy>()
.As<ITenantIdentificationStrategy>().SingleInstance(); //Get Tenant from request header
builder.Register(container =>
{
ITenantIdentificationStrategy strategy =
container.Resolve<ITenantIdentificationStrategy>();
// tenant resolution code
return new Tenant();
}).InstancePerLifetimeScope();
}
public static MultitenantContainer ConfigureMultitenantContainer(IContainer container)
{
var strategy <-- resolved from container
MultitenantContainer mtc = new MultitenantContainer(strategy, container);
mtc.ConfigureTenant(1, cb => {
cb.RegisterType<IP.Controllers.Extended.HomeController>).InstancePerLifetimeScope();
});
return mtc;
}
}
//HomeController.cs
namespace IP.Controllers
{
[Route("[controller]")]
public class HomeController : ControllerBase
{
}
[Route("Get")
public IActionResult Get()
{
return new JsonResult(new {Main = true});
}
}
//HomeController1.cs
namespace IP.Controllers.Extended <-- different namespace
{
[Route("[controller]")]
public class HomeController : ControllerBase
{
}
[Route("Get")
public IActionResult Get()
{
return new JsonResult(new {Main = false});
}
}
//program.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
http://localhost:8082/Home/Get [Without tenantid in header]
http://localhost:8082/Home/Get [Without tenantid=1 in header]
在这两种情况下,主家庭控制器都解决了不是特定于租户的..
任何帮助都将不胜感激。
解决方案
回答我自己的问题,
路由和控制器选择由 Asp.Net Core 处理,而不是由 Autofac 处理。
我在 ConfigureTenant 方法中注册特定于租户的控制器。Asp.Net Core Framework 不知道这些控制器。因此,对于给定的路由框架,总是选择注册控制器而不是在 ConfigureTenant 方法中注册的扩展控制器。
所以首先我删除了自定义应用程序功能提供程序。现在,当前程序集中的所有控制器都已注册。然后从 ConfigureTenant 方法中删除了控制器的单独注册。现在框架抛出歧义异常,因为有两个具有相同路由的控制器。
从堆栈跟踪中,我发现 EndPointResolver 实现正在引发歧义异常。因为我们可以为 EndPointResolver 提供我们自己的实现,所以我创建自定义 EndPointResolver 并注册它。
现在在路由选择期间,如果在选择控制器时存在歧义,我只需从请求标头中检索租户信息,并基于 Tanent 我正在处理歧义异常。
我不确定这是否是正确的方法,但现在我可以在不同的命名空间/程序集中注册具有相同名称 [相同路由] 的控制器。
推荐阅读
- c# - 使用带有逗号 C# 的文本框过滤 GridView
- python - mkvirtualenv 运行没有错误,但没有在 zsh 中创建环境
- javascript - 发送数据时 history.push() 不起作用
- ios - 为什么默认情况下符合 Swift 协议的值被视为值类型?
- facebook - 使用 Facebook Flutter 登录,如何更改我的代码?
- mysql - 我在mysql中的表有什么问题?
- swift - 错误:旧版构建系统不支持使用 xcframeworks
- php - Mollie webhook 没有被调用?
- asp.net-core - .net 核心获取位于 cloudflare 代理后面的 RemoteIpAddress.MapToIPv4()
- javascript - 通过 socket.io (JavaScript & FileReader) 上传文件