环境: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:类似情况的另一个用例:我正在尝试在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):(
需要帮助才能让解析器获得服务。可以提供任何必要的见解。
答案 0 :(得分:0)
经过多次组合不同方法对代码进行了整整2天的测序,终于找到了一个可以解决问题的解决方案。发布我的解决方案,以便让其他人头疼:)
需要NuGet包
涉及的文件/类(按运行时执行顺序)
请注意,执行顺序对于依赖项在其他上下文需要时可用是非常重要的。
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));
}
}
(更新:冻结配置) 更新了启动以确保完成配置(由于设置了多个位置)
罗和看哪 一切顺利:)如果这有帮助,请微笑并拥抱你的队友:)