学习笔记 --- ASP.NET状态管理

这篇是以前写的, 觉得配置文件(个性化数据那块) 和 缓存那里不够详细, 一直没发. 既然决定要专门整理一篇缓存笔记. 现在, 就直接发布下吧

##############################################

先别管ASP.NET的状态管理是什么? 首先回想一下浏览器和服务器的请求通信过程: 浏览器和服务器之间采用了HTTP协议作为共有约定来进行通信. 当在浏览器的地址栏中输入一个网址(IP地址)并按回车时(不考虑网络设备向DNS请求IP地址的过程), 浏览器首先发送一个GET请求到服务器, 服务器接收请求后根据模板页(default.aspx)和后台CS文件(default.aspx.cs)生成页面并回送给浏览器, 于是浏览器接收回送的消息并经浏览器编译解释后呈现给用户, 这时用户就可以看到页面上的各种元素了. 当用户希望执行某项操作时, 如: 点击button按钮, 这时浏览器将再次向服务器发送请求(Post请求)并附加上请求参数, 其中请求参数包含各种页面元数据的信息及状态参数; 当服务器接收到请求后, 将再次根据模板页和后台cs文件生成页面, 随后将请求参数中状态参数赋给相应的控件, 在页面事件的Load事件 --- LoadComplete事件之间, 执行控件事件, 即执行button的click事件的处理方法. 当页面事件处理完后, 将生成的页面再次返回到客户端浏览器. 这样, 看起来像是点击了button按钮, 执行了button的click事件绑定的方法.

而实际上, 服务器在接受到GET请求并回送给客户端浏览器后, 将直接销毁掉刚才创建的页面对象, 也就是说服务器生成页面的过程都是”一次性”服务, 再把生成好的页面发给浏览器后便销毁掉刚才创建的页面对象, 服务器无法为客户端保存任何信息. 当客户端浏览器发送POST请求时, 由客户端浏览器提供自己的参数并传到服务器端, 服务器做的工作和第一次GET请求时并没有区别, 只是客户端通过某种手段将自己的状态告诉了服务器, 而这种手段就是状态管理, 由客户端维护状态的状态管理就是客户端状态管理. 而随着技术的发展, 服务器端也可以记录客户的状态信息, 称之为服务器状态管理. 总之, 状态管理的目的是保存客户端的参数或状态, 例如: 用户的登陆状态, 由于HTTP协议时无状态的, 当我们第二次请求服务器时, 服务器已经丢掉了之前的页面对象, 服务器无法判断用户是已经登陆的用户还是为登陆的用户, 状态管理就为我们提供了这么一种手段, 用来告诉服务器用户时登陆过的, 还是未登录的.

状态管理的手段有9种: 见下图:

状态管理有基于客户端和基于服务器的两类状态管理, 其中基于客户端的状态管理是指状态管理信息存储在浏览器上, 在各次请求中不会再服务器上维护任何信息; 而基于服务器的状态管理将由服务器存储和维护客户端的状态信息.

基于客户端的状态管理(5种): 隐藏域、视图状态、控件状态、cookie、查询字符串, 其中控件状态多用于控件开发, 网站很少应用.

ViewState: 隐藏域和视图状态常用于同一页面的不同次请求之间的状态管理:

Name属性对客户端控件很重要, 添加了”name”属性后, name的值将会发送到服务器. 在Get或Post请求中, 将以"name属性的值"="value属性的值"发送, 多个名值对用&隔开.

//Calendar.aspx

View Code
<% @ Page Trace = " false " Language = " C# " AutoEventWireup = " true " CodeFile = " Calendar.aspx.cs "
Inherits
= " Calendar " %>

<! 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 runat ="server" >
< title > My Calendar </ title >
< style type ="text/css" >
.currentdate
{
border
: solid 1px Black ;
background-color
: Aqua ;
color
: Fuchsia ;
}
table
{
border-collapse
: collapse ;
border
: solid 1px Green ;
}
td
{
padding
: 15px ;
text-align
: center ;
border
: solid 1px Green ;
border-collapse
: collapse ;
}
.haveEvent
{
background-image
: url(images/tips.gif) ;
background-repeat
: no-repeat ;
background-position
: right bottom ;
}
</ style >
</ head >
< body >
< form id ="form_calendar" runat ="server" >
< div >
< div style ="float:left" >
< asp:Button ID ="btn_previous" runat ="server" Text ="上一月" OnClick ="Btn_Previous_Click" />
< asp:Label ID ="lbl_currentdate" runat ="server" Text ="当前日期" ></ asp:Label >
< asp:LinkButton ID ="lbtn_today" runat ="server" OnClick ="lbtn_today_Click" > 今天 </ asp:LinkButton >
< asp:Button ID ="btn_next" runat ="server" Text ="下一月" OnClick ="Btn_Next_Click" />
< br />
< br />
< asp:Table ID ="tb_calendar" runat ="server" >
</ asp:Table >
< br />
标题:
< asp:TextBox ID ="txt_title" Width ="280px" runat ="server" ></ asp:TextBox >< br />< br />
内容:
< asp:TextBox ID ="txt_content" Width ="280px" runat ="server" TextMode ="MultiLine"
Height
="100px" ></ asp:TextBox >
< br />< br />
< asp:LinkButton ID ="lbtn_add" runat ="server" onclick ="lbtn_add_Click" > 添加 </ asp:LinkButton >
</ div >
< div style ="float:right; width:299px;" >
事件列表:
< asp:BulletedList ID ="btl_Title" runat ="server" Height ="22px" Width ="256px" >
</ asp:BulletedList >
< asp:ListBox ID ="lst_content" runat ="server" Height ="100px" Width ="301px" ></ asp:ListBox >
</ div >
</ div >
< asp:HiddenField ID ="hid_currentdate" runat ="server" />
</ form >
</ body >
</ html >

