如何在基于 HTTP header 的 OWIN 环境中配置动态连接字符串?

How to configure a dynamic connection string on a OWIN enviroment based on HTTP header?

我是 OWIN 和 IoC 的新手,现在我需要实现一个动态上下文,该上下文由基于 HTTP header 的 Simple Injector 解析,该 HTTP header 标识谁在调用我的 API .这种方法可能不是最好的方法,所以我也愿意接受另一种可能的解决方案。

这是我的 OWIN 启动 class:

public void Configuration(IAppBuilder app)
{
    var httpConfig = new HttpConfiguration();
    var container = new Container();
    string connectionString = string.Empty;

    container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

    ConfigureOAuthTokenGeneration(app);
    ConfigureOAuthTokenConsumption(app);

    app.Use(async (context, next) => 
    {
        var customHeader = context.Request.Headers.Get("customHeader");
        connectionString = "conStr";//get con based on the header, from a remote DB here
        await next.Invoke();
    });

    app.UseOwinContextInjector(container);

    container.Register<DbContext>(() => new MyDynamicContext(connectionString), 
        Lifestyle.Scoped);
    //container.Register ...;

    container.Verify();

    httpConfig.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

    ConfigureWebApi(httpConfig);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(httpConfig);
}

我遇到的问题是DI框架创建实例时连接字符串总是空的。

任何帮助将不胜感激。

在您的例子中,MyDynamicContext 和连接字符串都是运行时值。如 here 所述,不应将运行时数据注入组件。相反,您应该定义一个抽象,允许在构建对象图后检索运行时值。

在你的情况下,最好有一个允许检索 DbContext 的抽象,例如:

public interface IDbContextProvider {
    DbContext Context { get; }
}

DbContext 的使用者可以使用 IDbContextProvider 抽象来获取当前上下文。实现可能如下所示:

class DbContextProvider : IDbContextProvider {
    private readonly Func<DbContext> provider;
    public DbContextProvider(Func<DbContext> provider) { this.provider = provider; }
    public DbContext Context { get { return this.provider(); } }
}

而这个DbContextProvider的注册可以如下所示:

var provider = new DbContextProvider(() => GetScopedItem(CreateContext));
container.RegisterSingleton<IDbContextProvider>(provider);

static T GetScopedItem<T>(Func<T> valueFactory) where T : class {
    T val = (T)HttpContext.Current.Items[typeof(T).Name];
    if (val == null) HttpContext.Current.Items[typeof(T).Name] = val = valueFactory();
    return val;
}    

static DbContext CreateContext() {
    var header = HttpContext.Request.Headers.Get("custHeader");
    string connectionString = "conStr";//get con based on the header, from a remote DB here
    return new MyDynamicContext(connectionString);
}