C#实现防止重复提交的代码详解

 更新时间:2025年09月12日 09:20:21   作者:李袁明  
当用户在前端进行提交数据时,如果网络出现卡顿和前端没有给出响应的话顾客通常都会狂点提交按钮,这样就很容易导致后端数据造成脏数据,所以本文给大家介绍了如何避免C#重复提交,需要的朋友可以参考下

前言

当用户在前端进行提交数据时,如果网络出现卡顿和前端没有给出响应的话顾客通常都会狂点提交按钮,这样就很容易导致后端数据造成脏数据,众所周知顾客就是老天爷,这种问题一定是咱有问题。下面我们就来看看如何避免这种情况吧。

防止重复提交的思路

防止重复提交我们可以才用缓存的方式存储一个key在我们的Redis或者其他类型的缓存,再给它设置一个过期时间比如五秒或者三四秒,这个时间最好不要设置的过长,不然会影响用户体验。值得注意的是这个key一定要是与用户一一对应且不会重复的!

Web API 防止重复提交

代码实现

以下是具体的代码实现:

// <summary>
	/// 防重复提交,api使用
	/// </summary>
	public class LockAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 拦截
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            if (GlobalContext.SystemConfig.Debug == false)
            {
                if (OperatorProvider.Provider.GetCurrent() == null)
                {
                    context.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "抱歉,没有操作权限" });
                    return;
                }
                else
                {
                    string token = context.HttpContext.Request.Headers[GlobalContext.SystemConfig.TokenName].ParseToString();
                    if (string.IsNullOrWhiteSpace(token))
                    {
                        context.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "token不能空" });
                        return;
                    }
                    //固定加锁5秒
                    bool result = CacheHelper.SetNx(token, token, 5);
                    if (!result)
                    {
                        context.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "请求太频繁,请稍后" });
                        return;
                    }
                }
            }
            await next();

            sw.Stop();
        }
    }

代码讲解

  • GlobalContext.SystemConfig.Debug :这里是读取配置文件判断是否为开发环境
  • OperatorProvider.Provider.GetCurrent():获取顾客在系统中的权限
  • context.HttpContext.Request.Headers[GlobalContext.SystemConfig.TokenName]:这里是通过上线文获取顾客的Token
  • CacheHelper.SetNx:这里是设置缓存:该方法会查询缓存中是否已有该用户的缓存信息,如果已经有了则返回false,没有就设置该用户的缓存并返回true。

使用方法

直接以特性的形似使用,在需要进行锁定的接口上标注即可

MVC防止重复提交

public class HandlerLockAttribute : ActionFilterAttribute
{
	public HandlerLockAttribute()
	{
	}

	public override void OnActionExecuting(ActionExecutingContext filterContext)
	{
		if (OperatorProvider.Provider.GetCurrent() == null)
		{
			WebHelper.WriteCookie("WaterCloud_login_error", "overdue");
			//filterContext.HttpContext.Response.WriteAsync("<script>top.location.href ='" + filterContext.HttpContext.Request.PathBase + "/Home/Error?msg=408" + "';if(document.all) window.event.returnValue = false;</script>");
			OperatorProvider.Provider.EmptyCurrent("pc_").GetAwaiter().GetResult();
			filterContext.Result = new RedirectResult(filterContext.HttpContext.Request.PathBase + "/Home/Error?msg=408");
			return;
		}
		else
		{
			string token = filterContext.HttpContext.Request.Cookies["pc_" + GlobalContext.SystemConfig.TokenName];
			string cacheToken = CacheHelper.GetAsync<string>("pc_" + GlobalContext.SystemConfig.TokenName + "_" + OperatorProvider.Provider.GetCurrent().UserId + "_" + OperatorProvider.Provider.GetCurrent().LoginTime).GetAwaiter().GetResult();
			if (string.IsNullOrWhiteSpace(token))
			{
				filterContext.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "token不能空" });
				return;
			}
			if (string.IsNullOrWhiteSpace(cacheToken))
			{
				filterContext.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "token不能空" });
				return;
			}
			if (token != cacheToken)
			{
				filterContext.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "请求异常" });
				return;
			}
			//固定加锁5秒
			bool result = CacheHelper.SetNx(token, token, 5);
			if (!result)
			{
				filterContext.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "请求太频繁,请稍后" });
				return;
			}
		}
		//随机值
		base.OnActionExecuting(filterContext);
	}
}
  • OperatorProvider.Provider.EmptyCurrent(“pc_”).GetAwaiter().GetResult():此处是判断如果顾客信息为空的话就清空当前登录账户的缓存
  • CacheHelper.SetNx:这里是设置缓存:该方法会查询缓存中是否已有该用户的缓存信息,如果已经有了则返回false,没有就设置该用户的缓存并返回true。

总结

到此这篇关于C#实现防止重复提交的代码详解的文章就介绍到这了,更多相关C#防止重复提交内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#实现图片缩略图功能的示例详解

    C#实现图片缩略图功能的示例详解

    这篇文章主要为大家详细介绍了如何利用C#实现图片缩略图的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • 基于WPF实现弹幕效果的示例代码

    基于WPF实现弹幕效果的示例代码

    这篇文章主要为大家详细介绍了如何利用WPF实现弹幕效果,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下
    2022-09-09
  • 在Framework 4.0中:找出新增的方法与新增的类(一)

    在Framework 4.0中:找出新增的方法与新增的类(一)

    经常看到有同学在讨论Framework 4 的新特性,新方法,于是想写个程序找出framework4.0中新增的方法和类
    2013-05-05
  • WPF使用WinSCP实现FTP下载

    WPF使用WinSCP实现FTP下载

    这篇文章主要为大家详细介绍了WPF如何使用WinSCP实现FTP下载,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下
    2023-01-01
  • C#中调用SAPI实现语音识别的2种方法

    C#中调用SAPI实现语音识别的2种方法

    这篇文章主要介绍了C#中调用SAPI实现语音识别的2种方法,本文直接给出实现代码,需要的朋友可以参考下
    2015-06-06
  • c#入门之循环语句使用详解(for循环、do/while)

    c#入门之循环语句使用详解(for循环、do/while)

    这篇文章主要介绍了c#入门之循环语句使用详解,有for循环和do/while的示例,需要的朋友可以参考下
    2014-04-04
  • Winform实现抓取web页面内容的方法

    Winform实现抓取web页面内容的方法

    这篇文章主要介绍了Winform实现抓取web页面内容的方法,代码只有短短几行,但是功能很实用,需要的朋友可以参考下
    2014-09-09
  • WPF实现手风琴式轮播图切换效果

    WPF实现手风琴式轮播图切换效果

    这篇文章主要为大家详细介绍了WPF实现手风琴式轮播图切换效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-09-09
  • C#索引属性用法实例分析

    C#索引属性用法实例分析

    这篇文章主要介绍了C#索引属性用法,实例分析了C#声明索引属性的相关技巧,需要的朋友可以参考下
    2015-06-06
  • C#实现任务栏通知窗口

    C#实现任务栏通知窗口

    作为程序员在享受的同时我们也不禁要问:这到底是怎么实现的呢?本文就利用Visual Studio .Net C# 2005以及.Net框架绘图技术来实现这种任务栏通知窗口。
    2015-10-10

最新评论