//Calendar.aspx.cs

View Code
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class Calendar : System.Web.UI.Page
{
#region 全局变量
// private DateTime _current;
public DateTime CurrentDate
{
#region 普通属性
/*
get
{
return this._current;
}
set
{
this._current = value;
}
*
*/
#endregion
#region 属性直接存取ViewState
get
{
if ( this .IsPostBack)
{
return (DateTime) this .ViewState[ " currentdate " ];
}
else
{
return DateTime.Now;
}
}
set
{
this .ViewState[ " currentdate " ] = value;
}
#endregion
}
#endregion

#region 页面事件
protected void Page_PreInit( object sender, EventArgs e)
{
#region 隐藏域
/*
string currentdate = this.Request[this.hid_currentdate.ClientID]; //直接用隐藏域的ID值("hid_currentdate")做索引也可
//隐藏域最早可以在PreInit事件中处理(从Request中取), 但如果通过隐藏域的.Value属性取值必须在InitComplete之后
if (!string.IsNullOrEmpty(currentdate))
{
this.CurrentDate = DateTime.Parse(currentdate);
}
else
{
this.CurrentDate = DateTime.Now;
}
*/
#endregion
}

protected void Page_PreLoad( object sender, EventArgs e)
{
/*
#region ViewSate
if (this.IsPostBack)
{
this.CurrentDate = (DateTime)this.ViewState["currentdate"];
}
else
{
this.CurrentDate = DateTime.Now;
}
#endregion
*/
}

protected void Page_Load( object sender, EventArgs e)
{
if ( ! this .IsPostBack)
{
// 画表格
// this._current = DateTime.Now;
this .CurrentDate = DateTime.Now;
// ShowCalendar();
// this.lbl_test.Text = Day1ofMonth.ToString();
}
ShowCalendar();
}



#endregion

#region 通过属性存取视图状态, 不再需要PreRenderComplete事件
/*
//保存数据岛隐藏域
protected void Page_PreRenderComplete(object sender, EventArgs e)
{
//this.hid_currentdate.Value = this.CurrentDate.ToShortDateString();
this.ViewState["currentdate"] = this.CurrentDate;
}
#endregion
*
*/
#endregion

private void ShowCalendar()
{
// 清楚数据
this .tb_calendar.Rows.Clear();
this .lbl_currentdate.Text = this .CurrentDate.ToShortDateString(); // lbl始终显示当前日期
// this.txt_title.Text = "";
// this.txt_content.Text = "";
this .btl_Title.Items.Clear();
this .lst_content.Items.Clear();

// 日历数据
int day1ofMonth = ( int ) new DateTime( this .CurrentDate.Year, this .CurrentDate.Month, 1 ).DayOfWeek; // 每月1号星期几, 返回值为枚举需强转
int dayofMonth = DateTime.DaysInMonth( this .CurrentDate.Year, this .CurrentDate.Month); // 每月有多少天

// 画日历
string [] weekname = new string [ 7 ] { " " , " " , " " , " " , " " , " " , " " };
int rows = (day1ofMonth + dayofMonth + 6 ) / 7 ;
for ( int i = 0 ; i <= rows; i ++ )
{
TableRow tr
= new TableRow();
this .tb_calendar.Rows.Add(tr);

if (i == 0 ) // 第一行, 填入星期几
{
for ( int j = 0 ; j < weekname.Length; j ++ )
{
TableCell tc
= new TableCell();
tr.Cells.Add(tc);
tc.Text
= weekname[j];
if (j == 0 || j == 6 )
{
tc.ForeColor
= System.Drawing.Color.Red;
}
else
{
// nothing to do here!
}
}
}
else // 填入空白格
{
for ( int j = 0 ; j < 7 ; j ++ )
{
TableCell tc
= new TableCell();
tr.Cells.Add(tc);
// 以下三行为每次的清理操作
// tc.ForeColor = System.Drawing.Color.Black; // 每次清除前景色, 可以用样式表实现
// tc.BackColor = System.Drawing.Color.White; // 每次清楚背景色
tc.Text = " &nbsp; " ; // 每次画表格前, 清除原先的数字
}
}
}

// 填数据
string virtualPath = this .Server.MapPath( " ~/App_Data " );
int rowindex;
int colindex;
for ( int i = 1 ; i <= dayofMonth; i ++ )
{
rowindex
= (day1ofMonth + i - 1 ) / 7 + 1 ; // 取得行索引
colindex = (day1ofMonth + i - 1 ) % 7 ; // 取得列索引
TableCell tc = this .tb_calendar.Rows[rowindex].Cells[colindex];
// tc.Text = i.ToString();
LinkButton lbtn = new LinkButton();
lbtn.ID
= string .Format( " lbtn{0} " ,i);
lbtn.Text
= i.ToString();
lbtn.Click
+= new EventHandler(lbtn_Click); // 添加天按钮的事件
// 用命令参数, 可以获得选中按钮所对应的日期是什么
// lbtn.CommandArgument = new DateTime(this.CurrentDate.Year, this.CurrentDate.Month, i).ToShortDateString();
tc.Controls.Add(lbtn);
if (i == this .CurrentDate.Day)
{
// tc.ForeColor = System.Drawing.Color.Magenta;
// tc.BackColor = System.Drawing.Color.Cyan;
// lbtn.CssClass = "currentdate"; // 引用Css样式, 在aspx中添加.currentdate{}样式
lbtn.CssClass = " currentdate " ;

}
else
{
// nothing to do here!
}

// 产看文件夹中是否有记录事情的文件, 有的话则改变图标
string filedir = System.IO.Path.Combine(virtualPath, new DateTime( this .CurrentDate.Year, this .CurrentDate.Month,i).ToShortDateString()); // this.CurrentDate一定有值
System.IO.DirectoryInfo dirinfo = new System.IO.DirectoryInfo(filedir);
if (dirinfo.Exists)
{
System.IO.FileInfo[] files
= dirinfo.GetFiles();
if (files.Length > 0 )
{
tc.CssClass
= " haveEvent " ;
}
else
{
this .btl_Title.Items.Clear();
}
}
else
{
// nothing to do here!
}

}
this .lbl_currentdate.Text = this .CurrentDate.ToShortDateString(); // 填充当前日期
// 产看当日的文件夹中是否有记录事情的文件, 有的话则显示
string filedir2 = System.IO.Path.Combine(virtualPath, this .CurrentDate.ToShortDateString()); // this.CurrentDate一定有值
System.IO.DirectoryInfo dirinfo2 = new System.IO.DirectoryInfo(filedir2);
if (dirinfo2.Exists)
{
System.IO.FileInfo[] files
= dirinfo2.GetFiles();
if (files.Length > 0 )
{
string title = "" ;
string content = "" ;
System.IO.StreamReader sr
= null ;
foreach (System.IO.FileInfo fi in files)
{
sr
= new System.IO.StreamReader(fi.FullName);
title
= sr.ReadLine();
content
= sr.ReadLine();
sr.Close();
this .btl_Title.Items.Add(title);
this .lst_content.Items.Add(content + Environment.NewLine);
}
}
else
{
this .btl_Title.Items.Clear();
}
}
else
{
// nothing to do here!
}
}

#region 按钮事件
protected void Btn_Previous_Click( object sender, EventArgs e)
{
this .CurrentDate = this .CurrentDate.AddMonths( - 1 );
ShowCalendar();
}
protected void Btn_Next_Click( object sender, EventArgs e)
{
this .CurrentDate = this .CurrentDate.AddMonths( 1 );
ShowCalendar();
}
void lbtn_Click( object sender, EventArgs e)
{
LinkButton lbtn
= sender as LinkButton;
int day = Convert.ToInt32(lbtn.Text);
this .CurrentDate = new DateTime( this .CurrentDate.Year, this .CurrentDate.Month, day);
ShowCalendar();
}
protected void lbtn_today_Click( object sender, EventArgs e)
{
this .CurrentDate = DateTime.Now;
ShowCalendar();
}
protected void lbtn_add_Click( object sender, EventArgs e)
{
string virtualPath = this .Server.MapPath( " ~/App_Data " );
string filedir = System.IO.Path.Combine(virtualPath, this .CurrentDate.ToShortDateString()); // this.CurrentDate一定有值
System.IO.DirectoryInfo dirinfo = new System.IO.DirectoryInfo(filedir);
if ( ! dirinfo.Exists)
{
dirinfo.Create();
}
else
{
// nothing to do here!
}

if ( this .txt_title.Text != "" && this .txt_content.Text != "" )
{
System.IO.StreamWriter sw
= new System.IO.StreamWriter( string .Format( " {0}/{1} " , filedir,System.IO.Path.GetRandomFileName()));
sw.WriteLine(txt_title.Text);
sw.WriteLine(txt_content.Text);
sw.Close();
this .txt_title.Text = "" ;
this .txt_content.Text = "" ;
}
else
{
// nothing to do here!
}
ShowCalendar();
}
#endregion
}

