服务器控件

转载 2006年05月31日 15:51:00
对这个概念很多人有误解。以为凡是 WebControl 都必须放在 <form runat="server"></form> 里面。比如:http://community.csdn.net/Expert/topic/3848/3848189.xml?temp=.1163141

先让我们来做几个试验。
(为了说明方便,以下仅列出 aspx 文件中 body 里的内容。)
1,
<form id="Form1" method="post" runat="server">
</form>   
<asp:TextBox ID="txtHello" Runat="server" Text="OK"></asp:TextBox>

2,
<form id="Form1" method="post" runat="server">
</form>   
<asp:Label ID="lblHello" Runat="server" Text="Hello"></asp:Label>

3,
<form id="Form1" method="post" runat="server">
</form>   
<asp:Button ID="btnHello" Runat="server" Text="Hello"></asp:Button>

结果发现了什么?

Label 可以正常使用。而 TextBox 和 Button 都会出现抛出一个异常。

因为 Label, Button, TextBox 都继承自 System.Web.UI.WebControls.WebControl 类。下面我们用 Reflector 来分析一下。
(如果不了解 Reflector 的可用 google 搜索).

WebControl 类的部分代码:
// (Attributes 省略)
public class WebControl : Control, IAttributeAccessor
{
    
// 

    
protected override void Render(HtmlTextWriter writer)
    
{
          
this.RenderBeginTag(writer);  // here
          this.RenderContents(writer);
          
this.RenderEndTag(writer);
    }

     
    
public virtual void RenderBeginTag(HtmlTextWriter writer)
    
{
          
this.AddAttributesToRender(writer);  // here
          HtmlTextWriterTag tag1 = this.TagKey;
          
if (tag1 != HtmlTextWriterTag.Unknown)
          
{
                writer.RenderBeginTag(tag1);
          }

          
else
          
{
                writer.RenderBeginTag(
this.TagName);
          }

    }

}

Button 类的部分代码:
// (Attributes 省略)
public class Button : WebControl, IPostBackEventHandler
{
    
// 

    
protected override void AddAttributesToRender(HtmlTextWriter writer)
    
{
          
if (this.Page != null)
          
{
                
this.Page.VerifyRenderingInServerForm(this); // here
          }

            
// .

          
base.AddAttributesToRender(writer);
    }


    
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
    
{
          
if (this.CausesValidation)
          
{
                
this.Page.Validate();
          }

          
this.OnClick(new EventArgs());
          
this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
    }

}

TextBox 类部分代码:
// (Attributes 省略)
public class TextBox : WebControl, IPostBackDataHandler
{
    
protected override void AddAttributesToRender(HtmlTextWriter writer)
    
{
        
int num1;
        
if (this.Page != null)
        
{
            
this.Page.VerifyRenderingInServerForm(this); // here
        }

        writer.AddAttribute(HtmlTextWriterAttribute.Name, 
this.UniqueID);
        TextBoxMode mode1 
= this.TextMode;

        
// 
    }

}

Label 类部分代码:
// (Attributes 省略)
public class Label : WebControl
{
    
// 
}

注意其中 // here 标注的地方。这些就是方法调用跳转的地方。

从以上的跟踪我们可以得到一个结论:
只有需要处理回发(PostBack) 的控件才必须放在 Form 内。
这种控件通常要实现 IPostBackEventHandler 或者 IPostBackDataHandler 接口。

而上面代码里的 Page.VerifyRenderingInServerForm(this) 方法正是我们做的试验里异常的抛出者。这个方法检测当前控件是否在一个 runat="server" 的 form 内部,并且在 Render 调用中。如果不是,则抛出异常。
我们看到上面的 Label 类中就保留了基类对 AddAttributesToRender 的默认实现,而没有加入对 Page.VerifyRenderingInServerForm(this)  这个检验的调用机制。

对控件开发者而言,如果你的控件需要处理回发事件或回发数据,则必须实现 IPostBackEventHandler 或 IPostBackDataHandler 接口。并且为了保险起见,应该重写 AddAttributesToRender 虚拟方法的实现,在其中调用 Page.VerifyRenderingInServerForm(this) 这个检验。

前面试验的错误信息里有堆栈跟踪,也说明了这一点:
异常详细信息: System.Web.HttpException: 类型“TextBox”的控件“txtHello”必须放在具有 runat=server 的窗体标记内。

堆栈跟踪: 


[HttpException (
0x80004005): 类型“TextBox”的控件“txtHello”必须放在具有 runat=server 的窗体标记内。]
   System.Web.UI.Page.VerifyRenderingInServerForm(Control control) 
+152
   System.Web.UI.WebControls.TextBox.AddAttributesToRender(HtmlTextWriter writer) 
+40
   System.Web.UI.WebControls.WebControl.RenderBeginTag(HtmlTextWriter writer) 
+17
   System.Web.UI.WebControls.TextBox.Render(HtmlTextWriter writer) 
+17
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) 
+241
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) 
+72
   System.Web.UI.Control.Render(HtmlTextWriter writer) 
+7
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) 
+241
   System.Web.UI.Page.ProcessRequestMain() 
+1900

相关文章推荐

ASP.NET服务器控件与组件编程

  • 2014年10月02日 13:03
  • 3.92MB
  • 下载

asp.net服务器控件命名规范

  • 2013年11月27日 20:42
  • 9KB
  • 下载

ASP.Net WebForm学习笔记:一、aspx与服务器控件探秘

作者:周旭龙 出处:http://edisonchou.cnblogs.com 开篇:毫无疑问,ASP.Net WebForm是微软推出的一个跨时代的Web开发模式,它...

asp.net服务器控件

  • 2013年10月26日 15:45
  • 632KB
  • 下载

ASP.NET02-Web标准服务器控件

  • 2013年10月29日 22:04
  • 312KB
  • 下载

HTML标签与HTML服务器控件的区别

HTML标签和HTML服务器控件之间的区别 早期的Web开发只能够使用HTML来开发Web页面,这种HTML标签给开发过程带来了许多的不便,比如无法利用程序直接来控制这些HTML标签的属性、使用方法...

获取非服务器控件到后台的示例

  • 2014年05月23日 10:45
  • 123KB
  • 下载

ASP.NET服务器控件与组件编程

  • 2005年12月28日 12:01
  • 3.92MB
  • 下载

asp.net服务器控件button先执行js再执行后台的方法

关于button这个服务器控件,我一直想减少它向服务器提交数据。那些检测,还是在客户端实现就好了。 这就需要javascript,但是我发现仅仅有javascript还是不够的。button服务器控...
  • sz1103
  • sz1103
  • 2016年05月05日 17:26
  • 252

asp.net服务器控件高程源代码

  • 2007年04月24日 10:46
  • 648KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:服务器控件
举报原因:
原因补充:

(最多只允许输入30个字)