Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

В двадцатом выпуске рассылки '.Net Собеседник' вы можете прочесть обзор новых компонент и продуктов, разработанных с использованием платформы .Net, получить ссылки на новые технические статьи из Microsoft Knowledge Base,


Информационный Канал Subscribe.Ru

.Net Собеседник #20

Содержание
  1. От автора
  2. Обзор новостей
  3. Статья выпуска - Отслеживаем пользователя на страницах сайта с помощью ASP.Net (окончание)
  4. Время кода - ColorListBox на C#
  5. Форумы .Net на www.sql.ru

От автора

Здравствуйте, коллеги!


Пришёл август - настала пора и моего отпуска, о чём вам с большим удовольствием и сообщаю. Следующий выпуск рассылки ждите в сентябре.

Желаю приятного чтения.

{К содержанию}

Обзор новостей

  1. Доступен SQL Server ("Yukon") Beta 2
    SQL Server ("Yukon") Beta 2 стал доступен для скачивания подписчикам MSDN. Если вы подписчик MSDN, то можете скачать образ диска, однако помните, что это около 600 MB, то есть может быть стоит подождать CD, который будет рассылаться подписчикам.
  2. Вышла VG.net 2.1: векторная графика в Visual Studio .NET
    Вышла новая версия 2.1 графического движка VG.net. Новая версия поддерживает способность построения и отображения анимированной векторной графики в Visual Studio .NET, a также отображения её через Internet Explorer на веб-страницах. Пример для просмотра доступен здесь .
  3. Netcoole объявила о выходе VB6TOCS v2.2
    VB6TOCS - инструмент, выполняющий конвертацию проектов Visual Basic 6.0 в проекты Visual C# .NET. VB6TOCS создаёт новый проект, конвертирует каждый файл из оригинального проекта (.vbp) в новый проект(.csproj), и генерирует отчёт, описывающий проделанную работу. В этой версии исправлено много ошибок.
  4. JetBrains объявила о выходе ReSharper 1.0: плагина к Visual Studio
    JetBrains объявила о выходе финальной версии 1.0 своего продукта ReSharper. ReSharper является добавлением к Microsoft Visual Studio .NET, которое привносит в кодирование элемент интеллектуальной помощи, подсветку ошибок в реальном времени и функции рефакторинга.
  5. ComponentOne® выпустила ComponentOne Studio Enterprise™ 2004 v3
    ComponentOne today выпустила ComponentOne Studio Enterprise 2004 v3. Этот релиз включает Flash для .NET и Preview для .NET, меню и панели инструмента для .NET, компоненты отчётов для .NET, Chart для .NET, WebChart для ASP.NET и т.п. Всего доступно более 110 комопонент.
  6. Вышел компонент PortSight Meta Tree 2.0
    Вышел PortSight Meta Tree 2.0, компонет для .NET, упрощающий организацию реляционных и неструктурированных данных в иерархические структуры.
BUGs, FIXes and HOW TO's -
  1. The TextChanged event of a TextBox control may not fire if the AutoComplete feature is enabled in Internet Explorer
  2. Object properties in the PropertyDescriptorCollection class do not update as you expect

{К содержанию}

Статья выпуска

Отслеживаем пользователя на страницах сайта с помощью ASP.Net (окончание) 

ЯЗЫК: C#, ASP.Net
Автор статьи: Vikram http://www.codeproject.com/
Код к статье : Демонстрационный проект


Определяем события для HttpModule

Нам необходимо зарегистрировать три события для отслеживания страниц в нашем HttpModule. Регистрируем события:

public void Init(HttpApplication app)
{
app.BeginRequest += (new EventHandler(this.OnBeginRequest));
app.PreRequestHandlerExecute +=
(new EventHandler(this.OnPreRequestHandlerExecute));
if (app.Modules["Session"] != null)
{
SessionStateModule session = (SessionStateModule)
app.Modules["Session"];
app.AcquireRequestState +=
(new EventHandler(this.OnAcquireRequestState));
session.Start += (new EventHandler(this.OnSessionStart));
}
}

Событие AcquireRequestState – это событие происходит тогда, когда ASP.NET необходимо проассоциировать текущее сессионное состояние с текущим запросом. Это идеальное место для создания объекта-кеша с помощью callback-функции. Время жизни этой функции устанавливается равным времени жизни сессии.

