C#防止重復提交
文章目錄
- C#防止重復提交
- 前言
- 防止重復提交的思路
- Web API 防止重復提交
- 代碼實現
- 代碼講解
- 使用方法
- MVC防止重復提交
- 總結
前言
當用戶在前端進行提交數據時,如果網絡出現卡頓和前端沒有給出響應的話顧客通常都會狂點提交按鈕,這樣就很容易導致后端數據造成臟數據,眾所周知顧客就是老天爺,這種問題一定是咱有問題。下面我們就來看看如何避免這種情況吧。
防止重復提交的思路
防止重復提交我們可以才用緩存的方式存儲一個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。
總結
這里主要是通過過濾器實現的。這里順帶提一下,過濾器也屬于是AOP編程的體現哦。今日的分享就到此結束,有什么不懂的可以留言討論。