使用HttpModule来禁用Web表单重复提交<转

简介:

在网速慢或者网站反应慢的情况下,如果提交表单需要超过5秒的时间还未提交成功,多数人会重新点击提交。这样不仅造成错误的数据,还会加剧服务器的压力。

    通过使用HttpModule,我们可以在表单处理前,检测一些标志,从而防止用户重复提交数据,再通过一些接口,让用户自己来处理重复提交时,应该如何告诉用户。

    通过使用HttpModule,我们也可以在客户端表单提交时,使用DIV覆盖住表单,从UI层防止用户再次单击提交(用户直接F5管不了)。

    这种方法使用简单,直接把脚本和图片放在指定的目录中,然后在Web.config中添加Module

 


     <httpModules>
            
<!--防止重复提交 LOG记录MODULE -->
            
<add name="NonReduplicatePostModule" type="tests.NonReduplicatePostModule,test"/>
    
</httpModules>

 

    下面是实现代码:

 

复制代码

    /// NonReduplicatePostModule 的摘要说明。
    
/// </summary>
    public class NonReduplicatePostModule : System.Web.IHttpModule
    {
        
private static ILog log  = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        
private const string hiddenFileName = "__NonReduplicatePostModule__";
        
private const string maskdivScriptRelativeUrl = "~/js/maskDiv.js";
        
private const string onformSubmit = "Evlon.MaskDiv.Instance.show();";
        
private HttpApplication context = null;

        
#region IHttpModule 成员

        
public void Init(HttpApplication context)
        {
            
this.context = context;
            
this.context.PreRequestHandlerExecute+=new EventHandler(context_PreRequestHandlerExecute);
        }

        
public void Dispose()
        {
            
this.context.PreRequestHandlerExecute-=new EventHandler(context_PreRequestHandlerExecute);
        }

        
#endregion

        
private void context_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            HttpApplication webApp 
= sender as HttpApplication;
            
if(webApp != null)
            {
                
//已经处理过,提示用户不要重复提交
                Page page = webApp.Context.Handler as Page;
                
if(page != null)
                {
                    page.PreRender
+=new EventHandler(page_PreRender);
                    
                    
//找到Page,添加时间
                    if(webApp.Request.Form[hiddenFileName] != null)
                    {
                        
string flag = webApp.Request.Form[hiddenFileName].ToString();
                        
if(webApp.Context.Cache.Get(flag) != null)
                        {
                            log.Debug(
"found  reduplicate post");
                            
if(page is IReduplicatePostHandler)
                            {
                                webApp.Context.Handler 
= new ReduplicatePostHandler((IReduplicatePostHandler)page);
                            }
                            
else
                            {
                                webApp.Context.Handler 
= new ReduplicatePostHandler();
                            }
                        }
                        
else
                        {
                            
//放进缓存中,表示已经被处理过,在一分钟后自动移聊(可再次提交)
                            webApp.Context.Cache.Add(flag,DateTime.Now,null,System.Web.Caching.Cache.NoAbsoluteExpiration,TimeSpan.FromMinutes(1),System.Web.Caching.CacheItemPriority.Normal,null);
                        }
                    }
                }
            }

        }



        
private void page_PreRender(object sender, EventArgs e)
        {
            Page page 
= sender as Page;
            
if(page != null)
            {
                
//找到Page,添加时间
                page.RegisterHiddenField(hiddenFileName,string.Format("{0}_{1}_{2}",page.Session.SessionID.GetHashCode(), page.GetType().GetHashCode(), DateTime.Now.Ticks));
                
//表单UI显示 MASKDIV
                page.RegisterClientScriptBlock("maskdiv_include","<script type='text/javascript' src='" + page.ResolveUrl(maskdivScriptRelativeUrl) + "' ></script>");
                page.RegisterOnSubmitStatement(
"maskdiv", onformSubmit);
            }

        }
    }

    
public interface IReduplicatePostHandler
    {
        
void OnReduplicatePost(HttpContext context, EventArgs e);
    }

    
internal class ReduplicatePostHandler : IHttpHandler
    {
        
private IReduplicatePostHandler handler = null;
        
internal ReduplicatePostHandler(IReduplicatePostHandler handler)
        {
            
this.handler = handler;
        }

        
internal ReduplicatePostHandler()
        {
        
        }

        
#region IHttpHandler 成员

        
public void ProcessRequest(HttpContext context)
        {
            
if(handler != null)
            {
                handler.OnReduplicatePost(context,
new EventArgs());
            }
            
else
            {
                context.Response.Write(
"不要重复提交");
            }
        }

        
public bool IsReusable
        {
            
get
            {
                
// TODO:  添加 ReduplicatePostHandler.IsReusable getter 实现
                return false;
            }
        }

        
#endregion

    }

