C#實現(xiàn)防止重復(fù)提交的代碼詳解
前言
當(dāng)用戶在前端進(jìn)行提交數(shù)據(jù)時,如果網(wǎng)絡(luò)出現(xiàn)卡頓和前端沒有給出響應(yīng)的話顧客通常都會狂點提交按鈕,這樣就很容易導(dǎo)致后端數(shù)據(jù)造成臟數(shù)據(jù),眾所周知顧客就是老天爺,這種問題一定是咱有問題。下面我們就來看看如何避免這種情況吧。
防止重復(fù)提交的思路
防止重復(fù)提交我們可以才用緩存的方式存儲一個key在我們的Redis或者其他類型的緩存,再給它設(shè)置一個過期時間比如五秒或者三四秒,這個時間最好不要設(shè)置的過長,不然會影響用戶體驗。值得注意的是這個key一定要是與用戶一一對應(yīng)且不會重復(fù)的!
Web API 防止重復(fù)提交
代碼實現(xiàn)
以下是具體的代碼實現(xiàn):
// <summary>
/// 防重復(fù)提交,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 = "抱歉,沒有操作權(quán)限" });
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 :這里是讀取配置文件判斷是否為開發(fā)環(huán)境
- OperatorProvider.Provider.GetCurrent():獲取顧客在系統(tǒng)中的權(quán)限
- context.HttpContext.Request.Headers[GlobalContext.SystemConfig.TokenName]:這里是通過上線文獲取顧客的Token
- CacheHelper.SetNx:這里是設(shè)置緩存:該方法會查詢緩存中是否已有該用戶的緩存信息,如果已經(jīng)有了則返回false,沒有就設(shè)置該用戶的緩存并返回true。
使用方法

直接以特性的形似使用,在需要進(jìn)行鎖定的接口上標(biāo)注即可
MVC防止重復(fù)提交
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;
}
}
//隨機(jī)值
base.OnActionExecuting(filterContext);
}
}
- OperatorProvider.Provider.EmptyCurrent(“pc_”).GetAwaiter().GetResult():此處是判斷如果顧客信息為空的話就清空當(dāng)前登錄賬戶的緩存
- CacheHelper.SetNx:這里是設(shè)置緩存:該方法會查詢緩存中是否已有該用戶的緩存信息,如果已經(jīng)有了則返回false,沒有就設(shè)置該用戶的緩存并返回true。
總結(jié)
到此這篇關(guān)于C#實現(xiàn)防止重復(fù)提交的代碼詳解的文章就介紹到這了,更多相關(guān)C#防止重復(fù)提交內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#的Socket實現(xiàn)UDP協(xié)議通信示例代碼
本篇文章主要介紹了C#的Socket實現(xiàn)UDP協(xié)議通信示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01
C#實現(xiàn)將記事本中的代碼編譯成可執(zhí)行文件的方法
這篇文章主要介紹了C#實現(xiàn)將記事本中的代碼編譯成可執(zhí)行文件的方法,很實用的技巧,需要的朋友可以參考下2014-08-08
Extjs4如何處理后臺json數(shù)據(jù)中日期和時間
本文給大家分享Extjs4如何處理后臺json數(shù)據(jù)中日期和時間,通過代碼示例給大家剖析,感興趣的朋友快來圍觀2015-08-08
c#winform窗口頁面一打開就加載的實現(xiàn)方式
這篇文章主要介紹了c#winform窗口頁面一打開就加載的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06