Cookie:

Cookie的使用:

发送到客户端的Cookie信息需要通过键值对处理, 且键和值的类型均为string.

大多数浏览器Cookie中保存的Value长度不能超过2K.

默认情况下, 关闭浏览器后Cookie将一同消失, 如果需要长时间保存Cookie, 可以修改Cookie的过期时间(Expires), 而删除Cookie的操作为设置一个更早的已失效的过期时间.

//CookieDemo.aspx

View Code
//default.aspx

<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>

<! 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 runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:TextBox ID ="txt_input" runat ="server" ></ asp:TextBox >
< asp:LinkButton ID ="lbtn_save" runat ="server" onclick ="lbtn_save_Click" > 保存 </ asp:LinkButton >
< asp:CheckBox ID ="chk_cookie" runat ="server" Text ="长期有效" />
< asp:LinkButton ID ="lbtn_del" runat ="server" onclick ="lbtn_del_Click" > 删除 </ asp:LinkButton >
< hr />
< asp:TextBox ID ="txt_result" runat ="server" ></ asp:TextBox >
< asp:LinkButton ID ="lbtn_get" runat ="server" onclick ="lbtn_get_Click" > 获取 </ asp:LinkButton >
</ div >
</ form >
</ body >

//CookieDemo.aspx.cs

