本文是《ASP.NET 2.0應用程序開(kāi)發(fā)》一書(shū)內容的延伸,講述ASP.NET 2.0服務(wù)器控件與標記之間的關(guān)系。
《ASP.NET 2.0應用程序開(kāi)發(fā)》一書(shū)中,第19頁(yè)、第1.5.6小節的內容是關(guān)于A(yíng)SP.NET 2.0服務(wù)器控件語(yǔ)法的描述,由于書(shū)中只是簡(jiǎn)單地進(jìn)行了介紹,現將更多的內容補充說(shuō)明如下:
1,ASP.NET 2.0服務(wù)器控件與<form runat=server></form>的關(guān)系
ASP.NET 2.0服務(wù)器控件(HTML服務(wù)器控件和Web服務(wù)器控件)是否必須需要放在<form runat=server></form>的標記之中,可以根據需要進(jìn)行設置,大多數情況下,對于只用來(lái)進(jìn)行界面顯示的控件、并且不需要處理事件的控件,可以不放在<form runat=server></form>之間,對于大多數控件來(lái)說(shuō),是要在服務(wù)器端進(jìn)行事件處理和獲得某些返回值的,因此需要放在<form runat=server></form>之間。
2,如何進(jìn)行控制
服務(wù)器控件在進(jìn)行Render、AddAttributesToRender等的時(shí)候,會(huì )執行下面這句:
Page page1 = this.Page;
if (page1 != null)
{
page1.VerifyRenderingInServerForm(this);
}
Page.VerifyRenderingInServerForm 方法 就是驗證服務(wù)器控件是否需要在<form runat=server></form>的標記之中,如果不在這個(gè)標記之中,將會(huì )引發(fā)下面的異常。例如下面的代碼:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>VerifyRenderingInServerForm</title>
</head>
<body>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<form id="form1" runat="server">
</form>
</body>
</html>
在瀏覽這樣的頁(yè)面時(shí),將會(huì )引發(fā)異常:
類(lèi)型“TextBox”的控件“TextBox1”必須放在具有 runat=server 的窗體標記內。
說(shuō)明: 執行當前 Web 請求期間,出現未處理的異常。請檢查堆棧跟蹤信息,以了解有關(guān)該錯誤以及代碼中導致錯誤的出處的詳細信息。
異常詳細信息: System.Web.HttpException: 類(lèi)型“TextBox”的控件“TextBox1”必須放在具有 runat=server 的窗體標記內。
這是因為,TextBox控件在進(jìn)行Render的時(shí)候調用了page1.VerifyRenderingInServerForm(this);,因此,如果不放在<form runat=server></form>的標記之間,這個(gè)驗證過(guò)程是通不過(guò)的。
但是,我們可以在代碼中重載這個(gè)方法,以便是TextBox控件可以放在<form runat=server></form>的標記之外,例如下面的代碼:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
public override void VerifyRenderingInServerForm(Control control)
{
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>VerifyRenderingInServerForm</title>
</head>
<body>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<form id="form1" runat="server">
</form>
</body>
</html>
瀏覽這樣的頁(yè)面就不會(huì )產(chǎn)生異常。
3,調整展現方式后,頁(yè)面能否正常工作
MSDN上解釋Page.VerifyRenderingInServerForm 方法時(shí)說(shuō):
如果回發(fā)或使用客戶(hù)端腳本的服務(wù)器控件沒(méi)有包含在 HtmlForm 服務(wù)器控件 (<form runat="server">) 標記中,它們將無(wú)法正常工作。這些控件可以在呈現時(shí)調用該方法,以在它們沒(méi)有包含在 HtmlForm 控件中時(shí)提供明確的錯誤信息。
是的,雖然下面的代碼可以正常顯示,但一旦單擊“提交”按鈕,服務(wù)器端將得不到輸入的值,頁(yè)不能保存狀態(tài)了。
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
public override void VerifyRenderingInServerForm(Control control)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("<li>TextBox1.Text = " + TextBox1.Text);
Response.Write("<li>Request.Params = " + Request.Params[TextBox1.UniqueID]);
}
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("<li>TextBox1.Text = " + TextBox1.Text);
Response.Write("<li>Request.Params = " + Request.Params[TextBox1.UniqueID]);
if (!IsPostBack)
{
TextBox1.Text = "《ASP.NET2.0應用開(kāi)發(fā)技術(shù)》";
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>VerifyRenderingInServerForm</title>
</head>
<body>
<asp:TextBox ID="TextBox1" runat="server" Width="600px"></asp:TextBox>
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click"
Text="提交" />
</form>
</body>
</html>
因此,在一般情況下,不要將服務(wù)器控件移到<form runat=server></form>的標記之外
4,如何強制將服務(wù)器控件放入<form runat=server></form>的標記之間
有些服務(wù)器控件可以不放在<form runat=server></form>的標記之間,如Label控件,但如果需要強制將它放<form runat=server></form>的標記之間,可以使用下面的方法:
protected void Label1_PreRender(object sender, EventArgs e)
{
this.VerifyRenderingInServerForm(Label1);
}
5,百害而無(wú)一益?
有時(shí)候,頁(yè)面上需要放置多個(gè)form表單(雖然只放置一個(gè)<form runat=server></form>的表單也能實(shí)現),將表單控件放在<form runat=server></form>標記之外,將非常方便使用,這在以前的asp頁(yè)面中很常見(jiàn),現在在aspx中也可義實(shí)現。下面的頁(yè)面,既利用了服務(wù)器控件的方便性,也逃脫出了類(lèi)型“TextBox”的控件“TextBox1”必須放在具有 runat=server 的窗體標記內的限制。例如:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("<li>TextBox1.Text = " + TextBox1.Text);
Response.Write("<li>Request.Params = " + Request.Params[TextBox1.UniqueID]);
}
protected void Page_Load(object sender, EventArgs e)
{
KeyWords.Text = "《ASP.NET2.0應用開(kāi)發(fā)技術(shù)》";
Response.Write("<li>TextBox1.Text = " + TextBox1.Text);
Response.Write("<li>Request.Params = " + Request.Params[TextBox1.UniqueID]);
if (!IsPostBack)
{
TextBox1.Text = "《ASP.NET2.0應用開(kāi)發(fā)技術(shù)》";
}
}
public override void VerifyRenderingInServerForm(Control control)
{
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>VerifyRenderingInServerForm</title>
</head>
<body>
<form method="post" action="SearchDoc.aspx">
關(guān)鍵字:<asp:TextBox ID="KeyWords" runat="server"></asp:TextBox>
<asp:Button ID="Button2" runat="server" Text="搜索" />
</form>
<form id="form1" runat="server">
<asp:TextBox ID="TextBox1" runat="server" Width="600px"></asp:TextBox>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click"
Text="提交" />
</form>
</body>
</html>
在SearchDoc.aspx頁(yè)面,使用Request.Form即可獲得輸入的關(guān)鍵字。
聯(lián)系客服