Добавление зависимости в Global.asax

Я запускаю веб-приложение с MVC3 и Ninject. В файле 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 имеет значение null, когда вызывается 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, и я предполагаю, что одноэлементные экземпляры не будут такими одноэлементными в моем приложении.

Как я должен это делать? Использование статической переменной?


person vtortola    schedule 01.04.2011    source источник


Ответы (4)


Вот как мы это делаем, я провел некоторое тестирование, и мой 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;
                        }
                    }
                }
            }
        }
}

Надеюсь, поможет!

person VinnyG    schedule 13.04.2011
comment
разве это не убийственный факт, что DependencyResolver вызывается в каждом отдельном запросе. - person vtortola; 15.04.2011
comment
Я так не думаю, @Remo должен быть в состоянии сказать вам больше, чем я, но поскольку я вставляю свой _authService в большую часть моего контроллера в конструкторе, он, вероятно, делает то же самое и не стоит столько... - person VinnyG; 15.04.2011
comment
отличный. Я думаю, что это будет делаться до тех пор, пока @Remo не решит проблему. Бесконечно благодарен. - person vtortola; 16.04.2011
comment
рад, что это помогает, мне приятно :) - person VinnyG; 16.04.2011

Расширение MVC по умолчанию внедряет HttpApplication. Но можно использовать только внедрение свойств! Так что просто добавьте свойство, украшенное атрибутом Inject.

person Remo Gloor    schedule 01.04.2011
comment
Это тоже не работает. _auth имеет значение null, когда вызывается MvcApplication_AuthenticateRequest - person vtortola; 01.04.2011
comment
@vtortola, вы используете последнюю версию Ninject Mvc3? Свойство должно выглядеть следующим образом: [Inject] public ItUserAuthentication Auth { get; набор; } - person Talljoe; 02.04.2011
comment
У меня есть Ninject.Web.Mvc3-2.2.1.0-release-net-4.0.zip, думаю последняя версия. Я пробовал это, и это не сработало - person vtortola; 03.04.2011
comment
@vtortola Я посмотрел код. С введением пакета NuGet эта функция была нарушена. Поскольку в настоящее время я все равно обновляю пакеты NuGet до NuGet 1.2, я исправлю это в ближайшие дни. - person Remo Gloor; 14.04.2011
comment
Кстати, дайте мне крик, когда вы исправите это: D. бесконечно благодарен :) - person vtortola; 15.04.2011
comment
@vtortola Исправлено в Ninject.Extensions.MVC3 V2.2.2.0 - person Remo Gloor; 10.05.2011
comment
@Remo Gloor Это странно, я только что получил последнюю версию через Nuget (хотя, что интересно, Ninject nuget — это версия 2.2.1.4, в то время как ninject.org имеет версию 2.2.2.0, Ninject.MVC3 через Nuget — 2.2.2.0) и использую внедрение свойств, например: [Inject] public ILogger Logger { get; набор; } по-прежнему приводит к нулевой ссылке в Application_Start. Последняя версия Nuget не обновляется или? И я предполагаю, что под Ninject.Extensions.MVC3 v2.2.2.0 вы имели в виду Ninject.MVC3 v2.2.2.0. - person Ted; 28.05.2011
comment
Веб-сайт немного отстает (2.2.0.0), потому что его сложно обновить. MVC3 и Ninject не имеют одинаковых версий. Они обновляются индивидуально. Но все комбинации версий 2.2.x.x будут работать вместе. На github и nuget вы всегда найдете последнюю версию. Вероятно, они отличаются номером сборки, но в данном случае они построены с использованием одного и того же исходного кода, и в этом случае изменились только сценарии сборки или модульные тесты. - person Remo Gloor; 28.05.2011
comment
@RemoGloor Эй, Ремо, это работает с использованием репозиториев, привязанных к InRequestScope? Похоже, что после того, как я попытался добавить инъекцию свойства репозитория в global.asax, я начал получать ObjectContext, который уже удалил ошибки в моих приложениях. Нет проблем, если я удалю инъекцию свойства, хотя... - person B Z; 20.02.2012
comment
@B Z Внедрение объекта с временем жизни запроса в объект с более длительным временем жизни не имеет смысла. Объект должен зависеть только от объектов с таким же или более длительным жизненным циклом. - person Remo Gloor; 20.02.2012
comment
@RemoGloor ах, кажется, я вижу недостающую ссылку ... значит, время жизни для HttpApplication не InRequestScope? Я не смотрел на src, каково время жизни HttpApplication? Мой вариант использования должен быть связан с аутентификацией. У меня есть репо, чтобы получить информацию о пользователе для пользовательского удостоверения. Запрашивается у PostAuthenticate - person B Z; 20.02.2012
comment
@B Z HttpApplication управляется IIS. Обычно они повторно используются для нескольких запросов, но их можно удалить и создать заново в течение срока службы приложения. Так что это что-то среднее между запросом и синглтоном. Подробную информацию смотрите в msdn. - person Remo Gloor; 21.02.2012

Переместите код из конструктора в метод Application_Start. Я считаю, что даже если создается несколько экземпляров HttpApplication, Application_Start вызывается только один раз, и это тоже только для 1-го экземпляра. Дайте мне знать, если это решило вашу проблему.

Это различные обработчики событий, которые вы потенциально можете иметь в своем 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
}
person Zasz    schedule 01.04.2011
comment
Нет, это не так. Я сделал это, и когда вызывается MvcApplication_AuthenticateRequest, _auth по-прежнему имеет значение null :( - person vtortola; 01.04.2011

Можно ли использовать свойство HttpApplication.Application?

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
    }
}
person John Wathen    schedule 13.04.2011