View Code
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
if ( ! this .IsPostBack)
{

}
}

protected void lbtn_save_Click( object sender, EventArgs e)
{
// 创建cookie对象
HttpCookie cookie = new HttpCookie( " CK " );
cookie.Value
= this .txt_input.Text;

if ( this .chk_cookie.Checked == true )
{
cookie.Expires
= DateTime.Now.AddDays( 7 );
}

// 创建完还要放到Response中去, 生成回应头
// this.Response.SetCookie(cookie); --更新cookie
this .Response.Cookies.Add(cookie);
}
protected void lbtn_get_Click( object sender, EventArgs e)
{
HttpCookie hc
= this .Request.Cookies[ " CK " ];
this .txt_result.Text = hc.Value.ToString();
}
protected void lbtn_del_Click( object sender, EventArgs e)
{
HttpCookie hc
= this .Request.Cookies[ " CK " ];
hc.Expires
= new DateTime( 1900 , 1 , 1 );

this .Response.Cookies.Add(hc);
}
}

查询字符串:

示例: http://www.cait.com/default..aspx?category=teacher&name=hao

大多数浏览器允许的URL长度不大于2K

若使用查询字符串, 必须使用HttpGet命令提交, 注意这种方式不适合传递重要的敏感信息

//default.aspx, 注意地址栏

View Code
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>

<! 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 runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
栏目:
< asp:TextBox ID ="txt_category" runat ="server" ></ asp:TextBox >
姓名:
< asp:TextBox ID ="txt_name" runat ="server" ></ asp:TextBox >
< hr />
< asp:LinkButton ID ="lbtn_submit" runat ="server" onclick ="lbtn_submit_Click" > 查看 </ asp:LinkButton >
</ div >
</ form >
</ body >
</ html >

//default.aspx.cs

View Code
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{

}
protected void lbtn_submit_Click( object sender, EventArgs e)
{
if ( this .txt_category.Text != null && this .txt_name.Text != null )
{
string url = string .Format( " default.aspx?category={0}&name={1} " , this .txt_category.Text, this .txt_name.Text);
this .Response.Redirect(url);
// this.Server.Transfer(url);
}
}
}

会话状态Session:

Session是一种将用户状态信息保存在服务器上的机制. 当用户第一次请求(GET)服务器时, 服务器将为客户端创建一个SessionID并发给客户端(通常存在cookie中), 同时在服务器内存上为客户端创建一个字典用来保存客户端信息. 当用户第二次请求时(POST)将自动把SessionID通过请求参数传给服务器, 从而判断用户的状态.

默认情况下, *.aspx文件支持Session, 而*.ashx不支持Session. 因此ashx要使用Session需要实现System.Web.SessionState.IRequiresSessionState

Session的实现机制较复杂, 但使用起来确很简单:

存: this.Session[“键”] = 值;   取: object obje = this.Session[“键”];

客户端: SessionID可以存在Cookie(默认)或Url中, 若客户端禁用cookie, 那么可以在配置文件中稍作修改就可以将SessionID存于Url中.

View Code
< configuration >
< system.web >
< sessionState cookieless = “true” />
</ system.web >
</ configuration >

服务器端: 存储客户端的状态信息, 可采用多种方式存储.

1.存放在服务器内存中, 也就是存放在为IIS进程所分配的内存中, 如果Web服务器进程崩溃将会丢失会话信息. 因为服务器内存资源有限, 所以服务器会给Session设置一个过期时间, 当过期时间满后如果客户仍然没有再次访问服务器, 则会删除相应的用户字典. 这个机制成为滑动过期机制, 可以再配置文件中修改该时间.

View Code
< configuration >
< system.web >
< sessionState mode =”Inproc” /> <! —mode=”off”表示禁用Session-- >
</ system.web >
</ configuration >

2.存放在StateServer中, 使用该种方式可以在网站崩溃情况下, 保持Session信息. 该种设置需要配置stateConnectionString(默认: tcpip=127.0.0.1:42424), ip地址可以不同, 但是端口号必须相同. 此外, 还需要确保”服务管理器”中的ASP.NET State Service服务必须启动.

View Code
< configuration >
< system.web >
< sessionState mode =”StateServer” stateConnectionString =”tcpip=127.0.0.1:42424”/>
</system.web >
</ configuration >

3.存放在SqlServer中, 使用该种方式, 需要使用Aspnet_regsql.exe(路径: C:\windows\Mcrosoft.NET\Framework\v2.0.50717)工具安装会话状态数据库, 命令操作: “aspnet_regsql –E –ssadd –sstype p”; 手动操作: 在Aspnet_regsql.exe工具目录下, 双击执行并选中sql脚本installsqlstate.sql(临时表)或者installpersistsqlstate(永久表).

同时还要修改配置文件: 配置连接串, 配置数据库的超时时间(默认30秒), 且需要确保Session中的对象是可序列化的.

View Code
< configuration >
< system.web >
< sessionState mode =”SQLServer” timeout =”60” sqlConnectionString =”data source =.\;integrated Security =sspi”/>
</system.web >
</ configuration >

4. 最后一种为自定义的状态管理机制, 该种机制需要创建一个集成SessionStateStoreProviderBase抽象类的类, 然后在配置文件中指定实现类的类名.

