【问题标题】:PerHttpRequestLifeTimeManager for Unity with Web API and OWINPerHttpRequestLifeTimeManager for Unity 与 Web API 和 OWIN
【发布时间】:2016-10-24 11:27:04
【问题描述】:

我有一个使用带有 OWIN 的 Web API 5.23 构建的 Web 服务。我使用 Unity 作为 IOC 容器。

此 Web 服务由每 2 秒触发一次 http 请求的 Windows 服务使用。

windows服务启动时,web服务抛出如下异常:

发生 System.NotSupportedException H结果=-2146233067 Message=在前一个异步操作完成之前在此上下文上启动了第二个操作。使用 'await' 确保在此上下文上调用另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的。

据我所知,两个线程正在尝试使用同一个 DbContext 实例,因此在每个请求上创建一个新的 DbContext 应该可以解决我的问题。

查看 Unity 提供的 LifeTimeManagers,似乎 TransientLifetimeManager 是自

以来的必经之路

TransientLifetimeManager。对于这个生命周期管理器,Unity 为每次调用 Resolve 或 ResolveAll 方法创建并返回请求类型的新实例。此生命周期管理器默认用于使用 RegisterType 方法注册的所有类型,除非您指定不同的生命周期管理器。

由于某种原因,这不起作用,我仍然遇到同样的异常。

经过一番搜索,我找到了PerRequestLifetimeManager 。但我不能使用它,因为我不想依赖 MVC。当我检查它的实现方式时,我注意到它依赖于 IHttpModule。我不确定是否可以使用它,因为我正在使用 OWIN 中间件来托管我的 Web 服务。

如何使用 OWIN 为 Web API 实现 PerRequestLifetimeManager?

详细信息以防我做错了:

 public static class MiddlewareContainer
{
    public static void Register(IUnityContainer container)
    {
        container.RegisterType<DbContext, LicenceDbContext>(new TransientLifetimeManager());
        container.RegisterType<IdentityDbContext<IdentityUser>, LicenceDbContext>(new TransientLifetimeManager());

        container.RegisterType<IOAuthAuthorizationServerProvider, LicenceAuthorizationProvider>(new TransientLifetimeManager(),
            new Interceptor<InterfaceInterceptor>(),
            new InterceptionBehavior<AuthorizationProviderLoggingInterceptionBehavior>());

        container.RegisterType<IDeploymentAuthRepository, DeploymentAuthRepository>(new TransientLifetimeManager());
        container.RegisterType(typeof (UserManager<>), typeof (UserManager<>) ,new TransientLifetimeManager());
        container.RegisterType(typeof (IUserStore<>), typeof (UserStore<>), new TransientLifetimeManager());

        container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
        container.RegisterType<IHttpActionResultProvider, HttpActionResultProvider>();
        container.RegisterType<IClaimsIdentityFactory, ClaimsIdentityFactory>();

        container.RegisterType<LoggingInterceptionBehavior, AuthorizationProviderLoggingInterceptionBehavior>();
        container.RegisterType<ILogger, Logger>();
        container.RegisterType<IIdentityProvider, IdentityProvider>();
        container.RegisterType<IIdentityProviderFactory, IdentityProviderFactory>();
        container.RegisterType<ILogger, Logger>();

        container.RegisterType(typeof (IRepository<>), typeof (Repository<>));
        container.RegisterType<IRepository<UserActivity>, UserActivityRepository>();
        container.RegisterType<IRepository<Licence>, LicenceRepository>();
        container.RegisterType<IJsonConverter, JsonConverter>();
        container.RegisterType<IEqualityComparer<Message>, MessageComparer>();
        container.RegisterType<System.Web.Http.ExceptionHandling.ExceptionLogger, GenericExceptionLogger>();
    }
}

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        var container = new UnityContainer();
        container.AddNewExtension<Interception>();

        MiddlewareContainer.Register(container);
        config.DependencyResolver = new UnityResolver(container);

        ConfigureFilters(config, container);
        ConfigureOAuth(app,container);

        WebApiConfig.Register(config);
        app.UseWebApi(config);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    }

【问题讨论】:

  • 我也想看到一个答案。我尝试了很长一段时间来让 Unity 在每个请求中都能正常运行,但它从来没有奏效,并导致 EF 和 DbContext 出现问题。我已经切换到 SimpleInjector 以在需要时完成此任务,但我真的很想让 Unity 工作。

标签: c# asp.net-web-api owin


【解决方案1】:

发现问题。它与 Unity 无关。在我正在调用的 Startup 类中

ConfigureOAuth(app,container);

从问题中发布的代码来看,无法知道这可能是一个问题。 (为此道歉)。

这里是方法的内容。

 public void ConfigureOAuth(IAppBuilder app, UnityContainer container)
    {
        OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
            Provider = container.Resolve<IOAuthAuthorizationServerProvider>()
        };

        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }

在实例化 OAuthAuthorizationServerOptions 时,我还必须实例化一个 Provider

该提供程序是 OWIN 管道的一部分,仅在服务器启动时实例化一次。每个传入的请求都会命中该提供者,从而导致上述错误。 (多个请求尝试使用相同的 DbContext)。

使 IOAuthAuthorizationServerProvider 线程安全解决了这个问题,但这不是理想的情况。

理想的解决方案是指定一个 providerFactory,该工厂将为每个请求创建一个新的提供者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 2015-04-08
    • 2014-05-24
    • 1970-01-01
    相关资源
    最近更新 更多