【问题标题】:what is the best way to capture page views per user in asp.net-mvc在 asp.net-mvc 中捕获每个用户的页面浏览量的最佳方法是什么
【发布时间】:2011-05-21 02:32:19
【问题描述】:

在不降低网站性能的情况下按人捕获页面浏览量的最佳方法是什么?我看到stackoverflow到处都显示页面视图。每次我点击页面时,他们都会插入数据库吗?

在 asp.net-mvc 中,是否有任何推荐的方法来跟踪每个用户的页面浏览量(我的网站有一个登录屏幕),以便我可以查看人们访问哪些页面以及访问频率

【问题讨论】:

  • 您使用的是哪个版本的 asp.net mvc?

标签: c# asp.net-mvc pageviews


【解决方案1】:

首先.. 如果您真正关心的是客户如何使用我的网站,那么您很可能希望查看Google Analytics 或类似服务。

但是,如果您想要一个快速而肮脏的页面查看记录,并且您正在使用 ASP.Net MVC 3,那么正如 Chris Fulstow 所提到的,您将想要混合使用全局操作过滤器和缓存。这是一个例子。

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; }
    }
}

在你的 Global.asax.cs 中

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

对于 ASP.Net MVC 3 之前的版本,您必须手动将相同的属性应用于所有操作。

[PageView]
public ActionResult CallOne()
{
}

[PageView]
public ActionResult CallTwo()
{
}

【讨论】:

  • @ShaneC - 感谢您的回复。 .唯一的问题是我没有看到你在任何地方坚持这个
  • 不知道你的数据库是如何设置的......我朋友的那部分取决于你:) 在 onRemove 中看到它说 // 将值写入数据库
  • @ShaneC - 何时调用 OnRemove?在单页加载时?
  • 不,它只在缓存过期时调用。它作为 On remove 回调传递到 Cache.Insert 调用中。
  • @usr - 你不关心其余的(例如内容请求)
【解决方案2】:

最好的方法可能是global action filter,它拦截对所有控制器上所有操作的请求,然后在数据库中为当前用户和页面增加一个计数器。为了避免过多地访问数据库,您可以缓存这些值并每隔几分钟使它们失效,具体取决于您处理的流量。

【讨论】:

  • 您能否更详细地解释一下您将如何缓存该值并每隔几分钟使它们无效?
  • 查看 System.Web.Caching.Cache 类 - msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx - 它可以让您在内存中缓存值并设置到期日期。
  • 动作过滤器不是正确的选择。您不会收到所有请求,只会收到 MVC 请求。
  • @usr 不认为我们要在这里跟踪所有请求吗?只是页面视图,可以合理地假设为 MVC 控制器操作。
【解决方案3】:

我们使用开源 Piwik:http://piwik.org/,它安装在自己的服务器上。 _Layout页面中的一行Javascript在页面加载后调用Piwik(将JS放在最后),完全不影响页面加载性能。

除了计数之外,您还会获得大量有关用户来源、浏览器、屏幕分辨率、已安装插件的信息。此外,您可以跟踪转化并使用相同的工具来跟踪营销活动等。

我想不出在 MVC 或一般的 Web 应用程序中实现此功能会更好的情况。这些东西根本不属于你的网络应用程序,是一个应该分离出来的元问题。这种方法使我们能够以统一的方式跟踪我们所有应用程序(其中 32 个:mvc 2/3、webforms、php...)的分析。

如果您真的不想为此目的使用其他工具,我建议您访问您的 IIS 日志并从那里获取您的统计信息。同样,要从中获得任何真正的决策能力,您需要在其上放置一个好的分析器。我推荐 Splunk:http://www.splunk.com/

【讨论】:

  • 有一个论点是将用于此类分析的 JavaScript 放在更靠近页面顶部的位置,因为它能够记录被放弃的页面请求或非常快速的页面请求 - 例如,如果我点击“产品”,在页面完成加载之前,我发现了一个“相机”链接并单击它 - 页面底部的脚本实际上不会记录我对“产品”页面的访问。
  • @Sohnee:同意。 Piwik 还可以通过嵌入 1 个像素的图像来跟踪点击量。如果 Javascript 性能成为一个问题,这将是一个不太强大的替代方案。
  • @xameeramir 是的,但是我们的网络团队发现 Google Analytics 更好,所以我们正在转换。另外,我们不是 PHP 的粉丝。
【解决方案4】:

我想为感兴趣的人发布 Shane 答案的更新版本。需要考虑的一些事项:

  1. 您必须在装饰时将 action 属性设置为服务 使用如下语法的方法:

    [ServiceFilter(typeof(PageViewAttribute))]

  2. 据我所知,HttpRuntime.Cache.Insert 不是 .NET Core 中的东西,所以我使用了 IMemoryCache 的简单实现(您可能需要将此行添加到您的 startup.cs 中才能使用界面):

    services.AddMemoryCache();

  3. 因为我们将 IMemoryCache 注入到一个不是控制器的类中,所以我们需要在 startup.cs 中将我们的属性注册为服务,如下所示:

    services.AddScoped(); - 没有括号!

  4. 创建 cacheKey 时返回的任何对象都将分配给 OnRemove 方法的 'value' 参数。

下面是代码。

public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var controllerActionDescriptor = filterContext.ActionDescriptor as ControllerActionDescriptor;

        var arguments = filterContext.ActionArguments;
        ActionId = arguments["id"].ToString();

        var calledMethod = string.Format("{0} -> {1}",
                                         controllerActionDescriptor.ControllerName,
                                         controllerActionDescriptor.ActionName);

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

        var cachedResult = _memoryCache.Get(cacheKey);

        if (cachedResult == null)
        {
            //Get cacheKey if found, if not create cache key with following settings
            _memoryCache.GetOrCreate(cacheKey, cacheKey =>
            {
                cacheKey.AbsoluteExpirationRelativeToNow
                              = pageViewDumpToDatabaseTimeSpan;
                cacheKey.SetValue(1);
                cacheKey.RegisterPostEvictionCallback(onRemove);
                return cacheKey.Value;
            });
        }
        else
        {
            _memoryCache.Get(cacheKey);
        }
    }

    //Called when Memory entry is removed
    private void onRemove(object key, object value, EvictionReason reason, object state)
    {
        if (!key.ToString().StartsWith("PV-"))
        {
            return;
        }

        // write out the value to the database
        SaveToDataBase(key.ToString(), (int)value);

    }

作为参考,这是针对 .NET Core 5 MVC 应用程序完成的。

问候。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-29
    • 2012-04-08
    • 2011-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多