关于 ASP.NET 代码隐藏模型的问题

发布于 2024-10-07 13:01:39 字数 3318 浏览 5 评论 0原文

我正在考虑 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() 方法完成了将控件引用绑定到控件实例这一脏活。

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

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

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

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

再次非常感谢。

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

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

default_aspx class(代表页面的最终类)<--- _Default class(类背后的代码)<--- System .Web.UI.Page

在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: 2010 年 12 月 16 日下午 45 点

来自此处

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

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

针对您的宝贵意见,我们将开始悬赏。 :)

I am thinking about the asp.net 2.0 code behind model.

After I drag a button onto my Default.aspx page, I got the following declaration in my Default.aspx.designer.cs file:

public partial class _Default {

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

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

And now it's OK for me to write the following code in Default.aspx.cs file:

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

But I am wondering, what I got is nothing but a declaration of Button1 variable of Button type, it hasn't been instanciated, how could this code run without trigging a Null Reference Exception?

I think there must exist some code like this somewhere:

Button1 = new Button();

But where is this code? When is this code executed? Who executes it?

Many thanks...

Update - 1 - 21:17 12/15/2010

I found 2 auto-generated file in a mysterious location C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\edd9f4a1\7f113408, they are:

App_Web_x_swwj6s.1.cs
App_Web_x_swwj6s.0.cs

I found code like below in the App_Web_x_swwj6s.0.cs file:

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

And this method is invoked in the below code:

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

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

And finally the above code is invoked in the following method:

protected override void FrameworkInitialize()

So I believed that the FrameworkInitialize() method is the one who did the dirty job of bind the control reference to a control instance.

To prove this, I intentionally wrote the following code in my code-behind file:

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

I hope there would be a Null Reference Exception when I click the button, but strange enough, the whole web site run smoothly.

Is it true that all the controls I declared in the aspx file are created with the FrameworkInitialize() method? Why there's no Null Reference Exception in the above scenario?

Many thanks again.

Update - 2 - 21:43 12/15/2010

I think I may find the explanation, I checked the final page class generated by ASP.NET with .NET reflector. Its deriving relation is like this:

default_aspx class (The ultimate class representing the page)<--- _Default class (the code behind class) <--- System.Web.UI.Page

And in the default_aspx class, I found this:

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

So, this could explain why my intention to set the Button1 to null failed.

Now, my question is, does the FrameworkInitialize() method has to be called at the very beginning of a page's life cycle so that we could use the control on the page afterwards.

Update - 3 - 3:45 PM 12/16/2010

From here:

Once the HTTP page handler class is
fully identified, the ASP.NET run time
calls the handler's ProcessRequest
method to process the request.
Normally, there is no need to change
the implementation of the method as it
is provided by the Page class.

This implementation begins by calling
the method FrameworkInitialize, which
builds the controls tree for the page.
The method is a protected and virtual
member of the TemplateControl
class—the class from which Page itself
derives. Any dynamically generated
handler for an .aspx resource
overrides FrameworkInitialize. In this
method, the whole control tree for the
page is built.

A bounty is started for your precious comments. :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

℉絮湮 2024-10-14 13:01:39

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

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

So what exactly do you want to get answers to now... to me it looks like you're answering most of your questions your self? :)

Regarding the FrameworkInitialize its easiest if you fire up Reflector and look at the code. Code is law! :) In here you'll see that System.Web.UI.TemplateControl.FrameworkInitialize()
will call a internal method named System.Web.Compilation.BuildResultNoCompileTemplateControlFrameworkInitialize(TemplateControl)which is doing the actual initialization of your control tree. This means that overriding FrameworkInitialize() and setting your Button1 to null doesn't have any effect, since that code will end up being run BEFORE the control tree is initialized.

迷路的信 2024-10-14 13:01:39

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

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

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

请参阅此链接这个

The page and its controls (including your button in this case) are instantiated by the webforms "view engine" before the OnLoad, etc events are fired.

Otherwise, you'd have to have an ISAPI filter or similar device intercept requests and create the page object and its controls before any events were fired. This is what the ASP.NET ISAPI DLL does, I think.

I haven't tried this, but you may be able to set a break point in the page's constructor to see the ::Controls[] list before anything is created, which I would expect to be empty (but the page life cycle link I've provided below will have a better explanation).

See this link or this one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文