使用WebAPI 2解析器

时间:2018-04-05 06:59:32

标签: asp.net-web-api2 owin ninject

环境:ASP.NET WebAPI 2,NInject Web API(3.3.0.0)

用例:我正在使用OwinStartup类设置自定义Owin身份验证。该类使用ASP.NET Identity.IUserStore来设置用户。我的挑战是让配置的解析器查询此引用。但是,像MVC一样的解析器检索在WebAPI中不起作用

var userStore = DependencyResolver.Current.GetService(typeof(IUserStore<ExtendedUser, string>)) as IUserStore<ExtendedUser, string>;

我的启动配置如下: -

    public partial class Startup
    {
        System.Web.Http.Dependencies.IDependencyResolver resolver;

        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration httpConfig = new HttpConfiguration();

            // Due to "new" config, the underlying resolver gets empty
            this.resolver = httpConfig.DependencyResolver;

            this.ConfigureOAuthTokenGeneration(app);

            // ... other code removed

        }

        private void ConfigureOAuthTokenGeneration(IAppBuilder app)
        {
            // Fails due to resolver being empty
            var userStore = this.resolver.GetService(typeof(IUserStore<ExtendedUser, string>)) as IUserStore<ExtendedUser, string>;
            UserService.UserStore = userStore;  
            app.CreatePerOwinContext<UserService>(UserService.Create);

            // Other code removed
        }
    }

UserService类: -

public class UserService : UserManager<ExtendedUser, string>
{
    public UserService(IUserStore<ExtendedUser, string> store)
        : base(store)
    {
    }

    //[Ninject.Inject]
    public static IUserStore<ExtendedUser, string> UserStore { get; set; }

    public static UserService Create(IdentityFactoryOptions<UserService> options, IOwinContext context)
    {
        // var userStore = DependencyResolver.Current.GetService(typeof(IUserStore<ExtendedUser, string>)) as IUserStore<ExtendedUser, string>;
        var manager = new UserService(UserStore);
....
     }
}

接口在NInject配置中正确配置。 NInject正确设置,因为没有Owin集成,我可以解析我的服务。

kernel.Bind<Microsoft.AspNet.Identity.IUserStore<ExtendedUser, string>>().To<UserStore<ExtendedUser, string>>();

已尝试

  1. 使用“注入”参数
  2. 进行属性注入
  3. 将请求的UserManager与服务分开(这也需要一个需要明确初始化的构造函数
  4. 更新1:类似情况的另一个用例:我正在尝试在ExceptionFilter上设置自定义记录器,如下所示: -

       public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                // Exception handling
                config.Filters.Add(new ExceptionFilters());
            }
        }
      public class ExceptionFilters : ExceptionFilterAttribute
        {
           public ExceptionFilters(ZLogging.ILogger logger)
            {
                this.logger = logger;
            }
            public override void OnException(HttpActionExecutedContext context)
            {
    this.logger.Log(....)
            }
       }
    

    这里再次调用ExceptionFilters构造函数在WebApiConfig的Register方法中被阻止。

    在WebApiConfig中,我们可以使用传递的HttpConfiguration实例获取DependencyResolver,然后获取记录器服务。因此,这不是问题。但是无论何处无法访问HttpConfiguration,都会遇到解决问题的问题

    更新2 在启动课程中使用DI设置,如下所示: -

    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration httpConfig = new HttpConfiguration();
    
        httpConfig.DependencyResolver = new NinjectDependencyResolver(new Ninject.StandardKernel() );
        this.resolver = httpConfig.DependencyResolver;
    

    ....     }

    虽然这清除了Owin引用解析的问题,但是由于在执行周期中的Startup之前首先解析了Global.asax,它会破坏WebAPI中的异常过滤器(请参阅更新1):(

    需要帮助才能让解析器获得服务。可以提供任何必要的见解。

1 个答案:

答案 0 :(得分:0)

经过多次组合不同方法对代码进行了整整2天的测序,终于找到了一个可以解决问题的解决方案。发布我的解决方案,以便让其他人头疼:)

需要NuGet包

  • Ninject.Web.WebApi.WebHost(所有其他人都自动安装为依赖项)
  • WebActivatorEx(确保DI配置代码是第一个运行)

涉及的文件/类(按运行时执行顺序)

请注意,执行顺序对于依赖项在其他上下文需要时可用是非常重要的。

  1. NInjectWebCommon.cs(通过WebApi.Host组件为某些组件生成,其他一些组件可能需要手动设置)
  2. Global.asax(通常放在这里的一些代码可能会重新定位)
  3. Startup.cs(放置Owin代码)
  4. NInjectWebCommon (初始化DI框架,将其注入执行管道)。发布完整代码以帮助那些无法通过NInject.Web.WebAPi.WebHost Nuget包获取它的人

    命名空间将由WebActivator属性修饰为

    [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(NinjectWebCommon), "Start")]
    [assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(NinjectWebCommon), "Stop")]
    

    基础课

    public static class NinjectWebCommon
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();
    
        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }
        public static void Stop()
        {
            bootstrapper.ShutDown();
        }
        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
    
            RegisterServices(kernel);
            return kernel;
        }
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<ILogger>().To<NLogLogger>().InSingletonScope();
            // .... other services as below
            kernel.Bind<IEmployeeRepository>().To<EmployeeRepository>();
        }
    }
    

    Global.asax (有关路由和DI的所有其他配置将从此处删除)

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            Startup.HttpConfiguration = GlobalConfiguration.Configuration;
        }
    }
    

    Startup.cs (包含Owin + WebApi简报)

        public partial class Startup
        {
            public static HttpConfiguration HttpConfiguration { get; set; }
    
            public void Configuration(IAppBuilder app)
            {
                this.ConfigureOAuthTokenGeneration(app);
    
                this.ConfigureOAuthTokenConsumption(app);
    
                this.ConfigureWebApi();
    
                app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    
                app.UseWebApi(HttpConfiguration);
    
                HttpConfiguration.EnsureInitialized();
    
            }
    
            private void ConfigureOAuthTokenGeneration(IAppBuilder app)
            {
                var userStore = HttpConfiguration.DependencyResolver.GetService(typeof(IUserStore<ExtendedUser, string>)) as IUserStore<ExtendedUser, string>;
                UserService.UserStore = userStore;
                app.CreatePerOwinContext<UserService>(UserService.Create);
                app.CreatePerOwinContext<SignInService>(SignInService.Create);
    ...
            }
     ....  other methods removed for simplification
            private void ConfigureWebApi()
            {
                HttpConfiguration.MapHttpAttributeRoutes();
    
                WebApiConfig.Register(HttpConfiguration);
             }
      }
    

    <强> WebApiConfig

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
    
            // Exception handling
            var logger = config.DependencyResolver.GetService(typeof(ILogger)) as ILogger;
            config.Filters.Add(new ExceptionFilters(logger));
        }
    }
    

    (更新:冻结配置) 更新了启动以确保完成配置(由于设置了多个位置)

    罗和看哪 一切顺利:)如果这有帮助,请微笑并拥抱你的队友:)