private void OnAcquireRequestState(Object source, EventArgs ea)
{
HttpApplication app = (HttpApplication)source;
HttpContext ctx = (HttpContext) app.Context;
string key = ctx.Session.SessionID;
CacheItemRemovedCallback onCacheRemove = null;
try
{
ctx.Cache.Remove(key);
onCacheRemove = new CacheItemRemovedCallback (this.CacheRemoveCallback);
ctx.Cache.Add(key,ctx.Session.SessionID,null, DateTime.Now.AddMinutes(ctx.Session.Timeout),TimeSpan.Zero, CacheItemPriority.Normal,onCacheRemove);
}
catch(Exception exception) {
string message = exception.Message;
// Publish Exception
}
}

Метод CacheRemoveCallBack вызывает метод PageTrackerUtil.TrackSessionEnd для публикации статистики при окончании сессии. Метод CacheCallBackMethod синхронизирован таким образом, чтобы быть выполненным во время окончания сессии.

private void CacheRemoveCallback(string key, Object source, CacheItemRemovedReason reason)

{
if (reason == CacheItemRemovedReason.Expired)
{
PageTrackerUtil.TrackSessionEnd(key);
}
}

События модуля сессии – используем SessionStateModule для регистрации события OnSessionStart. Используем это событие для сигнализации того, что кто-то зашел на сайт.

private void OnSessionStart(Object source, EventArgs ea)
{
PageTrackerUtil.TrackSessionStart(HttpContext.Current);
}

PreRequestHandlerExecute - это событие происходит перед тем, как ASP.NET начинает обработку страницы. Используйте это событие для отслеживания индивидуальных страниц.

private void OnPreRequestHandlerExecute(object source, EventArgs e)
{
PageTrackerUtil.TrackSessionPages(((HttpApplication)source).Context);
}

Методы отслеживания страниц

В HttpModule мы задействовали три метода: TrackSessionStart, TrackSessionPages и TrackSessionEnd класса PageTrackerUtil для отслеживания страниц. Поскольку у нас нет доступа к объекту Session, поскольку он уже уничтожен ASP.NET, то мы используем свою собственную маленькую и простую статическую хэш-таблицу для хранения объектов отслеживания страниц.
TrackSessionStart

private static void UpdateSessionConst(string key, PageTracker tracker) {

if (SessionConst.Session[key] == null)
{
SessionConst.Session.Add(key,tracker); }
else
{
SessionConst.Session.Remove(key);
SessionConst.Session.Add(key,tracker);
}
}
public static void TrackSessionStart(HttpContext ctx)
{
string key = ctx.Session.SessionID;
string siteTracking = ConfigurationSettings.AppSettings["SiteTracking"];
string ip = ctx.Request.UserHostAddress.ToString();
if (siteTracking == null || siteTracking.Length == 0) return;
if (siteTracking.ToLower() != "none" && ValidTracking(ctx))
{
PageTracker tracker = new PageTracker(ctx);
UpdateSessionConst(key,tracker);
EADUtility.SendMail(tracker.SessionUserHostAddress, CreateTrackerMessageBody(tracker));
}
}

При старте сессии мы создаем объект класса PageTracker и сохраняем его в нашей статической хэш-таблице SessionConst.Session.

using System;
using System.Collections;

namespace EAD.Constant
{
public class SessionConst
{
public static Hashtable Session = new Hashtable();
public static Hashtable Page = new Hashtable();
}
}

TrackSessionPages