复制代码

 

     用到的JS文件:/js/MaskDIV.js

复制代码

Evlon = {};
Evlon.MaskDiv 
= function()
{
    
var div = window.document.createElement("DIV");
    div.style.position 
= "absolute";
    div.style.top 
= "0px";
    div.style.left 
= "0px";
    div.style.width 
= '100%';//document.body.scrollWidth + 'px';
    div.style.height = '100%'//document.body.scrollHeight + 'px';
    div.style.backgroundColor = "white";
    div.style.zIndex 
= 999;
    div.style.filter 
= "Alpha(style=0,opacity=50)";
    div.style.opacity
="0.50";
    
this.divMask = div;
    
    div 
= window.document.createElement("DIV");
    div.style.position 
= "absolute";
    div.style.top 
= "0px";
    div.style.left 
= "0px";
    div.style.width 
= '100%';//document.body.scrollWidth + 'px';
    div.style.height = '100%'//document.body.scrollHeight + 'px';
    div.style.zIndex = 1000;
                    
    
this.divTooltip = div;

    
this.show = function()
    {
        
//创建半透明DIV
        window.__maskDiv__ = document.body.insertAdjacentElement('afterBegin',this.divMask);
        
        
//创建提示DIV
        window.__maskDivText__ = document.body.insertAdjacentElement('afterBegin',this.divTooltip);
        window.__maskDivText__.innerHTML 
= "<table style='border-collapse:collapse;border-width:0px;width:100%;height:100%;'0><tr height='38%'><td></td></tr><tr><td align='center' valign='top'>" + 
                    
"<table style='border-collapse:collapse;border:solid 1px yellow;'><tr><td align='right'><img width='20' height='20' src='image/loading.gif' usesrc='image/loading.gif' onerror='this.src= this.usesrc = \"../\" + this.usesrc'/></td>" + 
                    "<td align='left'><span style = 'filter:alpha(opacity=100);background-color:#ccc;font-size:20px'>提交中.</span></td></tr></table>" + 
                    
"</td></tr></table>";

    }
    
    
this.hide = function()
    {
        
if(window.__maskDiv__ != null)
        {
            document.body.removeChild(window.__maskDiv__);
            window.__maskDiv__  
= null;
        }
        
if(window.__maskDivText__ != null)
        {
            window.__maskDivText__.innerHTML 
= '';
            document.body.removeChild(window.__maskDivText__);
            window.__maskDivText__  
= null;
        }
    }
}

Evlon.MaskDiv.Instance 
= new Evlon.MaskDiv();

window.showModalDialogMask 
= function(sURL , vArguments, sFeatures)
{
    
var sign = window.showModalDialog(sURL , vArguments, sFeatures);
    
if(sign != "" && sign != null)
    {
        
//创建半透明DIV
        Evlon.MaskDiv.Instance.show();
        
    }
    
    
return null;
    
//return sign;
}
复制代码

原文地址:http://www.cnblogs.com/evlon/archive/2009/05/21/1486517.html




本文转自温景良(Jason)博客园博客,原文链接:http://www.cnblogs.com/wenjl520/archive/2010/07/16/1779067.html,如需转载请自行联系原作者


