0

I am trying to implement something in ASP.NET MVC where I can make each user perform an action once every n minutes.

I have come across controls such as Timer but, not quite sure what to use. I would like it so that when the user performs the action, a timer begins to count down from, for example, 3 minutes to 0:00. Once the 3 minutes have lapsed, the user will be able to perform the action again.

Any ideas how I can achieve this? Would I need a Timer Control?

Subby
  • 5,370
  • 15
  • 70
  • 125

4 Answers4

1

There is a perfect solution here: Best way to implement request throttling in ASP.NET MVC? created by SO team.

Basically the idea is to store page hits for each user in the cache and then respond to a request based on your logic.

Community
  • 1
  • 1
bobek
  • 8,003
  • 8
  • 39
  • 75
1

The easiest way to do this would be to save the time of the last action in the session and on subsequent requests check whether it has been more than 3 minutes. For example:

public ActionResult DoSomething(){
     if (Session["LastAction"] == null || (DateTime.Now - (DateTime)(Session["LastAction"])).Minutes > 3){
          // do action
          Session["LastAction"] = DateTime.Now;
          return View("OK. action executed");
     }
     else{
          return View("Please wait");
     }
}
Kenneth
  • 28,294
  • 6
  • 61
  • 84
  • This seems feasible and makes clear sense. I shall try this out! – Subby May 22 '13 at 21:01
  • What if the user deletes cookies? Will this method still work? – Subby May 22 '13 at 21:03
  • No, it won't. If you want it to be related to the user you will always have a possibility of circumventing it. If he opens another browser it won't work either. – Kenneth May 22 '13 at 21:04
  • @Subby no it won't. Unless you store your session in the URL. – bobek May 22 '13 at 21:04
  • Would it therefore be wise to store the time against the User in the database? – Subby May 22 '13 at 21:06
  • If the user is authenticated, sure. – bobek May 22 '13 at 21:08
  • It would be a possibility. If you have a logged in user, you could also store it in the application-object. That way it's not depending on cookies – Kenneth May 22 '13 at 21:08
  • Would using this "Application-object" be better than storing the value in the database against the User? – Subby May 22 '13 at 21:09
  • It would certainly be easier. You just replace `Session` with `HttpContext.Application` (and of course add an identifier for the user, since application is shared by everyone, whereas session is a per user object). In terms of what's the best solution, it all depends on your architecture and requirements – Kenneth May 22 '13 at 21:10
  • Right okie doke. I'll research in to HttpContext.Application. – Subby May 22 '13 at 21:12
  • When I do: HttpContext.Current.Application[user.Username] = DateTime.Now().ToString(); - it says it doesn't recognise Current. – Subby May 22 '13 at 21:42
  • It should be `HttpContext.Application`. You should get rid of `Current` – Kenneth May 22 '13 at 21:52
  • I get a null reference when doing: DateTime lastEarn = (DateTime)HttpContext.Application[user.Username]; – Subby May 22 '13 at 22:08
  • Well, the first time there's probably no value yet, so the cast will fail. You should do a null check before doing this. I have updated my answer – Kenneth May 22 '13 at 22:14
  • I saw my mistake immediately after posting the comment and did exactly as how you have deduced. The problem which I can see however is that the Null check succeeds on the 3rd or 4th request.... Why is this? – Subby May 22 '13 at 22:16
  • Well, surely there must be something in there then. Have you checked the value? – Kenneth May 22 '13 at 22:30
  • When running for the first time, the value is null and it gets assigned. When I try again, every works fine. When I try once more, the value turns out to be null. – Subby May 22 '13 at 22:35
1

You could use jquery-timer http://code.google.com/p/jquery-timer/

Basic use would be disable button, invoke timer and then re-enable button when it completes.

However, if you want to post back in the interim this would not work.

alanh
  • 1,153
  • 10
  • 14
1

The most elegant way to achieve this is implementing a job scheduler like Quartz.NET and defining proper job (what has to be done) and proper trigger (when/how often has to be done). With Quartz you can also implement much more complex conditions ("do it every Monday" etc).

Hope it will help.

Kamil Będkowski
  • 1,092
  • 4
  • 16
  • 36