Ste*_*doo 4 c# asp.net simple-injector asp.net-web-api owin
无论如何都要访问当前主体,并且在请求使用Simple Injector进入控制器之前?我正在使用OWIN和Asp.net身份.
我有一个DbContext,我注入到我的控制器中,但是这个上下文将根据经过身份验证的用户获取它的连接字符串.这是我到目前为止,
container.RegisterWebApiRequest<TenantDbContext>();
container.RegisterWebApiRequest<ITenantConnectionStringProvider>(() => new TenantConnectionStringProvider(container));
Run Code Online (Sandbox Code Playgroud)
然后在我的TenantConnectionStringProvider中我有这个,
var request = container.GetCurrentHttpRequestMessage();
var principal = request.GetRequestContext().Principal as ClaimsPrincipal;
Run Code Online (Sandbox Code Playgroud)
但校长没有索赔.我意识到声明仅在控制器创建后才可用.这是否意味着它是不可能的,因为这一步是在创建控制器之前进行的?
编辑:这基本上是代码的其余部分:
WebApi控制器
public CampaignsController(TenantDbContext context, ILog log)
{
this.campaignService = campaignService;
this.log = log;
}
Run Code Online (Sandbox Code Playgroud)
租户上下文(仅从EF的DbContext继承):
public TenantDbContext(ITenantConnectionStringProvider provider)
: base(provider.GetConnectionString())
{
}
Run Code Online (Sandbox Code Playgroud)
在搞砸了一下后,我能够做到这一点,但感觉非常hacky ..我添加了一个在验证后发生的OWIN中间件.我不知道为什么,但我在这里有所有经过身份验证的用户信息,但是当它转到TenantConnectionStringProvider时,HttpRequestMessage上没有这些信息.
app.Use(async (context, next) =>
{
using (container.BeginExecutionContextScope())
{
CallContext.LogicalSetData("Claims", context.Authentication.User.Claims);
var request = (OwinRequest)context.Request;
await next();
}
});
Run Code Online (Sandbox Code Playgroud)
然后在我的TenantConnectionStringProvider中,我就这样做了,
public string GetConnectionString()
{
var context = (IEnumerable<Claim>)CallContext.LogicalGetData("Claims");
return "test";//get claim from context to get the connection string
}
Run Code Online (Sandbox Code Playgroud)
您可以注册Func<ClaimsPrincipal>(工厂)并将其注入您的TenantConnectionStringProvider班级:
public class TenantConnectionStringProvider : ITenantConnectionStringProvider
{
private readonly Func<ClaimsPrincipal> _claimsPrincipalFactory;
public TenantConnectionStringProvider(Func<ClaimsPrincipal> claimsPrincipalFactory)
{
_claimsPrincipalFactory = claimsPrincipalFactory;
}
public void TestMethod()
{
// Access the current principal
var principal = _claimsPrincipalFactory();
}
}
Run Code Online (Sandbox Code Playgroud)
注册应该是这样的(不确定......):
// Register your types, for instance using the scoped lifestyle:
container.RegisterSingleton<Func<ClaimsPrincipal>>(() =>
{
// Not sure of which one to use.
//return (ClaimsPrincipal)HttpContext.Current.User;
//return (ClaimsPrincipal)Thread.CurrentPrincipal;
return (ClaimsPrincipal)Context.User;
});
container.RegisterWebApiRequest<ITenantConnectionStringProvider, TenantConnectionStringProvider>();
Run Code Online (Sandbox Code Playgroud)
这是否意味着这是不可能的,因为此步骤发生在创建控制器之前?
绝对是您创建它的方式。我并不完全熟悉简单注入器,但我打赌使用Lazy<>可能会有好处:
var request = container.GetCurrentHttpRequestMessage();
var principal = new Lazy<ClaimsPrincipal>(() =>
{
return request.GetRequestContext().Principal as ClaimsPrincipal;
});
Run Code Online (Sandbox Code Playgroud)
未经测试,但是当您实际需要主值时(我假设稍后在同一类中的不同方法中),您可以使用它,principal.Value然后它会运行并检索您的ClaimsPrincipal. 当然,这些都是巨大的假设,因为没有代码可以查看所有内容是如何连接的。如果您可以提供如何获取 dbcontext 的连接字符串(如何连接),我也许可以为您提供完整的解决方案。