code_junkie

Best way to implement request throttling in ASP.NET MVC?

Nov 10th, 2011
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.28 KB | None | 0 0
  1. /// <summary>
  2. /// Decorates any MVC route that needs to have client requests limited by time.
  3. /// </summary>
  4. /// <remarks>
  5. /// Uses the current System.Web.Caching.Cache to store each client request to the decorated route.
  6. /// </remarks>
  7. [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
  8. public class ThrottleAttribute : ActionFilterAttribute
  9. {
  10. /// <summary>
  11. /// A unique name for this Throttle.
  12. /// </summary>
  13. /// <remarks>
  14. /// We'll be inserting a Cache record based on this name and client IP, e.g. "Name-192.168.0.1"
  15. /// </remarks>
  16. public string Name { get; set; }
  17.  
  18. /// <summary>
  19. /// The number of seconds clients must wait before executing this decorated route again.
  20. /// </summary>
  21. public int Seconds { get; set; }
  22.  
  23. /// <summary>
  24. /// A text message that will be sent to the client upon throttling. You can include the token {n} to
  25. /// show this.Seconds in the message, e.g. "Wait {n} seconds before trying again".
  26. /// </summary>
  27. public string Message { get; set; }
  28.  
  29. public override void OnActionExecuting(ActionExecutingContext c)
  30. {
  31. var key = string.Concat(Name, "-", c.HttpContext.Request.UserHostAddress);
  32. var allowExecute = false;
  33.  
  34. if (HttpRuntime.Cache[key] == null)
  35. {
  36. HttpRuntime.Cache.Add(key,
  37. true, // is this the smallest data we can have?
  38. null, // no dependencies
  39. DateTime.Now.AddSeconds(Seconds), // absolute expiration
  40. Cache.NoSlidingExpiration,
  41. CacheItemPriority.Low,
  42. null); // no callback
  43.  
  44. allowExecute = true;
  45. }
  46.  
  47. if (!allowExecute)
  48. {
  49. if (String.IsNullOrEmpty(Message))
  50. Message = "You may only perform this action every {n} seconds.";
  51.  
  52. c.Result = new ContentResult { Content = Message.Replace("{n}", Seconds.ToString()) };
  53. // see 409 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  54. c.HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
  55. }
  56. }
  57. }
  58.  
  59. [Throttle(Name="TestThrottle", Message = "You must wait {n} seconds before accessing this url again.", Seconds = 5)]
  60. public ActionResult TestThrottle()
  61. {
  62. return Content("TestThrottle executed");
  63. }
Add Comment
Please, Sign In to add comment