【问题标题】:Question about ASP.NET Code Behind model关于模型背后的 ASP.NET 代码的问题
【发布时间】:2010-12-14 15:53:36
【问题描述】:

我正在考虑模型背后的 asp.net 2.0 代码。

在我将一个按钮拖到我的 Default.aspx 页面后,我在我的 Default.aspx.designer.cs 文件中得到了以下声明:

public partial class _Default {

    protected global::System.Web.UI.HtmlControls.HtmlForm form1;

    protected global::System.Web.UI.WebControls.Button Button1;
}

现在我可以在 Default.aspx.cs 文件中编写以下代码:

protected void Button1_Click(object sender, EventArgs e)
{
    Button1.Text = "clicked!";
}

但我想知道,我得到的只是一个Button类型的Button1变量的声明,它还没有被实例化,没有这个代码怎么能运行触发空引用异常

我认为某处一定存在这样的代码:

Button1 = new Button();

但是这段代码在哪里?这段代码什么时候执行?谁来执行?

非常感谢...

更新 - 1 - 21:17 12/15/2010

我在一个神秘的位置发现了 2 个自动生成的文件 C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\edd9f4a1\7f113408,它们是:

App_Web_x_swwj6s.1.cs
App_Web_x_swwj6s.0.cs

我在 App_Web_x_swwj6s.0.cs 文件中找到如下代码:

        private global::System.Web.UI.WebControls.Button @__BuildControlButton1()
         {
            global::System.Web.UI.WebControls.Button @__ctrl;                
            @__ctrl = new global::System.Web.UI.WebControls.Button();
            //....
            this.Button1 = @__ctrl;
            return @__ctrl;
          }

并且这个方法在下面的代码中被调用:

private global::System.Web.UI.HtmlControls.HtmlForm @__BuildControlform1()
{
  //....
  global::System.Web.UI.WebControls.Button @__ctrl1;

  @__ctrl1 = this.@__BuildControlButton1();
  //......
}

最后通过下面的方法调用上面的代码:

protected override void FrameworkInitialize()

所以我相信 FrameworkInitialize() 方法是将控件 reference 绑定到控件 instance 的脏活.

为了证明这一点,我特意在我的代码隐藏文件中编写了以下代码:

protected override void FrameworkInitialize()
{
    this.Button1 = null;
}

我希望当我点击按钮的时候会有一个空引用异常,但奇怪的是,整个网站运行顺利。

难道我在aspx文件中声明的所有控件都是用FrameworkInitialize()方法创建的吗?为什么上面的场景没有空引用异常?

再次感谢。

更新 - 2 - 21:43 12/15/2010

我想我可能会找到解释,我检查了 ASP.NET 使用 .NET 反射器生成的最终页面类。它的推导关系是这样的:

default_aspx 类(代表页面的终极类)_Default 类(类背后的代码)

在 default_aspx 类中,我发现了这个:

protected override void FrameworkInitialize()
{
    base.FrameworkInitialize();  // Button1=null is executed here.
    this.__BuildControlTree(this); // Here Button1 is STILL set to an instance.
    base.AddWrappedFileDependencies(__fileDependencies);
    base.Request.ValidateInput();
}

所以,这可以解释为什么我打算将 Button1 设置为 null 失败。

现在,我的问题是,是否必须在页面生命周期的最开始调用 FrameworkInitialize() 方法,以便之后我们可以在页面上使用控件。

更新 - 3 - 2010 年 12 月 16 日下午 3:45

来自here

一旦 HTTP 页面处理程序类 完全确定,ASP.NET 运行时 调用处理程序的 ProcessRequest 处理请求的方法。 正常情况下不需要更改 方法的实现 由 Page 类提供。

这个实现首先调用 方法 FrameworkInitialize,它 为页面构建控件树。 该方法是受保护的和虚拟的 模板控件的成员 类——Page 本身所在的类 导出。任何动态生成的 .aspx 资源的处理程序 覆盖 FrameworkInitialize。在这个 方法,整个控制树为 页面已构建。

为您宝贵的 cmets 开始赏金。 :)

【问题讨论】:

标签: asp.net code-behind


【解决方案1】:

那么,您现在究竟想得到什么答案……在我看来,您的大部分问题似乎都是您自己回答的? :)

关于FrameworkInitialize,如果您启动 Reflector 并查看代码,则最简单。代码就是法律! :) 在这里你会看到System.Web.UI.TemplateControl.FrameworkInitialize() 将调用一个名为System.Web.Compilation.BuildResultNoCompileTemplateControlFrameworkInitialize(TemplateControl) 的内部方法,它正在对您的控制树进行实际初始化。这意味着覆盖 FrameworkInitialize() 并将 Button1 设置为 null 不会产生任何影响,因为该代码最终会在控制树初始化之前运行。

【讨论】:

  • 感谢您的回复。我只是不确定我的答案。 :) 因此,任何相关的 cmets 都会开始赏金。
【解决方案2】:

页面及其控件(在这种情况下包括您的按钮)在 OnLoad 等事件被触发之前由 webforms“视图引擎”实例化。

否则,您必须有一个 ISAPI 过滤器或类似的设备拦截请求并在 任何 事件被触发之前创建页面对象及其控件。我认为这就是 ASP.NET ISAPI DLL 的作用。

我还没有尝试过,但是您可以在页面的构造函数中设置一个断点,以便在创建任何内容之前查看::Controls[] 列表,我希望它是空的(但页面生命周期链接我在下面提供的会有更好的解释)。

this linkthis one

【讨论】:

  • 谢谢。根据您的回复和 Joel Etherton 的回复,现在我知道实例化代码在哪里。但仍不确定该代码何时执行。
  • 当你说when that code is executed时,你指的是页面/控件实例化还是事件处理程序?
  • 这整个过程看ASP.NET MVC就更清楚了。删除了几层抽象,让您更熟悉请求/实例化/渲染/回复过程。 (并不是说 MVC 比 Web 表单更好/更差 - 它只是一个更透明的过程。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-29
相关资源
最近更新 更多