what is the best way to capture page views per user in asp.net-mvc

leora picture leora · May 21, 2011 · Viewed 14.7k times · Source

what is the best way to capture page views by person without slowing down performance on the site. I see that stackoverflow show page views all over the place. Are they doing an insert into a db everytime i click on a page?

In asp.net-mvc, Is there any recommended way to track page view per user (my site has a login screen) so i can review which pages people are going to and how often

Answer

Shane Courtrille picture Shane Courtrille · Jun 16, 2011

First off.. if what you really care about is how are customers using my site then you most likely want to look into Google Analytics or a similar service.

But if you want a quick and dirty page view record and you are using ASP.Net MVC 3 then as Chris Fulstow mentioned you're going to want to use a mix of global action filters and caching. Here is an example.

PageViewAttribute.cs 

    public class PageViewAttribute : ActionFilterAttribute
{
    private static readonly TimeSpan pageViewDumpToDatabaseTimeSpan = new TimeSpan(0, 0, 10);

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var calledMethod = string.Format("{0} -> {1}",
                                         filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
                                         filterContext.ActionDescriptor.ActionName);

        var cacheKey = string.Format("PV-{0}", calledMethod);

        var cachedResult = HttpRuntime.Cache[cacheKey];

        if(cachedResult == null)
        {
            HttpRuntime.Cache.Insert(cacheKey, new PageViewValue(), null, DateTime.Now.Add(pageViewDumpToDatabaseTimeSpan) , Cache.NoSlidingExpiration, CacheItemPriority.Default,
                                  onRemove);
        }
        else
        {
            var currentValue = (PageViewValue) cachedResult;

            currentValue.Value++;
        }
    }

    private static void onRemove(string key, object value, CacheItemRemovedReason reason)
    {
        if (!key.StartsWith("PV-"))
        {
            return;
        }

        // write out the value to the database
    }

    // Used to get around weird cache behavior with value types
    public class PageViewValue
    {
        public PageViewValue()
        {
            Value = 1;
        }

        public int Value { get; set; }
    }
}

And in your Global.asax.cs

public class MvcApplication : HttpApplication 
{
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new PageViewAttribute());
        }
}

For pre-ASP.Net MVC 3 ONLY you are going to have to apply the same attribute manually to all of your actions.

[PageView]
public ActionResult CallOne()
{
}

[PageView]
public ActionResult CallTwo()
{
}