这篇是以前写的, 觉得配置文件(个性化数据那块) 和 缓存那里不够详细, 一直没发. 既然决定要专门整理一篇缓存笔记. 现在, 就直接发布下吧
##############################################
先别管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
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
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 = " " ; // 每次画表格前, 清除原先的数字
}
}
}
// 填数据
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
<% @ 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
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, 注意地址栏
<! 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
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中.
< system.web >
< sessionState cookieless = “true” />
</ system.web >
</ configuration >
服务器端: 存储客户端的状态信息, 可采用多种方式存储.
1.存放在服务器内存中, 也就是存放在为IIS进程所分配的内存中, 如果Web服务器进程崩溃将会丢失会话信息. 因为服务器内存资源有限, 所以服务器会给Session设置一个过期时间, 当过期时间满后如果客户仍然没有再次访问服务器, 则会删除相应的用户字典. 这个机制成为滑动过期机制, 可以再配置文件中修改该时间.
< 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服务必须启动.
< 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中的对象是可序列化的.
< system.web >
< sessionState mode =”SQLServer” timeout =”60” sqlConnectionString =”data source =.\;integrated Security =sspi”/>
</system.web >
</ configuration >
4. 最后一种为自定义的状态管理机制, 该种机制需要创建一个集成SessionStateStoreProviderBase抽象类的类, 然后在配置文件中指定实现类的类名.
< system.web >
< sessionState mode =”Custom” customProvider =”namespace.classname,assembl”/>
</system.web >
</ configuration >
//default.aspx
<! 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
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
<! 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
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
< 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
<! 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
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
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
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
<! 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
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
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