相关文章
|
8月前
|
前端开发
Web前端---表格和表单
Web前端---表格和表单
85 1
|
8月前
|
缓存 安全 Java
7:Servlet表单-Java Web
7:Servlet表单-Java Web
77 0
|
4月前
|
前端开发 数据安全/隐私保护
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
本文档详细介绍了HTML表单的多种元素及其用法,包括下拉菜单(`&lt;select&gt;` 和 `&lt;option&gt;`)、文本域(`&lt;textarea&gt;`)、标签解释(`&lt;label&gt;`)、各类按钮(`&lt;button&gt;`)及表单重置功能、无语义布局标签(`&lt;div&gt;` 和 `&lt;span&gt;`)以及字符实体的应用。此外,还提供了一个完整的注册信息表单案例,涵盖个人信息、教育经历和工作经历等部分,展示了如何综合运用上述元素构建实用的表单。
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
|
4月前
|
前端开发 数据安全/隐私保护
【前端web入门第二天】02 表单-input标签-单选框-多选框
本文介绍了HTML中`&lt;input&gt;`标签的基本使用方法及其应用场景,如登录、注册页面和搜索区域。通过设置`type`属性,可以实现文本框、密码框、单选框、多选框及文件上传等功能。此外,还详细说明了占位文本的使用、单选框的常用属性及多选框的默认选中状态,并提供了示例代码与效果展示。
127 7
|
5月前
|
安全 前端开发 PHP
构建与验证表单:传统PHP与Laravel框架的比较分析——探索Web开发中表单处理的优化策略和最佳实践
【8月更文挑战第31天】在 Web 开发中,表单构建与数据验证至关重要。传统 PHP 方法需手动处理 HTML 表单和数据验证,而 Laravel 框架则提供了一种更现代、高效的解决方案。本文通过对比传统 PHP 和 Laravel 的方法,探讨表单构建与验证的最佳实践。Laravel 通过简洁的语法糖、内置的数据过滤和验证机制,显著提升了代码的安全性和可维护性,适用于大型项目或需要快速开发的场景。然而,在追求灵活性的小型项目中,直接使用 PHP 仍是不错的选择。了解两者的优劣,有助于开发者根据项目需求做出最佳决策。
49 0
|
5月前
|
前端开发 开发者 安全
JSF表单处理大揭秘:数据绑定与事件处理,如何让Web应用更加智能?
【8月更文挑战第31天】在现代Web应用开发中,JSF(JavaServer Faces)框架因强大的表单处理能力而广泛应用。其数据绑定机制可实现表单控件与后端模型的双向传输,降低前后端耦合度,提高代码维护性和类型安全性。事件处理机制则支持丰富的内置与自定义事件,进一步增强应用灵活性。本文通过示例代码展示这些特性,帮助开发者更好地利用JSF构建高效、灵活的Web应用。然而,JSF也存在组件库较小和学习成本较高等局限,需根据具体需求权衡使用。
57 0
|
5月前
|
开发者 Java Spring
JSF 牵手社交登录,如魔法风暴席卷 Web 世界,开启震撼便捷登录之旅!
【8月更文挑战第31天】在互联网时代,便捷登录成为用户的核心需求。社交登录凭借其便捷性、安全性和社交化的特点,在各类Web应用中广泛应用。JavaServer Faces(JSF),作为一款流行的Java Web框架,能够轻松集成社交登录功能,显著提升用户体验。本文详细介绍社交登录的优势,并提供两种JSF集成社交登录的常见方法:一是利用Spring Social等第三方库简化开发;二是自行实现社交登录流程。开发者可根据项目需求选择适合的方案。
56 0
|
5月前
|
安全 Java 云计算
JSF 应用究竟何去何从?云端部署能否成为其全新突破点?快来一探究竟!
【8月更文挑战第31天】本文介绍了将JavaServer Faces(JSF)应用部署到云平台的过程。首先,根据成本、功能、可靠性和安全性选择合适的云平台。接着,展示了构建简单JSF应用的示例代码。最后,以AWS Elastic Beanstalk为例,详细说明了部署流程。部署至云端可提升应用的可用性、扩展性和安全性。
63 0
|
5月前
|
开发者 数据管理 Java
表单革命:Vaadin Forms如何重塑你的Web表单体验,打造用户互动新纪元
【8月更文挑战第31天】在现代Web开发中,表单是用户与应用交互的关键。Vaadin框架提供了强大的表单处理工具,简化了高效且用户友好表单的创建。本文深入探讨Vaadin Forms的工作原理,包括数据绑定、验证和事件处理等功能,并通过详细代码示例,帮助开发者掌握其使用方法,从而构建出满足各种需求的表单。
54 0
|
5月前
|
数据采集 前端开发 开发者
Angular表单控件详解:掌握模板驱动与响应式表单的精髓,让Web应用中的数据采集工作变得高效又简单,彻底告别繁琐的表单处理流程
【8月更文挑战第31天】表单是 Web 应用的关键组件,用于用户登录、注册及信息提交。Angular 作为成熟前端框架,提供了强大的表单处理功能,包括模板驱动与响应式表单。本文通过技术博客形式,详细介绍这两种表单控件,并提供示例代码,展示如何利用它们简化表单处理流程,提高开发效率。首先介绍简单的模板驱动表单,然后讲解基于 RxJS 的响应式表单,适用于复杂逻辑。通过本文,你将学会如何高效地使用 Angular 表单控件,提升应用的用户体验。
60 0