2011-04-01 141 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 
    } 
}