Ninject对ASP.net身份的IIS Web主机的依赖关系

时间:2014-10-15 16:57:59

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

我有一段时间让Ninject使用标准的ASP.net Identity解决方案。我使用的堆栈是WebApi 2.2和Ninject 3.2。

我正在使用生成的NinjectWebCommon.cs文件稍作修改,我将CreateKernel方法公之于众,所以我可以在OWIN管道中注册它。

 private static readonly Bootstrapper Bootstrapper = new Bootstrapper();
    private static IKernel _kernel;

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start()
    {

        DynamicModuleUtility.RegisterModule(typeof (OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof (NinjectHttpModule));
        Bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        Bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    public static IKernel CreateKernel()
    {
        if (_kernel != null) return _kernel;

        _kernel = new StandardKernel();
        try
        {
            _kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            _kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
            RegisterServices(_kernel);
            return _kernel;
        }
        catch
        {
            _kernel.Dispose();
            throw;
        }

    }

在我的Startup.Auth.cs文件中,为ASP.net身份配置了OWIN,我正在尝试使用以下设置 -

 public partial class Startup
{
    static Startup()
    {
        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            RefreshTokenProvider = new RefreshTokenProvider(),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(20),
#if DEBUG
            AllowInsecureHttp = true
#endif
        };
    }

    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static string PublicClientId { get; private set; }

    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        //allow cors
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        //use ninject in owin
        app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
        app.UseWebApi(GlobalConfiguration.Configuration);


        // Enable the application to use bearer tokens to authenticate users
        var opts = new OAuthBearerAuthenticationOptions
        {
            AuthenticationType = "Bearer",
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
            Provider = new QueryStringOAuthBearerProvider("access_token")
        };
        app.UseOAuthBearerAuthentication(opts);
        app.UseOAuthAuthorizationServer(OAuthOptions);
    }
}

我得到的问题是每当使用app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);应用程序抛出“Sequence contains no elements error”时,使用以下stacktrace -

[InvalidOperationException: Sequence contains no elements]
   System.Linq.Enumerable.Single(IEnumerable`1 source) +315
   Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() +87
   Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) +29
   Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) +194
   Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) +205
   Ninject.Web.Common.OwinHost.<Execute>d__1.MoveNext() +257
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21
   Microsoft.Owin.Cors.<Invoke>d__0.MoveNext() +1205
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21
   Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__5.MoveNext() +287
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21
   Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<DoFinalWork>d__2.MoveNext() +272
   System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +22
   Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow() +33
   Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +150
   Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +42
   System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +415
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

我在设置用于OWIN和IIS托管Web应用程序其余部分的ninject内核时是否做错了什么?

2 个答案:

答案 0 :(得分:1)

和你一样,我也花了很长时间来解决这个问题。尽管我试验了所有各种Ninject扩展程序集和大量的在线代码片段,但我仍然无法使推荐的配置工作,这些代码片段建议如何使用它们。如上所述,仅当OWIN配置为通过app.UseNinjectMiddleware()使用Ninject时才会发生异常。

最后,我通过删除ConfigureAuth()中的以下行来简单地从DI流程中删除了OWIN:

    app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
    app.UseWebApi(GlobalConfiguration.Configuration);

this answer中所述,我现在使用Ninject将所有必需的身份组件(UserManagerRoleManager等)注入使用它们的控制器中。

答案 1 :(得分:1)

我认为你不应该同时使用 Ninject.Web.WebApi.OwinHost Ninject.Web.WebApi.WebHost 。你只能选择一个。