【问题标题】:Web Api Autofac InstancePerRequestWeb Api Autofac InstancePerRequest
【发布时间】:2016-01-27 12:29:19
【问题描述】:

我的 Web Api 项目中有一个自定义 AuthorizationFilter 属性,就像这样

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class GenericAuthenticationFilter :  AuthorizationFilterAttribute
{

    /// <summary>
    /// Public default Constructor
    /// </summary>
    public GenericAuthenticationFilter()
    {
    }

    private readonly bool _isActive = true;

    /// <summary>
    /// parameter isActive explicitly enables/disables this filter.
    /// </summary>
    /// <param name="isActive"></param>
    public GenericAuthenticationFilter(bool isActive)
    {
        _isActive = isActive;
    }



    /// <summary>
    /// Checks basic authentication request
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnAuthorization(HttpActionContext filterContext)
    {

        if (!_isActive) return;
        var identity = FetchAuthHeader(filterContext);
        if (identity == null)
        {
            ChallengeAuthRequest(filterContext);
            return;
        }
        var genericPrincipal = new GenericPrincipal(identity, null);
        Thread.CurrentPrincipal = genericPrincipal;
        if (!OnAuthorizeUser(identity.Name, identity.Password, filterContext))
        {
            ChallengeAuthRequest(filterContext);
            return;
        }

        base.OnAuthorization(filterContext);
    }

我的 StartUpClass 是这样的

  public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
        // Get your HttpConfiguration. In OWIN, you'll create one
        // rather than using GlobalConfiguration.
        var config = new HttpConfiguration();
        WebApiConfig.Register(config);
        IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
        config.DependencyResolver =
        new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
        // Register your Web Api controllers.
        IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
        IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
        IoC.Instance.RegisterWebApiModelBinderProvider();
        IoC.Instance.RegisterWebApiFilterProvider(config);
        // Register the Autofac middleware FIRST, then the Autofac Web API middleware,
        // and finally the standard Web API middleware.
        app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
        app.UseAutofacWebApi(config);
        app.UseWebApi(config);

    }
}

我的所有依赖关系都解决的IoC类是这样的

public class IoC : ContainerBuilder
{

    /// <summary>
    /// 
    /// </summary>
    private readonly static IoC _instance = new IoC();

    /// <summary>
    /// 
    /// </summary>
    private static object _lock;

    /// <summary>
    /// 
    /// </summary>
    private IContainer _componentsContainer;