View Code
< configuration >
< system.web >
< sessionState mode =”Custom” customProvider =”namespace.classname,assembl”/>
</system.web >
</ configuration >

//default.aspx

View Code
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>

<! 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 runat ="server" >
< title ></ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >

< br />
< br />
< asp:TextBox ID ="TextBox1" runat ="server" ></ asp:TextBox >
< asp:LinkButton ID ="LinkButton1" runat ="server" onclick ="LinkButton1_Click" > 保存 </ asp:LinkButton >
< br />
< br />
< asp:Label ID ="Label1" runat ="server" Text ="Label" ></ asp:Label >
< asp:LinkButton ID ="LinkButton2" runat ="server" onclick ="LinkButton2_Click" > 获取 </ asp:LinkButton >

</ div >
</ form >
</ body >
</ html >

//default.aspx.cs

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{

}
protected void LinkButton1_Click( object sender, EventArgs e)
{
this .Session[ " Code " ] = this .TextBox1.Text;
}
protected void LinkButton2_Click( object sender, EventArgs e)
{
this .Label1.Text = this .Session[ " Code " ] as string ;
}
}

Application:

Application是全局的状态管理手段, 当服务器一启动时Application就会被创建并长期存在于服务器上, Appllication类似于服务器的ViewState, 但只有一份而且没有过期时间, Application是全局的, 而ViewState是页面级的, Application中保存的信息持久有效, 且数据保存在一个全局的字典中. Application允许多线程操作, HttpApplicationState对象提供了Lock()和UnLock()两个方法提供同步的访问. 我们可以通过Global.asax文件中的Application_Start()方法来初始化应用程序状态Application. 注意: 这里的Application不同于HttpApplication类(处理管道).

Application适合存储全局性的数据, 如: 当前在线人数, 当前系统运行时间等.

//default.aspx

View Code
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>

<! 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 runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:Label ID ="lbl_time" runat ="server" Text ="页面执行时间" ></ asp:Label >
</ div >
</ form >
</ body >
</ html >

//default.aspx.cs

View Code
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{

}
protected void Page_PreRenderComplete( object sender, EventArgs e)
{
DateTime old
= DateTime.Parse( this .Application[ " AppStartTime " ].ToString());
TimeSpan span
= DateTime.Now - old;
this .lbl_time.Text = string .Format( " 服务器累计运行时间: {0}毫秒! " , span.TotalMilliseconds);
}
}

//Global.asax

View Code
<% @ Application Language = " C# " %>

< script runat = " server " >

void Application_Start( object sender, EventArgs e)
{
// Code that runs on application startup
this .Application[ " AppStartTime " ] = DateTime.Now;
}

void Application_End( object sender, EventArgs e)
{
// Code that runs on application shutdown

}

void Application_Error( object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs

}

void Session_Start( object sender, EventArgs e)
{
// Code that runs when a new session is started

}

void Session_End( object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.

}

</ script >

配置文件属性: 配置文件中的Profile, 需要配合Sql Server及个性化数据使用(Profile Provider), 也可以自己实现SqlProfileProvider类将数据保存在XML文件或Web服务中.

ASP.NET 2.0 提供了一个称为个性化数据的功能, 可让您存储特定于用户的数据. 该功能与会话状态类似, 但不同点在: 用户会话过期后, 数据不一定丢失而由应用程序决定. 个性化数据可以让你轻松的管理用户信息, 甚至无需维护自己的数据库, 并且由于个性化数据没有存储到应用程序中, 所以当IIS崩溃、重启等情况时, 数据仍能得到保持.

请求处理的环境HttpContext: 详情可参见HttpApplication处理管道

每当一个请求到达ASP.NET网站时, HttpRuntime将会为这次请求创建一系列的对象, 为了方便使用, HttpRuntime创建一个HttpContext上下文对象(环境对象), 该对象是一个容器对象, 其中定义了用来表示处理此次请求所需要的所有数据. 在一次请求处理过程中, HttpContext对象是贯穿整个请求处理过程的, 因此可用来实现一次请求过程中的状态管理. HttpContext中常用的属性有: Request、Response、Server、Session.

HttpContent对象通过Items属性提供一个基于键值对的状态管理机制, 其中键和值均为Object类型.

Http只能处理一次请求过程, HttpContext是在HttpApplication处理管道中重要的状态管理手段.

//default.aspx

View Code
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>

<! 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 runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:Label ID ="lbl_time" runat ="server" Text ="页面事件事件" ></ asp:Label >
</ div >
</ form >
</ body >
</ html >

//default.aspx.cs

View Code
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class _Default : System.Web.UI.Page
{
protected void Page_PreInit( object sender, EventArgs e)
{
// this.Context.Items["time"] = DateTime.Now;
HttpContext.Current.Items[ " time " ] = DateTime.Now; // 使用HttpContext类的静态属性
}
protected void Page_Load( object sender, EventArgs e)
{

}
protected void Page_PreRenderComplete( object sender, EventArgs e)
{
TimeSpan span
= DateTime.Now - DateTime.Parse( this .Context.Items[ " time " ].ToString());
this .Context.Items[ " totaltime " ] = span.TotalMilliseconds;
this .lbl_time.Text = " 11个页面处理事件共耗时(毫秒): " + this .Context.Items[ " totaltime " ].ToString();
}
}

