在 asp.net-mvc 中捕获每个用户页面视图的最佳方法是什么

发布于 2024-11-09 04:13:12 字数 166 浏览 4 评论 0原文

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鹿! 2024-11-16 04:13:12

首先..如果您真正关心的是客户如何使用我的网站,那么您很可能想要研究 Google分析或类似服务。

但是,如果您想要快速而脏的页面视图记录,并且您正在使用 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()
{
}

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()
{
}
吃不饱 2024-11-16 04:13:12

最好的方法可能是 全局操作过滤器,拦截所有控制器上所有操作的请求,然后增加数据库中当前用户和页面的计数器。为了避免对数据库造成太大影响,您可以缓存这些值并每隔几分钟使它们失效,具体取决于您正在处理的流量。

The best way would probably be a global action filter that intercepts requests to all actions on all controllers, then increments a counter in the database for the current user and page. To save hitting the database too hard, you could cache these values and invalidate them every few minutes, depending on how much traffic you're dealing with.

温柔少女心 2024-11-16 04:13:12

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

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

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

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

We use the open source Piwik: http://piwik.org/, which is setup on it's own server. One line of Javascript in the _Layout page makes a call to Piwik after the page has loaded (put the JS at the end) and does not affect page load performance at all.

In addition to just counts, you'll get a ton of info about where your users are coming from, browser, screen resolutions, installed plugins. Plus you can track conversions and use the same tool to track marketing campaigns, etc.

<soapbox>

I cannot think of a situation where you'd be better off implementing this in MVC or in your web app in general. This stuff simply does not belong in your web app and is a meta-concern that should be separated out. This approach has enabled us to track analytics for all of our apps (32 of them: mvc 2/3, webforms, php...) in a unified manner.

If you really don't want to use another tool for this purpose, I would recommend tapping into your IIS log and getting your stats from there. Again, to get any real decision making power out of it, you'll need to put a good analyzer on it. I recommend Splunk: http://www.splunk.com/

</soapbox>

痴意少年 2024-11-16 04:13:12

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

  1. 在装饰您的应用程序时,您必须将操作属性设置为服务
    使用如下语法的方法:

    [ServiceFilter(typeof(PageViewAttribute))]

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

    services.AddMemoryCache();

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

    services.AddScoped<[PageViewAttribute]>(); - 没有括号!

  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 应用程序完成的。

问候。

I wanted to post an updated version of Shane's answer for those who are interested. Some things to consider:

  1. You have to set the action attribute up as a service when decorating your
    methods using syntax like the following :

    [ServiceFilter(typeof(PageViewAttribute))]

  2. As far as I can tell, HttpRuntime.Cache.Insert isn't a thing in .NET Core, so I used a simple implementation of IMemoryCache (You may need to add this line to your startup.cs in order to use the interface):

    services.AddMemoryCache();

  3. Because we are injecting IMemoryCache into a class that is not a controller, we need to register our attribute as a service in startup.cs, like so:

    services.AddScoped<[PageViewAttribute]>(); - without brackets!

  4. Whatever object you return when creating a cacheKey will be assigned to the 'value' parameter of the OnRemove method.

Below is the code.

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

    }

As a point of reference, this was done for a .NET Core 5 MVC App.

Regards.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文