views:

264

answers:

3

Hi folks,

Image i have a view that is cached with the OutputCache attribute but i still need to increment a counter that records that the page has been viewed, how could i do it?

I thought about creating my own Custom ActionFilterAttribute, and using Action Filter Order of Execution to record this .. but i'm not sure it will work.

eg.

[IncrementViewCountFilter(Order=1)]
[OutputCache(Duration=60,Order=2)]
public ActionResult Index(int questionId)
{ ... }

Firstly, my assumption here is that if the OutputCache is called, and the page is cached, then the controller code will not be ran.

Next problem i'm guessing is that the IncrementViewCountFilter wouldn't know about the questionId, so how would it know what to increment (because it is executed before the main Index code is executed).

Secondly, if the IncrementViewCountFilter did know the questionId .. and it's getting lots of hits, you wouldn't want it to write all the time to the DB.. but only when it gets to a certain number .. and then u 'flush' the output.

Anyone have any thoughts?

A: 

I can't comment on the MVC side but if I was doing this in WebForms this sounds like it would be a candidate for output cache substitution aka donut caching.

PhilPursglove
+1  A: 

The filter can get the questionId from the ActionExecutingContext.ActionParameters, which is passed to OnActionExecuting. As for caching the hit counts, well, use the cache. :)

Craig Stuntz
Can u provide some sample code about retreiving the questionId from the RouteData, please?
Pure.Krome
Pardon me, it's ActionExecutingContext.ActionParameters you want. This is passed to ActionFilterAttribute.OnActionExecuting. (In Preview 5, anyway.)
Craig Stuntz
Kewl! with caching the hit counts, in the cache.. yeah. i was going to do that but the key was HOW and WHEN to flush that count (ie: persist that info). I was thinking about maybe having a timer created on application-start and let it flush every xxx mins?
Pure.Krome
+4  A: 

Well, you have a few options.

Donut caching

One server-side option is 'Donut caching'. Donut caching allows most of the page to be cached, and portions of the page to be not cached (the hole in the middle of the donut). Donut caching is described here, and I have used it with great success.

Image-based tracker

Another option is having an image on the page actually load a server-side action that records the hit. This would look like

<img src="/controller/action">

on the page, where the action serves up an empty image at the end.

Client-side tracking

The last option is client-side tracking -- where some script runs on the client side and uses AJAX to call something on the server to record the hit. Google uses something like this for their Analytics package. If you're on the same domain as your tracking mechanism ... like if your main page is:

http://www.domain.com/home/action

and the tracker is on

http://www.domain.com/tracking/action

then you should be fine.

This gets tricky when your tracker is on a different domain (you need to handle this using JSONP or some other mechanism that allows for relatively safe cross-site scripting).

Dan Esparza