如何解决浏览器刷新问题.doc

上网导航 2023-10-10 357 0条评论
摘要: 相信大家也遇到一个问题(这个问题我经常遇到)那就是用户刷新当前显示页面,则服务器上采取的最后一个动作将盲目的重复。例如,如果前一次发送的结果是增加一条数据,则.....

相信大家也遇到一个问题(这个问题我经常遇到)那就是用户刷新当前显示页面,则服务器上采取的最后一个动作将盲目的重复。例如,如果前一次发送的结果是增加一条数据,则应用程序会在另一次回发时试图插入一个完全相同的数据。如图:这时我先在数据库添加一条记录(xiaofeng,11),然后刷新两遍浏览器得到的结果。页面刷新的基本原理页面刷新是一种内部浏览器操作,对此浏览器不会根据任何事件或回调提供任何外部通知。浏览器会缓存它所有服务请求,并在用户按下页面刷新键或按钮时重新显示。浏览器也不会为刷新事件提供任何类型通知。那么由此可以知道服务器端代码无法将刷新请求与一般的提交或回发请求相区分。那么此时我们需要创建外围机制,使两个在其他方面相同的请求看起来相同。所有浏览器都是通过重新发送最后发送的HTTP请求来实现刷新。为了使该副本不同于原始请求,一个额外的服务必须添加到其他参数,而ASP.NET页面必须能捕获他们。这里解决方案设计到HttpModule这块知识,所以先简单介绍下Asp.net为每一个正在运行的应用程序管理一个HttpApplication对象池,并从池中选出一个实例来服务特定的请求。这些对象基于global.asax文件中定义的类或者基于HttpApplication基类。

对请求负责的HttpApplication对象的最终目标是获得一个HTTP处理程序。在最终的HTTP处理程序的过程中,HttpApplication对象使请求通过一个由HTTP模块组成的通道。HTTP模块是一个实现了IHttpModule接口的.NETFramework类。那些筛选请求中的原始数据的HTTP模块,在web.config文件中配置的多个系统HTTP模块。HTTP模块可以对一个请求进行预处理和后处理,它截取处理系统事件以及其他模块产生的事件。IHttpModule接口它包含了两个方法:Init和Dispose。Inti方法初始化一个模块,并为它做好处理请求的准备。可以这里我们同意接受感兴趣的事件通知,它接受一个服务请求的HttpApplication对象的引用。使用该引用可以连接到系统事件。Application对象也有一个成为context的对象,该对象对ASP.NET应用程序内在属性的引用,这样就可以访问response,request,session等。Dispose方法处置该模块使用资源(除内存外的一切)。它典型的用法是关闭数据库连接或文件句柄。我们编写自定义Http模块,就是实现IHttpModule接口,并在web.config配置文件中httpModule节添加一个配置项,来注册我们编写的Http模块下面接着上面谈谈解决方案每个请求被分配一个标签号,而HTTP模块将跟踪它处理的每个不同页面里最后服务的标签。

如果该页面特有的标签号小于该页面的最后服务的标签号,则只能表明服务了相同的请求即页面刷新。那么我们可以用一个HTTP模块对标签号作初步检查,一个自定义页面类自动地将一个渐进的标签号码添加到每个服务过的页面。HTTP模块位于HTTP运行库环境的中间,登记应用程序中的一个资源的每个请求。页面第一次被请求时(不是回发),不分配任何标签。HTTP模块将生成一个新的标签号,并把它存储在HttpContext对象的Item集合中。此外,该模块将最后服务的标签的内部技术器初始化为0.随后该页面每次被请求时,该模块都将最后服务的标签与页面标签进行比较。如果页面标签大一些就认为使一次普通的回发;否则它将被标记为一次页面刷新。为了确保每个请求都有一个合适的标签号,需要得到页面类的帮助。该页面类从HTTP模块接收两种不同的信息。要存储在随页面一起传送的一个隐藏字段中的下一个标签,以及该请求是否为页面刷新的信息。(HttpContext类上的Items集合是一个载体集合,是为了让HTTP模块将信息向下传递给实际负责服务请求的页面和HTTP处理程序而特意建立具体实现首先我们构建一个HttpModule模块usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Web;namespaceComponentspublicclassRefreshModule:IHttpModule#regionIHttpModule成员publicvoidDispose()thrownewNotImplementedException();publicvoidInit(HttpApplicationapp)//注册事件app.BeginRequestnewEventHandler(OnAcquireRequestState);#endregionpublicvoidOnAcquireRequestState(objectsender,EventArgsHttpApplicationapp(HttpApplication)sender;HttpContextctxapp.Context;//检测请求是否是刷新RefreshAction.Check(ctx);return;检测请求是否是刷新请求,就是通过比较判断页面标签和最后一次服务标签大小,而页面标签存储在页面隐藏域中,最后一次服务标签从Hashtable中得到。

publicstaticvoidCheck(HttpContextctx)//初始化标签号EnsureRefreshTicket(ctx);浏览器缓存中得到最后一次服务标签intlastTicket从隐藏域中得到页面标签intthisTicketGetCurrentRefreshTicket(ctx,lastTicket);//更新服务标签UpdateLastRefreshTicket(ctx,thisTicket);//写入Items标记不是刷新ctx.Items[PageRefreshEntry]//判断本次回发是刷新ctx.Items[PageRefreshEntry]将判断的信息交给Page类,这个类是要被页面继承的,那么我们就可以在.cs文件里得到本次请求是否为刷新,就先像用IsPostBack属性一样。另外会自动将HttpContext.Current.Item中存储的页面标签存储到页面隐藏域中去publicclassPage#regionNewProperties//指示是否为刷新publicboolIsRefreshedHttpContext.Current.Items[RefreshAction.PageRefreshEntry];null)returnfalse;return(bool)o;#endregion#regionOverridesprotected override void OnPreRenderComplete(EventAr gs base.OnPreRenderComplete(e);SaveRefreshState(); #endregion#region Helpers /summaryprivate void SaveRefreshState() intticket (int)HttpContext.Current.Items[RefreshAction.NextPageTicketEntry]; ClientScript.RegisterHiddenField(RefreshAction. CurrentRefreshTicketEntry, ticket.ToString()); 在让页面继承该类,并在页面中判断是否刷新public partial class TestFresh protectedvoid Page_Load(object sender, EventArgs privatevoid Loaddata() SqlConnectioncon newSqlConnection("Data Source=. \\;Initial Catalog=db_HttpModule;User ID=sa;Password=asd12 DataTabledt newDataTable(); SqlDataAdapter sqldataadaper newSqlDataAdapter(" select fromdt_info", con);

文章版权及转载声明:

作者:上网导航本文地址:https://www.90xe.com/post/5615.html发布于 2023-10-10
文章转载或复制请以超链接形式并注明出处技术导航

分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