还有个Cache做状态管理, Cache仅有一份, 并且在有请求时, 我们可以通过HttpContext.Current.Cache获得Cache的引用; 无请求时通过HttpRuntime.Cache获得Cache的引用. 我个人感觉Cache主要用于缓存数据, 提供高性能、高效率的使用体验. 当然Cache也可以作为传递状态的一种方式, 因为Cache首先是一种状态管理的手段, 并且是综合Session和Application二者优点的状态管理手段. 稍后, 关于缓存会写一篇博客, 届时在谈谈个人关于Cache的理解吧.

//综合练习: 验证码

//SqlCalendar\DAL\CalendarHelper

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DAL
{
public class CalendarHelper // 为DAL层提供连接串
{
private static readonly string connectionStr = System.Configuration.ConfigurationManager.ConnectionStrings[ " MsSql " ].ConnectionString;

public static string ConnectionString // 对外提供连接串
{
get
{
return connectionStr;
}
}

}
}

//SqlCalendar\DAL\CalendarUser

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DAL
{
public class CalendarUser // DAL层通过SqlHelper访问数据库
{
// CalendarUser类提供关于日历用户的功能, 如: 创建用户
// DateTime是值类型, 而值类型没有与Sql中Null的对应, 加?表示可空类型, 即允许值类型为空
public int CreateUser( string username, string userpass, string email, DateTime ? birthday)
{
int result = - 1 ;

// 定制的参数是根据SqlHelper的方法来选的
string connectionStr = CalendarHelper.ConnectionString;
string sqlText = @" insert into T_UserInfo(username, userpass,email,birthday)
values(@username,@userpass,@email,@birthday)
" ;
System.Data.CommandType cmdType
= System.Data.CommandType.Text;

System.Data.SqlClient.SqlParameter p_username
= new System.Data.SqlClient.SqlParameter( " @username " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_userpass
= new System.Data.SqlClient.SqlParameter( " @userpass " ,System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_email
= new System.Data.SqlClient.SqlParameter( " @email " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_birthday
= new System.Data.SqlClient.SqlParameter( " @birthday " ,System.Data.SqlDbType.DateTime);

p_username.Value
= username;
p_userpass.Value
= userpass;
p_email.Value
= email;
p_birthday.Value
= birthday;

System.Data.SqlClient.SqlParameter[] paras
= new System.Data.SqlClient.SqlParameter[] { p_username, p_userpass, p_email, p_birthday };

result
= Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteNonQuery(connectionStr, cmdType,sqlText, paras);

return result;
}

public int CreateUserByProc( string username, string userpass, string email, DateTime ? birthday)
{
// 定制的参数是根据SqlHelper的方法来选的
string connectionStr = CalendarHelper.ConnectionString;
string sqlText = " SP_CreateUserProc " ;

System.Data.CommandType cmdType
= System.Data.CommandType.StoredProcedure;

System.Data.SqlClient.SqlParameter p_username
= new System.Data.SqlClient.SqlParameter( " @username " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_userpass
= new System.Data.SqlClient.SqlParameter( " @userpass " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_email
= new System.Data.SqlClient.SqlParameter( " @email " , System.Data.SqlDbType.NVarChar);
System.Data.SqlClient.SqlParameter p_birthday
= new System.Data.SqlClient.SqlParameter( " @birthday " , System.Data.SqlDbType.DateTime);
System.Data.SqlClient.SqlParameter p_return
= new System.Data.SqlClient.SqlParameter( " @returnValue " ,System.Data.SqlDbType.Int);

p_username.Value
= username;
p_userpass.Value
= userpass;
p_email.Value
= email;
p_birthday.Value
= birthday;

p_return.Direction
= System.Data.ParameterDirection.ReturnValue;

System.Data.SqlClient.SqlParameter[] paras
= new System.Data.SqlClient.SqlParameter[] { p_username, p_userpass, p_email, p_birthday,p_return};

Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteNonQuery(connectionStr, cmdType, sqlText, paras);

// 执行完存储过程后, 获取返回值
return ( int )p_return.Value;
}
}
}

//SqlCalendar\SqlHelper    --- 网上可以下载到

//SqlCalendar\Validator\Default.aspx

View Code
<% @ Page Language = " C# " AutoEventWireup = " true " CodeFile = " Default.aspx.cs " Inherits = " _Default " %>

<! 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 runat ="server" >
< title > Untitled Page </ title >
< style type ="text/css" >
.style1
{
width
: 95% ;
height
: 216px ;
}
.style5
{
}
.style6
{
width
: 57px ;
}
</ style >
</ head >
< body >
< form id ="form1" runat ="server" >
< div style ="text-align:center;" >
< div style =" width: 500px; height:500px; background-color:Silver; text-align:left; margin-top: 20; padding: 10px 0px 0px 30px; margin-top:4%" >

< table class ="style1" >
< tr >
< td class ="style6" >
< label for ="txt_username" > 用户名: </ label >
</ td >
< td class ="style5" >
< asp:TextBox ID ="txt_username" runat ="server" Width ="209px" ></ asp:TextBox >
</ td >
< td >
< asp:RequiredFieldValidator ID ="validator_rqeField_username" runat ="server"
ControlToValidate
="txt_username" Display ="Dynamic" ErrorMessage ="用户名不能为空" ></ asp:RequiredFieldValidator >
< asp:CustomValidator ID ="validator_custom_username" runat ="server"
ErrorMessage
="用户名已存在" ControlToValidate ="txt_username" ></ asp:CustomValidator >
</ td >
</ tr >
< tr >
< td class ="style6" >
< label for ="txt_password" > 密 码: </ label >
</ td >
< td class ="style5" >
< asp:TextBox ID ="txt_password" runat ="server" Width ="209px" TextMode ="Password" ></ asp:TextBox >
</ td >
< td >
< asp:RequiredFieldValidator ID ="validator_rqeField_password" runat ="server"
ControlToValidate
="txt_password" ErrorMessage ="密码不能为空" ></ asp:RequiredFieldValidator >
</ td >
</ tr >
< tr >
< td class ="style6" >
< label for ="txt_confirm" > 确 认: </ label >
</ td >
< td class ="style5" >
< asp:TextBox ID ="txt_confirm" runat ="server" Width ="209px" TextMode ="Password" ></ asp:TextBox >
</ td >
< td >
< asp:RequiredFieldValidator ID ="validator_rqe_confirm" runat ="server"
Display
="Dynamic" ErrorMessage ="确认密码不能为空" ControlToValidate ="txt_confirm" ></ asp:RequiredFieldValidator >
< asp:CompareValidator ID ="validator_compto_conpass" runat ="server"
ControlToCompare
="txt_password" ControlToValidate ="txt_confirm"
Display
="Dynamic" ErrorMessage ="密码不一致" ></ asp:CompareValidator >
</ td >
</ tr >
< tr >
< td class ="style6" >
< label for ="txt_email" > 邮 箱: </ label >
</ td >
< td class ="style5" >
< asp:TextBox ID ="txt_email" runat ="server" Width ="209px" ></ asp:TextBox >
</ td >
< td >
< asp:RequiredFieldValidator ID ="validator_rqeField_email" runat ="server"
ControlToValidate
="txt_email" Display ="Dynamic" ErrorMessage ="邮箱不能为空" ></ asp:RequiredFieldValidator >
< asp:RegularExpressionValidator ID ="validator_regx_email" runat ="server"
ControlToValidate
="txt_email" Display ="Dynamic" ErrorMessage ="邮件格式错误"
ValidationExpression
="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" ></ asp:RegularExpressionValidator >
</ td >
</ tr >
< tr >
< td class ="style6" >
< label for ="txt_birth" > 生 日: </ label >
</ td >
< td class ="style5" >
< asp:TextBox ID ="txt_birth" runat ="server" Width ="209px" ></ asp:TextBox >
</ td >
< td >
< asp:RangeValidator ID ="validator_range_birth" runat ="server"
ControlToValidate
="txt_birth" ErrorMessage ="日期格式错误" Type ="Date" ></ asp:RangeValidator >
</ td >
</ tr >
< tr >
< td class ="style6" >
验证码:
</ td >
< td class ="style5" colspan ="2" >
< asp:Image ID ="Image1" runat ="server" ImageUrl ="~/DynamicCode.ashx" />
</ td >
</ tr >
< tr >
< td class ="style6" >
输入验证码:
</ td >
< td class ="style5" colspan ="2" >
< asp:TextBox ID ="txt_dcode" runat ="server" Width ="210px" ></ asp:TextBox >
< asp:RequiredFieldValidator ID ="RequiredFieldValidator1" runat ="server"
ErrorMessage
="验证码不能为空" Display ="Dynamic" ControlToValidate ="txt_dcode" ></ asp:RequiredFieldValidator >
< asp:CustomValidator ID ="Validator_Dcode" runat ="server"
ErrorMessage
="验证码错误" ControlToValidate ="txt_dcode" Display ="Dynamic"
onservervalidate
="Validator_Dcode_ServerValidate" ></ asp:CustomValidator >
</ td >
</ tr >
< tr >
< td colspan ="3" >
< asp:LinkButton ID ="lbtn_reguser" runat ="server" onclick ="lbtn_reguser_Click" > 注 册 </ asp:LinkButton >
< asp:LinkButton ID ="ltbn_forgetpass" runat ="server" > 忘记密码? </ asp:LinkButton >
</ td >
</ tr >
</ table >

</ div >
</ div >
</ form >
</ body >
</ html >

//SqlCalendar\Validator\Default.aspx.cs

View Code
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Init( object sender, EventArgs e)
{
this .validator_range_birth.MaximumValue = DateTime.Now.ToShortDateString();
this .validator_range_birth.MinimumValue = DateTime.Now.AddYears( - 150 ).ToShortDateString();
}

protected void Page_Load( object sender, EventArgs e)
{
if ( this .IsPostBack)
{
// this.Validate(); // 手动调用验证方法
}

}
protected void lbtn_reguser_Click( object sender, EventArgs e)
{
if ( this .IsValid) // 当所有页面对象验证通过后, 将设置Page的IsValid属性, 支出验证通过
{
DAL.CalendarUser calendaruser
= new DAL.CalendarUser();

// 初始birthday为空, 当串不为空时转换
DateTime ? birthday = null ;
if ( ! string .IsNullOrEmpty( this .txt_birth.Text))
{
birthday
= DateTime.Parse( this .txt_birth.Text);
}

// int a = calendaruser.CreateUser(this.txt_username.Text, this.txt_password.Text, this.txt_email.Text, birthday);
int exist = calendaruser.CreateUserByProc( this .txt_username.Text, this .txt_password.Text, this .txt_email.Text, birthday);

if (exist != 0 )
{
this .validator_custom_username.IsValid = false ;
}
}
}
protected void Validator_Dcode_ServerValidate( object source, ServerValidateEventArgs args)
{
// 每次复位Validator状态
args.IsValid = false ;
// this.Validator_Dcode.IsValid = false;

#region Cookie
// HttpCookie hc = this.Request.Cookies["Dcode"];
// if (hc != null)
// {
// string rqtcode = hc.Value.ToString();
// // if(rqtcode == args.Value)
// if (rqtcode == this.txt_dcode.Text)
// {
// // this.Validator_Dcode.IsValid = true; // this.Validator_Dcode.IsValid是Valid控件上的IsValid
// args.IsValid = true; // 这里必须用args.IsValid, 因为args.IsValid是事件参数(临时的), 最终他会根据事件参数的结果修改控件上的IsValid属性, 进而显示错误信息
// }
// }
// else
// {
// this.validator_dcode.isvalid = false;
// }
#endregion

#region Session
if ( this .Session[ " Dycode " ] != null )
{
string num = this .Session[ " Dycode " ] as string ;
if (num == this .txt_dcode.Text)
{
args.IsValid
= true ;
// this.Validator_Dcode.IsValid = true;
}
else
{
args.IsValid
= false ;
// this.Validator_Dcode.IsValid = false;
}
}

#endregion
}
}

//SqlCalendar\Validator\DynamicCode.ashx

View Code
<% @ WebHandler Language = " C# " Class = " DynamicCode " %>

using System;
using System.Web;

// 使用Session记得在ashx中, 添加IRequiresSessionState的接口, 而aspx文件默认就是支持的
public class DynamicCode : IHttpHandler,System.Web.SessionState.IRequiresSessionState {

public void ProcessRequest (HttpContext context) {
// context.Response.ContentType = "text/plain";
// context.Response.Write("Hello World");
context.Response.ContentType = " image/jpeg " ;

context.Response.Cache.SetCacheability(HttpCacheability.NoCache);

// 随机数生成器
Random ran = new Random();
int rannum = ran.Next( 10000 , 100000 );

// 创建位图文件
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap( 300 , 80 );

// 在位图文件上画画, 需要创建与图片画板相关的画图器
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap))
{
// 用Graphic对象清空背景
g.Clear(System.Drawing.Color.DarkGreen);

// 花矩形框
g.DrawRectangle( new System.Drawing.Pen(System.Drawing.Brushes.Blue, 3 ), 0 , 0 ,bitmap.Width - 1 ,bitmap.Height - 1 );

// StringFormat对象, 用来保存数字位置, 在数字矩形的绘图区域中
System.Drawing.StringFormat sf = new System.Drawing.StringFormat();
sf.Alignment
= System.Drawing.StringAlignment.Center;
sf.LineAlignment
= System.Drawing.StringAlignment.Center;

// 画数字, RectangleF用来确定显示数字的矩形区域
g.DrawString(rannum.ToString(),
new System.Drawing.Font( " 黑体 " , 50 ),
System.Drawing.Brushes.Black,
new System.Drawing.RectangleF( 0 , 0 , bitmap.Width, bitmap.Height),
sf);

// 画横线
for ( int i = 0 ; i < 80 ; i ++ )
{
g.DrawLine(
new System.Drawing.Pen(System.Drawing.Brushes.Black),
ran.Next(
0 , bitmap.Width),
ran.Next(
0 , bitmap.Height),
ran.Next(
0 , bitmap.Width),
ran.Next(
0 , bitmap.Height));
}

// 将数字保存到Cookie中
// HttpCookie hc = new HttpCookie("Dcode");
// hc.Value = rannum.ToString();
// context.Response.Cookies.Add(hc); // 保存到cookie中去, 但是没有页面对象, 所以需要通过context

// 将数字保存到Session中
context.Session[ " DyCode " ] = rannum.ToString();
}

// 保存图片到response, 注意: 这里是一般处理程序, 没有页面对象, 所以只能用context
bitmap.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}

public bool IsReusable {
get {
return false ;
}
}

}

 

 

 

 

/// 补充内容 

一:页面间通过JS传值的形式大概有三种

 

1 window.opener传值,子页面能获取父页面的窗口对象。当然就能获取到对象的值了,这种方式不存在传值  的长度限制,不能跨域。

2 cookies传值,传值长度有限制。

3 URL传值,值也是有限制,但是能跨域。

 

二:ASP.NET页面传值

 

1.  使用QueryString变量(或者称URL)地址后加“?”

2.  Session传值。 (服务端)

3.  Applica传值。  (全局的,最好的例子是在线访问量)

4.  Cookies传值。(客户端保存)

5    HttpContext  也即是server.transfer()  注意它与redirect的区别

 

 

三:jS访问后台变量(1、2使用较多)

 

    1、通过页面上隐藏控件访问 <input id="hidencontrol" type="hidden" runat="server"> (注意要runat=“server”)

      2、<%=对象名%>  对象要是pubulic的

      3  后台注册函数"<script language='javascript'> value=" + 变量名+ "</script>"   访问value即可

 

四 :后台访问JS变量

     1  同样是hidden

     2  cookie或session

 

五 JS调用后台函数

 

1   document.getElementById("btn1").click();

2 var f = "<%=function()%>";  alert(f); 

 

 

六 后台调用JS

   1 注册JS函数

   2 使用Literal

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值