    /// <summary>
    /// 
    /// </summary>
    public static IoC Instance
    {
        get
        {
            return _instance;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public IContainer GetComponentsContainer()
    {
        if (_componentsContainer == null)
        {
            lock (_lock)
            {
                if (_componentsContainer == null)
                    _componentsContainer = this.Build();
            }
        }

        return _componentsContainer;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T Resolve<T>() where T : class
    {
        return GetComponentsContainer().Resolve<T>();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public ILifetimeScope BeginLifetimeScope()
    {
        return GetComponentsContainer().BeginLifetimeScope();
    }

    /// <summary>
    /// 
    /// </summary>
    private IoC()
    {
        _lock = new object();
        ConfigureDependencies();
    }

    /// <summary>
    /// 
    /// </summary>
    private void ConfigureDependencies()
    {
        //Configure all your depedendencies here!!

        //Database connection
        var connectionString = ConfigurationManager.ConnectionStrings["DBConnectionStringName"].ConnectionString;
        this.Register(c => new SqlConnection(connectionString)).As<IDbConnection>().InstancePerRequest();// InstancePerLifetimeScope();

        //Database Connection OrmLite
        OrmLiteConfig.DialectProvider = SqlServerDialect.Provider;
        //Register Repositories
        this.RegisterType<Repository>().As<IRepository>().InstancePerRequest();// InstancePerLifetimeScope();
        // Register Services
        this.RegisterType<UserService>().As<IUserService>().InstancePerRequest();// InstancePerLifetimeScope();
        this.RegisterType<TokenService>().As<ITokenService>().InstancePerRequest();
        this.RegisterType<DKMenuService>().As<IDKMenuService>().InstancePerRequest();// InstancePerLifetimeScope();
        this.RegisterType<DKGRIDTblService>().As<IDKGRIDTblService>().InstancePerRequest();// InstancePerLifetimeScope();
        this.RegisterType<FKService>().As<IFKService>().InstancePerRequest();// InstancePerLifetimeScope();
        this.RegisterType<LOVService>().As<ILOVService>().InstancePerRequest();// InstancePerLifetimeScope();
        this.RegisterType<JobService>().As<IJobService>().InstancePerRequest();// InstancePerLifetimeScope();
        this.RegisterType<MADEService>().As<IMADEService>().InstancePerRequest();// InstancePerLifetimeScope();

    }

}

我用这个过滤器装饰我的控制器

[GenericAuthenticationFilter]
    public AuthenticateController(ITokenService tokenService)
    {
        _tokenService = tokenService;
    }

我的问题是 GenericAuthenticationFilter 的 OnAuthorazation 方法永远不会被触发。 如果在 IoC 类上我将 InstancePerRequest 更改为 InstancePerLifetimeScope 一切正常,但我希望我的依赖项能够按请求工作

有什么想法吗?

【问题讨论】:

    标签: c# attributes asp.net-web-api2 autofac


    【解决方案1】:

    我不确定这是您的问题的一部分还是全部,但是...您只能构建一次ContainerBuilder。在Startup.Configuration() 我在第 11-12 行看到:

    config.DependencyResolver =
    new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
    

    IoC.Instance.GetComponentsContainer() 调用Build() 来创建容器。

    但仅仅两行之后,我看到您正在向容器中添加更多组件,然后我看到第二个调用:

    app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
    

    根据您的代码,这将是在您添加新注册之前构建的同一个容器。容器不会包含 API 控制器、模型绑定器或过滤器提供程序。

    我实际上不确定为什么您没有比现在遇到的问题更多

    尝试移动容器的设置(对IoC.Instance.GetComponentsContainer()的调用)直到一直到最后,在您完成注册所有依赖项之后.

    【讨论】:

      【解决方案2】:

      唯一有效的配置如下

      public class Startup
      {
          public void Configuration(IAppBuilder app)
          {
              // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
              // Get your HttpConfiguration. In OWIN, you'll create one
              // rather than using GlobalConfiguration.
              var config = new HttpConfiguration();
              WebApiConfig.Register(config);
              // Register your Web Api controllers.
              IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
              IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
              IoC.Instance.RegisterWebApiModelBinderProvider();
      
              config.DependencyResolver =
              new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
              // Register your Web Api controllers.
              //IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
              //IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
              //IoC.Instance.RegisterWebApiModelBinderProvider();
      
              // Register the Autofac middleware FIRST, then the Autofac Web API middleware,
              // and finally the standard Web API middleware.
              app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
              app.UseAutofacWebApi(config);
              app.UseWebApi(config);
      
          }
      }
      

      我仍然不确定它是否正确。 使用示例。我有一个像下面这样的过滤器

      public class ApiAuthenticationFilter : GenericAuthenticationFilter
      {
      
          /// <summary>
          /// Default Authentication Constructor
          /// </summary>
          public ApiAuthenticationFilter()
          {
      
          }
      

      }

      此过滤器中的方法正在使用这样解析的服务

      protected override bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
          {
              var provider = actionContext.Request.GetDependencyScope().GetService(typeof(IUserService)) as IUserService;
      

      }

      另一方面,我的控制器没有无参数构造函数,并且依赖关系会自动解析

      public class DKMenuController : ApiController
      {
          #region Private variable.
      
          private readonly ITokenService _tokenService;
          private readonly IDKMenuService _dkMenuService;
          private readonly IUserService _userservice;
          private const string Token = "Token";
      
          #endregion
      
          #region Public Constructor
      
          /// <summary>
          /// Public constructor to initialize DKMenu service instance
          /// </summary>
          public DKMenuController(ITokenService tokenService, IUserService userservice, IDKMenuService dkMenuService)
          {
              _tokenService = tokenService;
              _dkMenuService = dkMenuService;
              _userservice = userservice;
          }
      

      }

      我不知道它是否正确,但它有效

      【讨论】:

        猜你喜欢
        • 2018-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多