public static void TrackSessionPages(HttpContext ctx)
{
string siteTracking = ConfigurationSettings.AppSettings["SiteTracking"];
if (siteTracking == null || siteTracking.Length == 0 || siteTracking.ToLower() == "none") return;
if (ctx.Session == null) return;
string key = ctx.Session.SessionID;
siteTracking = siteTracking.ToLower();
if (siteTracking == "full" || siteTracking == "partial")
{
if (SessionConst.Session[key] != null)
{
PageTracker tracker = (PageTracker) SessionConst.Session[key];
if (tracker != null)
{
string relativeFilePath = ctx.Request.Url.AbsolutePath.Remove(0, ctx.Request.ApplicationPath.Length).ToLower();
// Remove things after ? mark.
int pos = relativeFilePath.IndexOf("?");
if (pos > 0)
{
relativeFilePath = relativeFilePath.Substring(0,pos);
}
if (siteTracking == "full")
{
tracker.AddPage(relativeFilePath);
}
else if (PageVisit(relativeFilePath))
{
tracker.AddPage(relativeFilePath);
}
UpdateSessionConst(key,tracker);
}
}
}

При отслеживании страницы, мы получаем класс PageTracker из статической хэш-таблицы и сохраняем его в похожей статической хэш-таблице SessionConst.Session, после добавления информации уровня страницы.
TrackSessionEnd

public static void TrackSessionEnd(string key)
{
string siteTracking = ConfigurationSettings.AppSettings["SiteTracking"];
if (siteTracking == null || siteTracking.Length == 0) return;
if (siteTracking.ToLower() != "none")
{
if (SessionConst.Session[key] != null)
{
PageTracker tracker = (PageTracker) SessionConst.Session[key];
SessionConst.Session.Remove(key);
SessionConst.Page.Remove(key);
if (tracker != null)
{
EADUtility.SendMail(tracker.SessionUserHostAddress+"-End",
CreateTrackerMessageBody(tracker)+
CreateTrackerPageListing(tracker)); }
}
}
}

Класс Page Tracker

До сих пор мы использовали администранивные процедура для выполнения отслеживания на уровне страницы. Актуальная информация уровня страницы хранится в классе PageTracker.
Инициализация параметров выполняется в конструкторе класса PageTracker.

public PageTracker(HttpContext ctx)
{
string KEY = ctx.Session.SessionID;
pages = new ArrayList();
expires = DateTime.Now.AddYears(1);
sessionReferrer = (ctx.Request.UrlReferrer == null) ? string.Empty : ctx.Request.UrlReferrer.ToString();
sessionURL = (ctx.Request.Url == null) ? string.Empty : ctx.Request.Url.ToString();
if (SessionConst.Page[KEY] == null)
{
visitCount = 1;
originalReferrer = sessionReferrer;
originalURL = sessionURL;
SessionConst.Page.Add(KEY,new PageHashData(visitCount, sessionReferrer,sessionURL));
}
else
{
PageHashData pageHashData = (PageHashData) SessionConst.Page[KEY];
pageHashData.PageCount++;
SessionConst.Page.Remove(KEY);
SessionConst.Page.Add(KEY,pageHashData);
visitCount = ((PageHashData)SessionConst.Page[KEY]).PageCount;
originalReferrer = ((PageHashData)SessionConst.Page[KEY]).Referrer;
originalURL = ((PageHashData)SessionConst.Page[KEY]).Url;
}
userHostAddress = ctx.Request.UserHostAddress.ToString();
userAgent = ctx.Request.UserAgent.ToString();
browser = ctx.Request.Browser.Browser;
crawler = ctx.Request.Browser.Crawler.ToString();
}

Метод AddPage вызывается из метода TrackSessionPages.

public void AddPage(string pageName)
{
PageData pti = new PageData();
pti.PageName = pageName;
pti.Time = DateTime.Now;
pages.Add(pti);
}

Благодаря использованию классов PageHashData и PagaData,которые хранятся в хэш-таблице SessionConst, устранена необходимость в использование куки.

using System;
namespace EAD.Utility
{
[Serializable]
public class PageHashData
{
private string referrer, url;
private int pageCount;
public PageHashData(int pageCount, string referrer, string url)
{
this.pageCount = pageCount;
this.referrer = referrer;
this.url = url;
}
public int PageCount { get { return pageCount;}
set{pageCount = value;} }
public string Referrer{ get { return referrer;} }
public string Url{ get { return url;} }
}
}

using System;
namespace EAD.Utility
{
[Serializable]
public class PageData
{
public string PageName;
public DateTime Time;
}
}

Известные проблемы

До сих пор не удается установить сколько времени пользователь проводит на данной конкретной странице, в том случае, если он не переходит на другие страницы поскольку статистика собирается только при переключение пользователя на другую страницу.

Результаты

Пример отслеживания страниц подобен тому, который приведен в статье Wayne'а.

Page Tracking Information
UserHostAddress 127.0.0.1 Durham North Carolina United States
Date 6/26/2004 3:00:05 PM
UserAgent Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)
Browser IE
Crawler False
URL http://localhost/PageTracking/index.aspx?IPCity=Durham&IPRegion=North Carolina&IPCountry=United States
Referer -
Visits 1
Orig Referer -
Orig URL http://localhost/PageTracking/index.aspx?IPCity=Durham&IPRegion=North Carolina&IPCountry=United States

