2011-04-01 145 views
8

我开始使用MVC3和Ninject创建Web应用程序。在Global.asax文件中还需要一个依赖项,该文件需要是单例。在Global.asax中注入依赖关系

我认为它应该是这样的:

public class MvcApplication : NinjectHttpApplication 
{ 
    IUserAuthentication _auth; 

    public MvcApplication() 
    { 
     base.AuthenticateRequest += new EventHandler(MvcApplication_AuthenticateRequest); 
    } 

    protected override IKernel CreateKernel() 
    { 
     var _kernel = new StandardKernel(new SecurityModule()); 
     _auth = _kernel.Get<IUserAuthentication>(); 

     return _kernel; 
    } 

    void MvcApplication_AuthenticateRequest(object sender, EventArgs e) 
    { 
     _auth.ToString(); 
    } 

但后来我看到_auth为空时MvcApplication_AuthenticateRequest被调用。

然后我试图像这样:

public class MvcApplication : NinjectHttpApplication 
{ 
    ItUserAuthentication _auth; 
    IKernel _kernel; 

    public MvcApplication() 
    { 
     _kernel = new StandardKernel(new SecurityModule()); 
     _auth = _kernel.Get<IUserAuthentication>(); 
     base.AuthenticateRequest += new EventHandler(MvcApplication_AuthenticateRequest); 
    } 

    protected override IKernel CreateKernel() 
    { 
     return _kernel; 
    } 

    void MvcApplication_AuthenticateRequest(object sender, EventArgs e) 
    { 
     _auth.ToString(); 
    } 

但现在我可以看到,构造函数被调用多次,因此,我将有几个的iKernel,我想这个单实例不会那么单在我的应用范围内。

我应该怎么做?使用静态变量?

回答

8

这是我们如何做到这一点,我做了一些测试,我的AuthService似乎在他的控制器去只有一次:

public class MvcApplication : NinjectHttpApplication 
    { 

     public static void RegisterRoutes(RouteCollection routes) 
     { 
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

      routes.MapRoute(
       "Default", // Route name 
       "{controller}/{action}/{id}", // URL with parameters 
       new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 
      ); 

     } 

     protected override IKernel CreateKernel() 
     { 
      var kernel = new StandardKernel(); 
      kernel.Load(Assembly.GetExecutingAssembly()); 

      kernel.Bind<ISession>().To<MongoSession>().InRequestScope(); 
      kernel.Bind<IAuthenticationService>().To<AuthenticationService>().InSingletonScope(); 
      kernel.Bind<IMailer>().To<Mailer>().InRequestScope(); 
      kernel.Bind<IFileProvider>().To<MongoFileProvider>().InRequestScope(); 

      return kernel; 
     } 

     protected override void OnApplicationStarted() 
     { 
      base.OnApplicationStarted(); 

      AreaRegistration.RegisterAllAreas(); 
      RegisterRoutes(RouteTable.Routes); 
     } 

     protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
     { 
      if (HttpContext.Current.User != null) 
      { 
       if (HttpContext.Current.User.Identity.IsAuthenticated) 
       { 
        if (HttpContext.Current.User.Identity is FormsIdentity) 
        { 
         var id = (FormsIdentity) HttpContext.Current.User.Identity; 
         var ticket = id.Ticket; 
         var authToken = ticket.UserData; 
         var authService = (IAuthenticationService)DependencyResolver.Current.GetService(typeof(IAuthenticationService)); 
         var user = authService.GetUserForAuthToken(authToken); 
         if (user != null) 
         { 
          user.SetIdentity(HttpContext.Current.User.Identity); 
          HttpContext.Current.User = (IPrincipal) user; 
         } 
        } 
       } 
      } 
     } 
} 

希望它能帮助!

+0

这不是一个杀死事实,即在每个请求中调用DependencyResolver。 – vtortola 2011-04-15 09:57:53

+0

我不这么认为,@Remo应该能够告诉你比我多,但是因为我在构造函数中的大部分控制器中注入了我的_authService,它可能会做同样的事情,并且不会“花费”那个mutch ... – VinnyG 2011-04-15 14:34:12

+0

太棒了。我认为这将直到@Remo解决问题。太感谢了。 – vtortola 2011-04-16 14:51:21

-1

将代码从构造函数移到Application_Start方法。我相信即使创建了多个HttpApplication实例,Application_Start也只会被调用一次,而且仅在一次实例中调用。让我知道它是否解决了您的问题。

这些都是不同的事件处理程序,你可以潜在地在你的Global.asax.cs:

public class Global : System.Web.HttpApplication 
{ 
    public Global() 
    { 
     InitializeComponent(); 
    } 

    protected void Application_Start(Object sender, EventArgs e) 
    { 

    } 

    protected void Session_Start(Object sender, EventArgs e) 
    { 

    } 

    protected void Application_BeginRequest(Object sender, EventArgs e) 
    { 

    } 

    protected void Application_EndRequest(Object sender, EventArgs e) 
    { 

    } 

    protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
    { 

    } 

    protected void Application_Error(Object sender, EventArgs e) 
    { 

    } 

    protected void Session_End(Object sender, EventArgs e) 
    { 

    } 

    protected void Application_End(Object sender, EventArgs e) 
    { 

    } 

    #region Web Form Designer generated code 
    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor. 
    /// </summary> 
    private void InitializeComponent() 
    {  
    } 
    #endregion 
} 
+0

不,它不。我已经完成了,当MvcApplication_AuthenticateRequest被调用时,_auth仍然是null :( – vtortola 2011-04-01 11:45:14

4

MVC扩展在默认情况下将注入的HttpApplication。但只有属性注入才能使用!所以只需添加一个用Inject属性装饰的属性。

+0

这也不起作用。当调用MvcApplication_AuthenticateRequest时,_auth为null – vtortola 2011-04-01 16:01:04

+2

@vtortola,您是否使用最新版本的Ninject Mvc3?像这样: [注入] public ItUserAuthentication Auth {get; set;} – Talljoe 2011-04-02 16:46:24

+0

我得到了“Ninject.Web.Mvc3-2.2.1.0-release-net-4.0.zip”,我认为这是最后一个版本。它没有工作 – vtortola 2011-04-02 22:17:18

-1

您是否可以使用HttpApplication.Appliction属性?

public class MyHttpApplication : System.Web.HttpApplication 
{ 
    protected void Application_Start() 
    { 
     this.Application["auth"] = GetAuthFromContainer(); 
    } 

    protected void Application_AuthenticateRequest() 
    { 
     IUserAuthentication auth = (IUserAuthentication)this.Application["auth"]; 
     // auth != null 
    } 
}