#c# #asp.net-mvc #pageviews
#c# #asp.net-mvc #просмотры страниц
Вопрос:
каков наилучший способ фиксировать просмотры страниц каждым пользователем без снижения производительности сайта. Я вижу, что stackoverflow показывает просмотры страниц повсюду. Выполняют ли они вставку в базу данных каждый раз, когда я нажимаю на страницу?
В asp.net-mvc есть ли какой-либо рекомендуемый способ отслеживать просмотр страниц для каждого пользователя (на моем сайте есть экран входа в систему), чтобы я мог просматривать, какие страницы посещают люди и как часто
Комментарии:
1. Какая версия asp.net вы используете mvc?
Ответ №1:
Во-первых .. если вас действительно волнует, как клиенты используют мой сайт, то вы, скорее всего, захотите заглянуть в Google Analytics или аналогичный сервис.
Но если вам нужна быстрая и грязная запись о просмотре страницы, и вы используете ASP.Net MVC 3 тогда, как упоминал Крис Фулстоу, вам захочется использовать сочетание глобальных фильтров действий и кэширования. Вот пример.
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) cachedResu<
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());
}
}
Для pre-ASP.Net ТОЛЬКО на MVC 3 вам придется вручную применять один и тот же атрибут ко всем вашим действиям.
[PageView]
public ActionResult CallOne()
{
}
[PageView]
public ActionResult CallTwo()
{
}
Комментарии:
1. @ShaneC — спасибо за ваш ответ. .единственная проблема в том, что я нигде не вижу, чтобы вы сохраняли это
2. Понятия не имею, как настроена ваша база данных .. эта часть, мой друг, зависит от вас 🙂 смотрите в onRemove, где говорится // записать значение в базу данных
3. @ShaneC — когда вызывается OnRemove? При любой загрузке одной страницы?
4. Нет, он вызывается только по истечении срока действия кэша. Он передается в кэш. Вставить вызов в качестве обратного вызова при удалении.
5. @usr — вас не волнует остальное (например, запросы контента)
Ответ №2:
Вероятно, лучшим способом был бы глобальный фильтр действий, который перехватывает запросы ко всем действиям на всех контроллерах, затем увеличивает счетчик в базе данных для текущего пользователя и страницы. Чтобы не слишком сильно нагружать базу данных, вы могли бы кэшировать эти значения и аннулировать их каждые несколько минут, в зависимости от объема трафика, с которым вы имеете дело.
Комментарии:
1. можете ли вы более подробно объяснить, как вы будете кэшировать значения и аннулировать их каждые несколько минут?
2. Проверьте System.Web.Caching. Класс кэша — msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx — это позволит вам кэшировать значения в памяти и устанавливать дату истечения срока действия.
3. Фильтр действий — неправильный выбор. Вы не будете получать все запросы, только запросы MVC.
4. @usr не думаете, что мы хотим отслеживать все запросы здесь? Просто просмотры страниц, которые можно разумно считать действиями контроллера MVC.
Ответ №3:
Мы используем Piwik с открытым исходным кодом:http://piwik.org /, который настроен на собственном сервере. Одна строка Javascript на странице _Layout вызывает Piwik после загрузки страницы (поместите JS в конце) и вообще не влияет на производительность загрузки страницы.
В дополнение к простым подсчетам, вы получите массу информации о том, откуда приходят ваши пользователи, браузере, разрешениях экрана, установленных плагинах. Кроме того, вы можете отслеживать конверсии и использовать тот же инструмент для отслеживания маркетинговых кампаний и т.д.
<soapbox>
Я не могу представить ситуацию, когда вам было бы лучше реализовать это в MVC или в вашем веб-приложении в целом. Этот материал просто не относится к вашему веб-приложению и является мета-проблемой, которую следует выделить. Этот подход позволил нам отслеживать аналитику для всех наших приложений (32 из них: mvc 2/3, webforms, php …) унифицированным образом.
Если вы действительно не хотите использовать другой инструмент для этой цели, я бы рекомендовал подключиться к вашему журналу IIS и получить оттуда свою статистику. Опять же, чтобы извлечь из этого реальную пользу для принятия решений, вам нужно установить на него хороший анализатор. Я рекомендую Splunk:http://www.splunk.com
</soapbox>
Комментарии:
1. Есть аргумент в пользу размещения JavaScript для этого типа анализа ближе к верхней части вашей страницы, поскольку он сможет регистрировать запросы на заброшенные страницы или очень быстрые запросы страниц — например, если я нажму на «Продукты» и до завершения загрузки страницы я найду ссылку на «Камеры» и нажму на нее — скрипт внизу страницы фактически не будет регистрировать мое посещение страницы «Продукты».
2. @Sohnee: Согласен. У Piwik также есть способ отслеживать просмотры путем встраивания изображения в 1 пиксель. Если производительность Javascript становится проблемой, это было бы несколько менее мощной альтернативой.
3. @xameeramir Да, но наша веб-команда сочла, что Google Analytics лучше, поэтому мы находимся в процессе переключения. Плюс мы не фанаты PHP.
Ответ №4:
Я хотел опубликовать обновленную версию ответа Шейна для тех, кто заинтересован. Некоторые вещи, которые следует учитывать:
-
Вы должны настроить атрибут action как сервис при оформлении своих методов, используя синтаксис, подобный следующему :
[ServiceFilter(typeof(PageViewAttribute))]
-
Насколько я могу судить, HttpRuntime.Кэш.В .NET Core нет функции Insert, поэтому я использовал простую реализацию IMemoryCache (возможно, вам потребуется добавить эту строку в свой startup.cs, чтобы использовать интерфейс):
Услуги.AddMemoryCache ();
-
Поскольку мы внедряем IMemoryCache в класс, который не является контроллером, нам нужно зарегистрировать наш атрибут как сервис в startup.cs, вот так:
Услуги.AddScoped<[PageViewAttribute]>(); — без скобок!
-
Любой объект, который вы возвращаете при создании CacheKey, будет присвоен параметру ‘value’ метода OnRemove.
Ниже приведен код.
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.
С уважением.