【问题标题】:Ninject.Web.PageBase still resulting in null reference to injected dependencyNinject.Web.PageBase 仍然导致对注入依赖项的空引用
【发布时间】:2010-03-01 18:41:10
【问题描述】:

我有一个使用 Ninject 2.0 的 ASP.NET 3.5 WebForms 应用程序。但是,尝试使用 Ninject.Web 扩展向 System.Web.UI.Page 提供注入时,即使我切换到使用服务定位器提供引用(使用 Ninject ),没有问题。

我的配置(简单起见):

public partial class Default : PageBase // which is Ninject.Web.PageBase
{
    [Inject]
    public IClubRepository Repository { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        var something = Repository.GetById(1); // results in null reference exception.
    }
 }

... //global.asax.cs

public class Global : Ninject.Web.NinjectHttpApplication
{
    /// <summary>
    /// Creates a Ninject kernel that will be used to inject objects.
    /// </summary>
    /// <returns>
    /// The created kernel.
    /// </returns>
    protected override IKernel CreateKernel()
    {
        IKernel kernel =
        new StandardKernel(new MyModule());
        return kernel;

    }

..

...

public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind<IClubRepository>().To<ClubRepository>();
        //...
    }
}

通过服务定位器获取 IClubRepository 具体实例可以正常工作(使用相同的“MyModule”)。 IE。

  private readonly IClubRepository _repository = Core.Infrastructure.IoC.TypeResolver.Get<IClubRepository>();

我错过了什么?

[更新]终于回到了这个,它在经典管道模式下工作,但不是集成的。经典管道是必需的吗?

[更新 2] 连接我的 OnePerRequestModule 是问题(为清楚起见,在上面的示例中已删除):

    protected override IKernel CreateKernel()
    {
        var module = new OnePerRequestModule();
        module.Init(this);

        IKernel kernel = new StandardKernel(new MyModule());

        return kernel;
    }

...必须是:

    protected override IKernel CreateKernel()
    {
        IKernel kernel = new StandardKernel(new MyModule());

        var module = new OnePerRequestModule();
        module.Init(this);

        return kernel;
    }

因此解释了为什么我在集成管道下得到空引用异常(对于 Ninject 注入的依赖项,或者只是从 Ninject.Web.PageBase 继承的页面的页面加载 - 无论先出现的情况)。

【问题讨论】:

    标签: asp.net ninject webforms


    【解决方案1】:

    这相当令人费解,因为据我所知,您似乎已正确配置了所有内容。从您得到 Null Reference Exception 而不是 ActivationException 的事实来看,页面级注入似乎没有发生。通常这是由于被注入的属性的保护级别,但根据您的代码,那里没有问题。您可以尝试以下一些方法来帮助找出问题所在:

    1. 在 PageBase 类的 OnInit 方法中调用 Kernel.Inject(this) 来启动 Ninject 的属性注入。如果由于某种原因没有执行此方法,则可能会导致您看到的问题。您可以通过重写 RequestActivation() 方法进行进一步调查,该方法是调用以执行实际注入的方法(请务必调用 base.RequestActivation())。如果您的覆盖从未被调用,则 OnInit 存在问题。

    2. InjectAttribute 是在默认内核配置中设置的,因此不需要指定它,但是如果您想更加确定,可以通过执行类似的操作在内核设置中设置属性映射:

      IKernel kernel = new StandardKernel(new NinjectSettings { InjectAttribute = typeof(InjectAttribute) },new MyModule());

    3. PageBase 类用于注入的内核实例(同样应由 Global.asax.cs 中的 CreateKernel 覆盖实例化的内核实例)存储在 Ninject.Web 中的服务定位器类型对象中.内核容器。我会确保您可以在 KernelContainer 上看到 Kernel 属性,并且在您的 Page_Load 方法中它不为空。

    就洞察力而言,这就是我目前所拥有的一切。就像我说的那样,从这里看来,你所有的鸭子都穿好衣服并排成一排,所以它们应该可以工作了....

    祝你顺利找到问题。

    【讨论】:

    • 感谢您对可能的问题进行了彻底的讨论 - 非常有用。 1. 在 OnLoad 中进行了尝试,并连接了 Page_Load。结果相同。将尝试使用 base.RequestActivation() 和以下建议。总而言之,它不起作用很奇怪,但感谢您的提示 - 会得到结果。
    • 请注意,这适用于经典管道,但奇怪的是不适用于集成。结果 [NullReferenceException: Object reference not set to an instance of an object.] System.Web.PipelineStepManager.ResumeSteps(Exception error) +1216 System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) +113 System.Web。 HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +616
    • 这太令人震惊了...我想 Web 应用程序与集成管道的工作方式有一些细微的变化???这真是离奇。这可能值得向 Ninject 开发团队报告错误。
    【解决方案2】:

    这可能不是 Ninject 特有的。我可以在没有 IoC 的集成模式下运行相同的异常。我只有一个简单的 asp.net 应用程序,它只包含一个没有逻辑的 aspx 页面。

    在我的 global.asax 文件中,我有以下内容:

    public class Global : HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            this.EndRequest += new EventHandler(Global_EndRequest);
        }
    
        void Global_EndRequest(object sender, EventArgs e)
        {
            // do stuff
        }
    

    在集成管道模式下运行时,基本上订阅 application_start 中的事件会导致此异常。切换到经典管道或删除事件订阅和处理程序会使错误消失。我在 Win7 Enterprise 64bit 上运行 IIS 7.5。

    这可能无法解决您的具体问题,但我在这里发布,因为这是我将异常粘贴到谷歌时出现的唯一页面!当我被允许问一个问题时,我会将我的答案转移到一个单独的问题中。我还没有 stackoverflow 荣誉:(

    【讨论】:

    • Rob:我觉得这有点乱。为什么要尝试订阅应用程序启动事件中的事件?只需使用 Global 中已有的 Application_End 事件?或者,如果您尝试在每个请求结束时执行,那么 Application_EndRequest?
    • 其他与以前不同的integrated和application_start问题,见mvolo.com/blogs/serverside/archive/2007/11/10/…
    • 有人知道这里发生了什么吗?我也遇到了同样的问题,希望现在有人已经解决了。
    猜你喜欢
    • 1970-01-01
    • 2016-10-01
    • 2013-07-26
    • 1970-01-01
    • 2011-11-22
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多