3.10 HiddenField控件

HiddenField控件(习惯上称为隐藏域)与HtmlInputHidden HTML服务器控件功能一样,HiddenField控件可以用来建立一个隐含的Input隐藏域(即它在页面上呈现为<input type="hidden"/>元素),ASP.NET允许你将信息存储在Input隐藏域中。隐藏域在浏览器中不以可见的形式呈现,但可以像对待其他标准服务器控件一样设置其属性。当向服务器提交页面时,隐藏域的内容将在HTTP窗体集合中随同其他控件的值一起发送。因此,可以将隐藏域作为一个信息储存库,将希望直接存储在页面中的任何特定于页面的信息放置到其中,它提供了一种在页面中存储信息但不显示信息的方法。例如,可以在隐藏域中存储用户首选项设置,以便可以在客户端脚本中读取此设置。若要将信息放入隐藏域中,请在两次回发之间将其Value属性设置为要存储的值。

如下面的代码所示,可以在隐藏域中存储一些数据信息。


<asp:HiddenField ID="HiddenField1"

runat="server"Value="隐藏域的初始值"/>


上面的代码虽然不会在页面运行的时候显示文本“隐藏域的初始值”,但查看页面代码的时候会发现页面中会生成如下HTML代码:


<input type="hidden"name="HiddenField1"

id="HiddenField1"value="隐藏域的初始值"/>


同样,也可以通过它的Value属性来通过代码为它赋值。如:


HiddenField1.Value="我爱ASP.NET";


由于隐藏域在服务器代码和客户端脚本之间共享信息,因此在将页面回发到服务器之前,客户端脚本可以更改隐藏域的值。这时候可以利用隐藏域的OnValueChanged事件来进行处理。为了帮助检测控件中的数据更改,隐藏域会触发它的OnValueChanged事件,即使隐藏域的值在回发之间发生了更改,也可以通过处理此事件来确定值是否已发生更改。示例如代码清单3-4所示。

代码清单3-4 TestHiddenField.aspx


<%@Page Language="C#"AutoEventWireup="true"

CodeBehind="TestHiddenField.aspx.cs"

Inherits="_3_3.TestHiddenField"%>

<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head id="Head1"runat="server">

<script type="text/javascript">

function PageLoad(){

//更改隐藏域的值

form1.HiddenField1.value=form1.TextBox1.value;

}

</script>

<title></title>

</head>

<body>

<form id="form1"runat="server">

<div>

<asp:Label ID="Label1"runat="server"/>

<br/>

<asp:TextBox ID="TextBox1"runat="server"/>

<br/>

<input type="submit"name="SubmitButton"

value="更改隐藏域的值"onclick="PageLoad()"/>

<br/>

<asp:HiddenField ID="HiddenField1"runat="server"

OnValueChanged="HiddenField1_ValueChanged"/>

</div>

</form>

</body>

</html>


在代码清单3-4中,当使用“更改隐藏域的值”按钮修改隐藏域HiddenField1的值的时候,将触发它的OnValueChanged事件。OnValueChanged事件定义如下所示:


using System;

using System.Collections.Generic;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace_3_3

{

public partial class TestHiddenField:System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

if(!Page.IsPostBack)

{

HiddenField1.Value="隐藏域的初始值";

Label1.Text=

"隐藏域的初始值为:"+HiddenField1.Value;

}

}

protected void HiddenField1_ValueChanged(

object sender, EventArgs e)

{

Label1.Text=

"隐藏域的值被客户端修改为:"+HiddenField1.Value;

}

}

}


运行上面的程序,出现如图3-7所示页面。

如图3-7所示,Label1控件初始显示为隐藏域HiddenField1的初始值“隐藏域的初始值为:隐藏域的初始值”。当在文本框里输入“我爱ASP.NET”,并单击“更改隐藏域的值”按钮时,将触发客户端事件PageLoad()。这时,客户端事件PageLoad()将隐藏域HiddenField1的值修改成“我爱ASP.NET”,并触发隐藏域HiddenField1的HiddenField1_ValueChanged事件(因为隐藏域的值发生改变)。最后,在HiddenField1_ValueChanged事件里将Label1控件的显示文本修改为“我爱ASP.NET”。显示结果如图3-8所示。

figure_0128_0089

图 3-7 TestHiddenField.aspx运行界面1

figure_0128_0090

图 3-8 TestHiddenField.aspx运行界面2

最后,使用隐藏域应该注意如下几点:

1)潜在的安全风险。虽然隐藏域不能够在页面上显示隐藏字段中的信息,但用户可通过查看该页面的源码来查看隐藏域的内容,并可以篡改它。因此,不要在HiddenField控件中存储一些系统的敏感信息,如用户ID、密码或信用卡信息等。当然,也可以手动加密和解密隐藏域的内容,但这需要额外的编码和开销。如果关注安全,请考虑使用基于服务器的状态机制,从而不将敏感信息发送到客户端。

2)存储结构比较简单。隐藏域不支持复杂数据类型,一般只提供一个字符串值域存放信息。若要存储多个值,必须实现分隔的字符串以及用来分析哪些字符串的代码。可以手动分别将复杂数据类型序列化为隐藏域以及将隐藏域反序列化为复杂数据类型。但是,这同样需要额外的代码来实现。如果需要将复杂数据类型存储在客户端上,请考虑使用视图状态。视图状态内置了序列化,并且将数据存储在隐藏域中。

3)性能问题。由于隐藏域存储在页本身,因此如果存储较大的值,用户显示页和发送页时的速度可能会减慢。

4)存储限制。如果隐藏域中的数据量过大,某些代理和防火墙将阻止对包含这些数据的页的访问。因为最大数量会随所采用的防火墙和代理的不同而不同,较大的隐藏域可能会出现偶发性问题。因此,如果需要存储大量的数据项,请考虑执行下列操作之一:

❑将每个项放置在单独的隐藏域中。

❑使用视图状态并打开视图状态分块,这样会自动将数据分割到多个隐藏域。

❑不将数据存储在客户端上,将数据保留在服务器上。向客户端发送的数据越多,应用程序的表面响应时间越慢,因为浏览器需要下载或发送更多的数据。