关于ASP.NET Code Behind模型的问题

时间:2010-12-14 15:53:36

标签: asp.net code-behind

我正在思考模型背后的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变量的声明,它还没有 instanciated ,这个代码怎么能运行而没有触发空引用异常

我认为某处必须存在这样的代码:

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()方法是将控件引用绑定到控件实例的脏工作者

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

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

我希望单击按钮时会出现Null Reference Exception,但奇怪的是,整个网站运行顺畅。

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

再次感谢。

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

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

default_aspx class(代表页面的终极类)< --- _Default 类(类后面的代码)< --- System.Web.UI 。第

在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 - 3:45 PM 12/16/2010

来自here

  

HTTP页面处理程序类是   完全确定,ASP.NET运行时   调用处理程序的ProcessRequest   处理请求的方法。   通常,没有必要改变   这个方法的实现就像它一样   由Page class提供。

     

此实现从调用开始   方法FrameworkInitialize,其中   构建页面的控件树。   该方法是受保护的和虚拟的   TemplateControl的成员   class - Page本身的类   派生。任何动态生成的   .aspx资源的处理程序   覆盖FrameworkInitialize。在这   方法,整个控制树为   页面已建成。

为了您宝贵的意见而开始赏金。 :)

2 个答案:

答案 0 :(得分:3)

在触发OnLoad等事件之前,页面及其控件(在本例中包括您的按钮)由webforms“视图引擎”实例化。

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

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

请参阅this linkthis one

答案 1 :(得分:3)

那么你现在究竟想要得到什么答案......对我来说,看起来你的大部分问题都是你自己回答的? :)

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