Пример отсчета в случае окончания сессии. В этом случае вы получаете детальную статистику о навигации пользователя по сайту:
UserHostAddress 127.0.0.1 Durham North Carolina United States
Date 6/26/2004 3:00:05 PM
UserAgent Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)
Browser IE
Crawler False
URL http://localhost/PageTracking/index.aspx?IPCity=Durham&IPRegion=North Carolina&IPCountry=United States
Referer -
Visits 1
Orig Referer -
Orig URL http://localhost/PageTracking/index.aspx?IPCity=Durham&IPRegion=North Carolina&IPCountry=United States
Visited Pages Count: 7
Visited Pages Elapsed Time
/index.aspx 00:00:03
/index.aspx 00:00:02
/webform2.aspx 00:00:01
/webform2.aspx 00:00:00
/webform3.aspx 00:00:01
/webform2.aspx 00:00:03

(окончание, начало в предыдущем, 19 номере)

{К содержанию}

Время кода

ColorListBox на C#

ЯЗЫК: C#
АВТОР: Sanjay Ahuja, http://www.codeproject.com/
Код к статье : Демонстрационный проект

ПЕРЕВОД: Чужа В.Ф ака hDrummer

Вступление

В этой статье мы рассмотрим, каким образом можно написать свой собственный элемент управления ListBox, который умеет сам себя отрисовывать. Обычно Windows берёт на себя задачу отрисовки элементов ListBox. Однако можно использовать свойство DrawMode и обрабатывать события MeasureItem и DrawItem для самостоятельной отрисовки этих элементов. Использовать такой компонент можно для отображения в ListBox изображений, текста разного цвета и размера и т.д.

Описание

Начнём с создания приложения Windows. Добавим ListBox на форму и установим его свойство DrawMode в OwnerDrawVariable. Или можно поступить иначе – добавить следующую строку кода в функцию InitializeComponent нашей формы -

//lstColor это компонент ListBox
this.lstColor.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;

Теперь добавим пару строк ниже вышеуказанной строки:

//говорим windows о том, что мы сами хотим рисовать элементы в ListBox
this.lstColor.DrawItem += new DrawItemEventHandler(this.DrawItemHandler);

// говорим windows о том, что мы сами хотим задавать размеры элементов
this.lstColor.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.MeasureItemHandler);

Теперь Windows будет извещать нас о событиях DrawItem и MeasureItem для каждого элемента, добавленного в ListBox.
Теперь добавим обработчики этих событий:

private void DrawItemHandler(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
e.DrawFocusRectangle();
e.Graphics.DrawString(data[e.Index], new Font(FontFamily.GenericSansSerif, 14, FontStyle.Bold), new SolidBrush(color[e.Index]), e.Bounds);
}

private void MeasureItemHandler(object sender, MeasureItemEventArgs e)
{
e.ItemHeight= 22;
}

В вышеприведенном коде data – массив, содержащий элементы, которые будут вставлены, а color – массив объектов класса Color.

Вот и всё.


{К содержанию}

Форумы .Net на SQL.RU - вопросы оставшиеся без ответа

Почему не апдейтится датасет?
Функции Date(),Time() и т.д. не зависят от региональных настроек.
DataGrid method invocation


На этом двадцатый выпуск .Net Собеседника закончен.
До следующего номера.



Чужа Виталий Ф. aka hDrummer,
hdrummer@sql.ru - жду ваши предложения, вопросы и замечания.


Рассылки Subscribe.Ru
.Net Собеседник - Новости мира Net, C#, ASP.Net

http://subscribe.ru/
http://subscribe.ru/feedback/
Адрес подписки
Отписаться

В избранное