参考
MSDN HttpApplication class, AcquireRequestState Event 的时机
Interface IHttpModule
{
void Init( HttpApplication context );
void Dispose();
}
使用
<system.web>
…
<httpModules>
<add name=”RefreshModule” type=”RivenWeb.RefreshModule” />
</httpModules>
</system.web>
要解决的问题:
当你refresh一个页面时,browser会将上次的提交再重复一遍,如果上次的操作是删除一条
记录,refresh会导致再删除一次,如果上次的操作是添加一条记录,则refresh会插入冗余
的记录.
写一个自己的HttpModule,在Init中注册HttpApplication的AcquireRequestState,
在时间处理函数中根据HttpApplication.Context拿到HttpContext并处理之.
public class RefreshModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.AcquireRequestState += new EventHandler(this.OnAcquireRequestState);
}
public void Dispose()
{
}
private void OnAcquireRequestState(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context;
RefreshAction.Check(ctx);
}
}
RefreshAction是一个工具类,用与Check HttpContext中的refresh信息,判断本次页面请求
的性质,并记录.
public static void Check(HttpContext ctx)
查看ctx.Session[”__LASTREFRESHTICKET”]是否为null,如果为null,
ctx.Session[”__LASTREFRESHTICKET”] = 0;
从Session读取Last refresh ticket
ctx.Session[”__LASTREFRESHTICKET”]
从hidden field读取Current refresh ticket
ctx.Request[”__CURRENTREFRESHTICKET”]
注意Last refresh ticket 位于Session中,而 Current refresh ticket位于Resuest中.
整个程序的关键就在于ctx.Request[”__CURRENTREFRESHTICKET”],如果是F5, ctx.Request[”__CURRENTREFRESHTICKET”]
和上一次请求一样,如果是正常的request,ctx.Request[”__CURRENTREFRESHTICKET”]为Page的隐藏字段”__CURRENTREFRESHTICKET”的值
而Page的隐藏字段”__CURRENTREFRESHTICKET”的值会在每次request中被TrackRefreshState()函数加1.
并在Pag_PreRender中被记录到hidden field中.
“When the user submits a new request (causes the displayed page to post back), the
hidden field (if any) is automatically attached to the request for the server. “
比较Last refresh ticket和Current refresh ticket,
如果current > last ()或
current = last 并且 current = last = 0(说明是第一次请求)
说明是正常的请求,set ctx.Items[PageRefreshEntry] = false;
并同步Last refresh ticket和Current refresh ticket,
ctx.Session[”__LASTREFRESHTICKET”] = current ticket;
否则在context的itemt记录此次refresh的类型
set ctx.Items[PageRefreshEntry] = true;
写一个Page类,为所有的request生成一个递增的ticket号,
1.提供Propery:IsPageRefresh,读取HttpContext.Current.Items[PageRefreshEntry],
从而得知但前page是refresh还是正常的请求.在进行正常的处理前,判断是否需要进行
数据操作.
protected void Button_Add_Click(object sender, EventArgs e)
{
if (!IsPageRefresh)
AddRecord(this.TextBox_FirstName.Text, this.TextBox_LastName.Text);
else
this.Message.InnerText = “Page refreshed”;
TrackRefreshState();
}
2.提供一个方法TrackRefreshState来修改Page.Session[RefreshTicketCounter],
如果是通过button click等错作引起的refresh, 就调用这个函数,使Page.Session[RefreshTicketCounter]+1
,以便新的页面请求中可以包含RefreshTicketCounter信息.
3.在Page.PreRender事件中将Page.Session[RefreshTicketCounter]记录到Page的隐藏字段中.
注意,这个隐藏字段中字段的名字为”__CURRENTREFRESHTICKET”,从而HttpModule可以从
ctx.Request[CurrentRefreshTicketEntry]读到这个值.
问题:
HttpContext.Session与Page.Session的辨析
隐藏字段和HttpContext.Request的关系.