IAuthenticationFilter 中的 C# Ninject Web API 异步查询导致实体框架中的多个操作错误

Posted

技术标签:

【中文标题】IAuthenticationFilter 中的 C# Ninject Web API 异步查询导致实体框架中的多个操作错误【英文标题】:C# Ninject Web API async query in IAuthenticationFilter causes multiple operations error in entity framework 【发布时间】:2017-10-27 14:39:41 【问题描述】:

我正在使用带有 Ninject 的 Web API 2,当我有多个并行 HTTP 调用时出现以下错误。

在前一个异步操作完成之前,在此上下文上启动了第二个操作。使用 'await' 确保在此上下文上调用另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的。

我之前没有收到此错误,从数据库中检索数据的所有代码都是异步的,所以我认为这是 Ninject 范围问题。

NinjectWebCommon

kernel.BindHttpFilter<MyAuthenticateFilter>(FilterScope.Action);

// Database context
kernel.Bind<IUnitOfWorkAsyncFactory>().To<UnitOfWorkAsyncFactory>().InRequestScope();
kernel.Bind<IUnitOfWorkAsync>().To<UnitOfWork>().InRequestScope();
kernel.Bind<IDataFactory>().To<DataFactory>().InRequestScope();

所有应用程序和域处理程序也是异步的,并使用相同的 DataFactoryUnitOfWorkAsyncFactoryIAuthenticationFilter 似乎存在线程问题。

用于DbContext 的工厂模式。

public class DataFactory : Disposable, IDataFactory

    private MyContext DbContext  get; set; 

    public IDataContextAsync GetDataContext()
    
        return DbContext ?? (DbContext = new MyContext());
    

    public void AfterDispose()
    
        DbContext = null;
    

    public DataFactory()
    

    

    public DataFactory(MyContext context)
    
        DbContext = context;
    

【问题讨论】:

你是不是不小心把async的东西一发不可收拾? 我看不到,尝试在IAuthenticationFilter 中的async Task AuthenticateAsync 方法上从数据库中读取会话实体时发生错误。当一个 http 调用触发读取并返回一个文件时会发生这种情况,该文件也标记为async 【参考方案1】:

我记得前段时间在 WebApi 中的过滤器注入问题和范围丢失。

据我所知,使用IDependencyResolver 的这个实现(不记得我在哪里得到它)解决了这个问题。

using System.Web.Http.Dependencies;

using global::Ninject.Syntax;

public class DependencyResolverWebApiNinject : DependencyScopeWebApiNinject, IDependencyResolver

    public DependencyResolverWebApiNinject(IResolutionRoot resolutionRoot)
        : base(resolutionRoot)
    
    

    public virtual IDependencyScope BeginScope()
    
        return this;
    

DependencyScopeWebApiNinject 在哪里:

using System;
using System.Collections.Generic;

using System.Linq;
using System.Web.Http.Dependencies;

using global::Ninject;
using global::Ninject.Infrastructure.Disposal;
using global::Ninject.Parameters;
using global::Ninject.Syntax;

public class DependencyScopeWebApiNinject : DisposableObject, IDependencyScope

    /// <summary>
    /// Initializes a new instance of the <see cref="DependencyScopeWebApiNinject"/> class.
    /// </summary>
    /// <param name="resolutionRoot">The resolution root.</param>
    public DependencyScopeWebApiNinject(IResolutionRoot resolutionRoot)
    
        this.ResolutionRoot = resolutionRoot;
    

    /// <summary>
    /// Gets the resolution root.
    /// </summary>
    /// <value>The resolution root.</value>
    protected IResolutionRoot ResolutionRoot
    
        get;
        private set;
    

    /// <summary>
    /// Gets the service of the specified type.
    /// </summary>
    /// <param name="serviceType">The type of the service.</param>
    /// <returns>The service instance or <see langword="null"/> if none is configured.</returns>
    public object GetService(Type serviceType)
    
        var request = this.ResolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return this.ResolutionRoot.Resolve(request).SingleOrDefault();
    

    /// <summary>
    /// Gets the services of the specifies type.
    /// </summary>
    /// <param name="serviceType">The type of the service.</param>
    /// <returns>All service instances or an empty enumerable if none is configured.</returns>
    public IEnumerable<object> GetServices(Type serviceType)
    
        return this.ResolutionRoot.GetAll(serviceType).ToList();
    

希望这会有所帮助

【讨论】:

我尝试使用它,但它导致了以下错误。 '使用从 ModelValidatorProvider 到 NinjectDefaultModelValidatorProvider 的绑定激活 ModelValidatorProvider 时出错在两个服务的构造函数之间检测到循环依赖。 似乎 Web API 2 不推荐使用此方法。GlobalConfiguration.Configuration.DependencyResolver = new DependencyResolverWebApiNinject(kernel); @Raybbo 除非您使用 Ninject 的 ModelValidatorProvider,否则您还应该将此行 kernel.Unbind&lt;ModelValidatorProvider&gt;(); 添加到您的 NinjectWebCommon 文件中

以上是关于IAuthenticationFilter 中的 C# Ninject Web API 异步查询导致实体框架中的多个操作错误的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC 控制器通过继承控制器来达到 过滤 并且多了一个IAuthenticationFilter

从 Web Api 2 IAuthenticationFilter AuthenticateAsync 方法设置 cookie

Asp Web Api 生命周期问题

DbContext 在使用异步任务方法时被释放

验证(Authentication)和授权(Authorization):

如果我有一个来自Web API 2项目的身份验证过滤器,我可以在WCF服务中重用它吗?