IdempotentAttribute.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. 
  2. using System.Security.Claims;
  3. namespace Admin.NET.Core
  4. {
  5. public class IdempotentAttribute : Attribute, IAsyncActionFilter
  6. {
  7. /// <summary>
  8. /// 请求间隔时间
  9. /// </summary>
  10. public int Delay = 7;
  11. /// <summary>
  12. /// 错误提示内容
  13. /// </summary>
  14. public string Msg = "您的操作太快了,请稍稍慢一点!";
  15. /// <summary>
  16. /// 自定义缓存Key 缓存规则 Key + 请求路由 + 用户id + 请求参数
  17. /// </summary>
  18. public string Key = "";
  19. /// <summary>
  20. /// false 返回上次请求结果 true 直接抛出异常
  21. /// </summary>
  22. public bool Ops = false;
  23. private SysCacheService _sysCacheService { get; set; }
  24. public IdempotentAttribute()
  25. {
  26. _sysCacheService = App.GetService<SysCacheService>();
  27. }
  28. public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
  29. {
  30. var httpContext = context.HttpContext;
  31. var path = httpContext.Request.Path.Value.ToString();
  32. var userId = httpContext.User?.FindFirstValue(ClaimConst.UserId);
  33. var tenSeconds = TimeSpan.FromSeconds(Delay);
  34. var parameters = "";
  35. foreach ( var parameter in context.ActionDescriptor.Parameters)
  36. {
  37. parameters += parameter.Name;
  38. parameters += context.ActionArguments[parameter.Name].ToJson();
  39. }
  40. var cacheKey = MD5Encryption.Encrypt(Key + path + userId + parameters);
  41. if (_sysCacheService.ExistKey(cacheKey))
  42. {
  43. if (Ops) throw Oops.Oh(Msg);
  44. try
  45. {
  46. var cachedResult = _sysCacheService.Get<RequestData>(cacheKey);
  47. context.Result = new ObjectResult(cachedResult.value);
  48. }
  49. catch (Exception)
  50. {
  51. throw Oops.Oh(Msg);
  52. }
  53. }
  54. else
  55. {
  56. //先加入一个空的缓存,防止第一次请求结果没回来导致连续请求。
  57. _sysCacheService.Set(cacheKey, "", tenSeconds);
  58. var resultContext = await next();
  59. if (resultContext.Result is ObjectResult objectResult)
  60. {
  61. var valueType = objectResult.Value.GetType();
  62. var requestData = new RequestData
  63. {
  64. type= valueType.Name,
  65. value = objectResult.Value
  66. };
  67. _sysCacheService.Set(cacheKey, requestData, tenSeconds);
  68. }
  69. }
  70. }
  71. /// <summary>
  72. /// 请求结果
  73. /// </summary>
  74. private class RequestData
  75. {
  76. /// <summary>
  77. /// 请求结果返回的数据
  78. /// </summary>
  79. public dynamic value { get; set; }
  80. /// <summary>
  81. /// 结果类型
  82. /// </summary>
  83. public string type { get; set; }
  84. }
  85. }
  86. }