2011-04-01 8 views
8

Estoy comenzando una aplicación web con MVC3 y Ninject. Hay una dependencia que también necesito en el archivo Global.asax que debe ser singleton.Ninject -ing una dependencia en Global.asax

pensé que debería ser así:

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(); 
    } 

pero luego vi que _auth es nula cuando MvcApplication_AuthenticateRequest se llama.

Entonces tratado de esta manera:

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(); 
    } 

pero ahora puedo ver que el constructor está siendo llamado varias veces, por lo tanto, voy a tener varios iKernel, y supongo que los casos simples no serán tan Singleton en el alcance de mi aplicación.

¿Cómo debo hacerlo? ¿Usando una variable estática?

Respuesta

8

Esto es cómo lo hacemos, hice algunas pruebas y mi AuthService parece ir en su controlador de una sola vez:

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; 
         } 
        } 
       } 
      } 
     } 
} 

espero que ayude!

+0

¿No es una muerte el hecho de que está llamando a DependencyResolver en cada solicitud? – vtortola

+0

No lo creo, @Remo debería poder decirle más que a mí, pero dado que inyecté mi _authService en la mayoría de mi controlador en el constructor, probablemente haga lo mismo y no "cueste" que se mutque ... – VinnyG

+0

genial. Creo que esto funcionará hasta que @ Remo solucione el problema. Un millón de gracias. – vtortola

-1

Mueva el código del constructor al método Application_Start. Creo que incluso si se crean varias instancias de HttpApplication, Application_Start solo se llama una vez, y eso solo en la primera instancia. Avísame si ha resuelto tu problema.

Estos son los diversos controladores de eventos que potencialmente puede tener en su 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

No, no lo hace. Lo he hecho y cuando MvcApplication_AuthenticateRequest es llamada, _auth sigue siendo nulo :( – vtortola

4

La extensión MVC inyecta el HttpApplication por defecto. ¡Pero solo se puede usar la inyección de propiedad! Así que solo agrega una propiedad decorada con el atributo Inject.

+0

Eso tampoco funciona. _auth es nulo cuando se llama MvcApplication_AuthenticateRequest – vtortola

+2

@vtortola, ¿está utilizando la última versión de Ninject Mvc3? La propiedad debería verse de esta manera: [Inject] public ItUserAuthentication Auth {get; set;} – Talljoe

+0

Tengo "Ninject.Web.Mvc3-2.2.1.0-release-net-4.0.zip", creo que es la última versión. Lo intenté y no funcionó – vtortola

-1

¿Se puede usar la propiedad 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 
    } 
}