Asp.Net防止多次提交数据(转)
Asp.Net防止多次提交数据
RefreshAction类:
public static class RefreshAction
{
// 常量
//服务端票证key
public const string LastRefreshTicketEntry = "__LASTREFRESHTICKET"; //客户端票证key
public const string CurrentRefreshTicketEntry = "__CURRENTREFRESHTICKET"; //用来保存是否是重复刷新的属性的key
public const string PageRefreshEntry = "IsPageRefresh"; // 检测F5按钮是否被按下
public static void Check(HttpContext ctx)
{
//初始化服务端票证
EnsureRefreshTicket(ctx); //从Session里读取上一次提供的票证
int lastTicket = GetLastRefreshTicket(ctx); //从请求里的隐藏域里读取当前页面的票证
int thisTicket = GetCurrentRefreshTicket(ctx); // 对比两个票证
if (thisTicket != lastTicket || (thisTicket == lastTicket && thisTicket == 0))
{
//如果当前的票证值大于上一次的票证值 或者
//当前票证值等于上一次票证值,并且当前票证值为0(这是第一次刷新)
//那么更新Session里上一次的票证值为当前票证值
UpdateLastRefreshTicket(ctx, thisTicket); //设置当前页是否重复刷新属性为false
ctx.Items[PageRefreshEntry] = false;
}
else
{
//设置当前页是否重复刷新属性为true;
ctx.Items[PageRefreshEntry] = true;
}
}
//确认上一次的票证不为空值
private static void EnsureRefreshTicket(HttpContext ctx)
{
// Initialize the session slots for the page (Ticket) and the module (LastTicketServed)
//初始化Session的最后一次票证值
if (ctx.Session[LastRefreshTicketEntry] == null)
ctx.Session[LastRefreshTicketEntry] = 0;
}
//从Session里得到上一次请求的票证值
private static int GetLastRefreshTicket(HttpContext ctx)
{ //返回Session里保存的上一次票证值
return Convert.ToInt32(ctx.Session[LastRefreshTicketEntry]);
}
//从当前请求里的到隐藏域里保存的当前票证值
private static int GetCurrentRefreshTicket(HttpContext ctx)
{
return Convert.ToInt32(ctx.Request[CurrentRefreshTicketEntry]);
}
// 将当前的票证值保存到Session里的上一次刷新的票证值
private static void UpdateLastRefreshTicket(HttpContext ctx, int ticket)
{
ctx.Session[LastRefreshTicketEntry] = ticket;
}
}
// 来源:www.CSFramework.com, C/S结构框架学习网
{
// 常量
//服务端票证key
public const string LastRefreshTicketEntry = "__LASTREFRESHTICKET"; //客户端票证key
public const string CurrentRefreshTicketEntry = "__CURRENTREFRESHTICKET"; //用来保存是否是重复刷新的属性的key
public const string PageRefreshEntry = "IsPageRefresh"; // 检测F5按钮是否被按下
public static void Check(HttpContext ctx)
{
//初始化服务端票证
EnsureRefreshTicket(ctx); //从Session里读取上一次提供的票证
int lastTicket = GetLastRefreshTicket(ctx); //从请求里的隐藏域里读取当前页面的票证
int thisTicket = GetCurrentRefreshTicket(ctx); // 对比两个票证
if (thisTicket != lastTicket || (thisTicket == lastTicket && thisTicket == 0))
{
//如果当前的票证值大于上一次的票证值 或者
//当前票证值等于上一次票证值,并且当前票证值为0(这是第一次刷新)
//那么更新Session里上一次的票证值为当前票证值
UpdateLastRefreshTicket(ctx, thisTicket); //设置当前页是否重复刷新属性为false
ctx.Items[PageRefreshEntry] = false;
}
else
{
//设置当前页是否重复刷新属性为true;
ctx.Items[PageRefreshEntry] = true;
}
}
//确认上一次的票证不为空值
private static void EnsureRefreshTicket(HttpContext ctx)
{
// Initialize the session slots for the page (Ticket) and the module (LastTicketServed)
//初始化Session的最后一次票证值
if (ctx.Session[LastRefreshTicketEntry] == null)
ctx.Session[LastRefreshTicketEntry] = 0;
}
//从Session里得到上一次请求的票证值
private static int GetLastRefreshTicket(HttpContext ctx)
{ //返回Session里保存的上一次票证值
return Convert.ToInt32(ctx.Session[LastRefreshTicketEntry]);
}
//从当前请求里的到隐藏域里保存的当前票证值
private static int GetCurrentRefreshTicket(HttpContext ctx)
{
return Convert.ToInt32(ctx.Request[CurrentRefreshTicketEntry]);
}
// 将当前的票证值保存到Session里的上一次刷新的票证值
private static void UpdateLastRefreshTicket(HttpContext ctx, int ticket)
{
ctx.Session[LastRefreshTicketEntry] = ticket;
}
}
// 来源:www.CSFramework.com, C/S结构框架学习网
RefreshModule 类:
//Provides module initialization and disposal events to the implementing class
public class RefreshModule : IHttpModule
{
//初始化模块
public void Init(HttpApplication app)
{ // Register for pipeline events
//注册请求关联状态时的事件处理器,就是说当一个请求到达服务器,
//那么首先触发这个事件,由OnAcquireRqeustState事件处理
app.AcquireRequestState = new EventHandler(this.OnAcquireRequestState);
}
// IHttpModule::Dispose
public void Dispose() { }
//判断是否是F5或前进/后退操作
private void OnAcquireRequestState(object sender, EventArgs e)
{
//得到访问的HTTP上下文
HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context; //检查是否是F5操作
if (ctx != null && ctx.Session != null)
RefreshAction.Check(ctx);
return;
}
}
// 来源:www.CSFramework.com, C/S结构框架学习网
public class RefreshModule : IHttpModule
{
//初始化模块
public void Init(HttpApplication app)
{ // Register for pipeline events
//注册请求关联状态时的事件处理器,就是说当一个请求到达服务器,
//那么首先触发这个事件,由OnAcquireRqeustState事件处理
app.AcquireRequestState = new EventHandler(this.OnAcquireRequestState);
}
// IHttpModule::Dispose
public void Dispose() { }
//判断是否是F5或前进/后退操作
private void OnAcquireRequestState(object sender, EventArgs e)
{
//得到访问的HTTP上下文
HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context; //检查是否是F5操作
if (ctx != null && ctx.Session != null)
RefreshAction.Check(ctx);
return;
}
}
// 来源:www.CSFramework.com, C/S结构框架学习网
定义一个基类,所有提交数据的页面继承:SubmitOncePage
public class SubmitOncePage : PageBaseRefreshCounter
{
#region Constants
// 常量
public const string RefreshTicketCounter = "RefreshTicketCounter";
#endregion
// Ctor
public SubmitOncePage()
{
// Register a PreRender handler
//注册页面呈现前的事件处理器
this.PreRender = new EventHandler(RefreshPage_PreRender);
}
//标志页面是否按F5进行重复刷新的标志属性
public bool IsPageRefresh
{
get
{
object o = HttpContext.Current.Items[RefreshAction.PageRefreshEntry];
if (o == null)
return false;
return (bool)o;
}
set
{
object o = HttpContext.Current.Items[RefreshAction.PageRefreshEntry];
if (o != null)
HttpContext.Current.Items[RefreshAction.PageRefreshEntry] = false;
}
}
//增加刷新票证的内部计数器
public void TrackRefreshState()
{ //初始化刷新计数器
InitRefreshState();
//将刷新计数器加1,然后放进Session
int ticket = Convert.ToInt32(Session[RefreshTicketCounter]) 1;
Session[RefreshTicketCounter] = ticket;
}
#region Private Members
// Create the hidden field to store the current request ticket
//创建隐藏域来保存当前请求的票证值
private void SaveRefreshState()
{
//将票证计数器的值加1,然后将此值注册到当前票证隐藏域中
int ticket = Convert.ToInt32(Session[RefreshTicketCounter]) 1;
this.ClientScript.RegisterHiddenField(RefreshAction.CurrentRefreshTicketEntry, ticket.ToString());
}
//初始化刷新计数器
private void InitRefreshState()
{
if (Session[RefreshTicketCounter] == null)
Session[RefreshTicketCounter] = 0;
}
// PreRender事件处理器
private void RefreshPage_PreRender(object sender, EventArgs e)
{
//在页面呈现之前就保存票证值到隐藏域
SaveRefreshState();
}
#endregion
}
// 来源:www.CSFramework.com, C/S结构框架学习网
{
#region Constants
// 常量
public const string RefreshTicketCounter = "RefreshTicketCounter";
#endregion
// Ctor
public SubmitOncePage()
{
// Register a PreRender handler
//注册页面呈现前的事件处理器
this.PreRender = new EventHandler(RefreshPage_PreRender);
}
//标志页面是否按F5进行重复刷新的标志属性
public bool IsPageRefresh
{
get
{
object o = HttpContext.Current.Items[RefreshAction.PageRefreshEntry];
if (o == null)
return false;
return (bool)o;
}
set
{
object o = HttpContext.Current.Items[RefreshAction.PageRefreshEntry];
if (o != null)
HttpContext.Current.Items[RefreshAction.PageRefreshEntry] = false;
}
}
//增加刷新票证的内部计数器
public void TrackRefreshState()
{ //初始化刷新计数器
InitRefreshState();
//将刷新计数器加1,然后放进Session
int ticket = Convert.ToInt32(Session[RefreshTicketCounter]) 1;
Session[RefreshTicketCounter] = ticket;
}
#region Private Members
// Create the hidden field to store the current request ticket
//创建隐藏域来保存当前请求的票证值
private void SaveRefreshState()
{
//将票证计数器的值加1,然后将此值注册到当前票证隐藏域中
int ticket = Convert.ToInt32(Session[RefreshTicketCounter]) 1;
this.ClientScript.RegisterHiddenField(RefreshAction.CurrentRefreshTicketEntry, ticket.ToString());
}
//初始化刷新计数器
private void InitRefreshState()
{
if (Session[RefreshTicketCounter] == null)
Session[RefreshTicketCounter] = 0;
}
// PreRender事件处理器
private void RefreshPage_PreRender(object sender, EventArgs e)
{
//在页面呈现之前就保存票证值到隐藏域
SaveRefreshState();
}
#endregion
}
// 来源:www.CSFramework.com, C/S结构框架学习网
最后在Web.Config文件内定义一个<httpModules>
<system.web>
<httpModules>
<add name="CSFramework_RefreshModule" type="CSFramework.BLL.RefreshModule"/>
</httpModules>
参考文档:
1.1 什么是ASP.NET / WebAPI / MVC?|C/S开发框架
C# ASP.NET使用ashx一般处理程序实现上传文件功能-C/S开发框架
在ASP.NET Core web API中使用Swagger/OpenAPI(Swashbuckle)-C/S开发框架
ASP.NET MVC快速入门(一)-C/S开发框架
ASP.NET Web API入门介绍(一)-C/S开发框架
ASP.NET Core中使用滑动窗口限流-C/S开发框架
ASP.NET IIS程序池被回收导致网站打开慢,IIS配置启用预加载模式-C/S开发框架
ASP.NET Web开发框架, B/S架构软件快速开发平台
[论坛社区]Asp.Net Forums v2.3.2130 官方中文版-源码下载
C#源码-[论坛社区]BBSGood论坛程序 ASP.NET版-源码下载
C#源码-[博客空间]X3BLOG(ASP.NET开源多用户博客系统) 1.1.0 beta1 源代码_x3blog-源码下载
C#源码-Asp.net明日文库源码-源码下载
C#源码-ASP.NET 4.0电子商城源码-源码下载
C#源码-大型综合管理ERP源码 大型ERP源码 bs框架 asp.net源码 界面美观-源码下载
C#源码-OA网络办公自动化系统asp.NET-源码下载
C#源码-淘特旅游网站管理系统Asp.Net版 4.3-源码下载
1.1 什么是ASP.NET / WebAPI / MVC?|C/S开发框架
C# ASP.NET使用ashx一般处理程序实现上传文件功能-C/S开发框架
在ASP.NET Core web API中使用Swagger/OpenAPI(Swashbuckle)-C/S开发框架
ASP.NET MVC快速入门(一)-C/S开发框架
ASP.NET Web API入门介绍(一)-C/S开发框架
ASP.NET Core中使用滑动窗口限流-C/S开发框架
ASP.NET IIS程序池被回收导致网站打开慢,IIS配置启用预加载模式-C/S开发框架
ASP.NET Web开发框架, B/S架构软件快速开发平台
[论坛社区]Asp.Net Forums v2.3.2130 官方中文版-源码下载
C#源码-[论坛社区]BBSGood论坛程序 ASP.NET版-源码下载
C#源码-[博客空间]X3BLOG(ASP.NET开源多用户博客系统) 1.1.0 beta1 源代码_x3blog-源码下载
C#源码-Asp.net明日文库源码-源码下载
C#源码-ASP.NET 4.0电子商城源码-源码下载
C#源码-大型综合管理ERP源码 大型ERP源码 bs框架 asp.net源码 界面美观-源码下载
C#源码-OA网络办公自动化系统asp.NET-源码下载
C#源码-淘特旅游网站管理系统Asp.Net版 4.3-源码下载
其它资料:
什么是C/S结构? | C/S框架核心组成部分 | C/S框架-WebService部署图 | C/S框架-权限管理 | C/S结构系统框架 - 5.1旗舰版介绍 | C/S结构系统框架 - 功能介绍 | C/S结构系统框架 - 产品列表 | C/S结构系统框架 - 应用展示(图) | 三层体系架构详解 | C/S架构轻量级快速开发框架 | C/S框架网客户案例 | WebApi快速开发框架 | C/S框架代码生成器 | 用户授权注册软件系统 | 版本自动升级软件 | 数据库底层应用框架 | CSFramework.CMS内容管理系统 |
什么是C/S结构? | C/S框架核心组成部分 | C/S框架-WebService部署图 | C/S框架-权限管理 | C/S结构系统框架 - 5.1旗舰版介绍 | C/S结构系统框架 - 功能介绍 | C/S结构系统框架 - 产品列表 | C/S结构系统框架 - 应用展示(图) | 三层体系架构详解 | C/S架构轻量级快速开发框架 | C/S框架网客户案例 | WebApi快速开发框架 | C/S框架代码生成器 | 用户授权注册软件系统 | 版本自动升级软件 | 数据库底层应用框架 | CSFramework.CMS内容管理系统 |
在线客服
