Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » .NET - ASP.NET »

Обсудить на форуме Обсудить на форуме

Новое в ASP.NET 2. Профили пользователей

Всегда приятно когда тебя помнят. Особенно когда помнят не только тебя, но и твои вкусы и предпочтения, понимаешь, что ты не просто один из многих. В такое место всегда хочется вернуться.

Однако это задачка не из легких. Представьте, что вы - продавец большого магазина, в котором ежедневно бывает не одна сотня покупателей, а что если вы - сайт, который ежедневно просматривают десятки тысяч посетителей? Нужно ведь не просто запомнить каждого, но еще и сохранить все это, пока он не соизволит зайти к вам еще раз, чтобы вы смогли продемонстрировать ему свою феноменальную память. А что если за это время его вкусы изменились и придется все запоминать заново, проблемы растут как снежный ком. Чтобы автоматизировать задачу потребуется не одна таблица в базе данных, множество запросов к ним, да еще и куча кода, чтобы связать все воедино. Ну и тестирование, тестирование, тестирование. Задумаешься, а стоит ли овчинка выделки? Однако не все так плохо, с выходом ASP.NET 2.0 все проблемы отходят на второй план, потому что теперь он содержит новую встроенную возможность - профиль (Profile) пользователя.

Профиль пользователя

Сервис персонализации (personalization) – это новая возможность в ASP.NET, которая применялась еще в продукте Site Server. Данный сервис предоставляет готовое решение для хранения персональных данных, непосредственно характеризующих пользователя сайта, так называемого профиля пользователя (Profile). Вот несколько примеров подобных данных – это имя, фамилия, адрес электронной почты пользователя, его временная зона, а также “корзина покупателя" для пользователя сайта электронной коммерции или информация о принадлежности посетителя сайта тем или иным группам пользователей. Сейчас такие параметры обычно хранят в сессии (Session), в файлах cookie, базах данных и так далее. Независимо от места их хранения, ASP.NET 1.x мало помогает в этом случае. Приходится своими силами разрабатывать и настраивать всю инфраструктуру под соответствующее хранилище. Также самостоятельно необходимо получать эти данные и сохранять их. Коллекция Session облегчает жизнь, но она ненадежна, а хранение ее в отдельном процессе или в базе данных приводило к высоким затратам ресурсов сервера и увеличению времени отклика приложения. В сущности, сервис персонализации - это коллекция, очень похожая на сессию по своей сути. Так же, как и сессия, профиль пользователя относится к одному конкретному посетителю сайта и обеспечивает хранение информации, относящейся непосредственно к нему. Однако есть и значительные отличия, выгодно характеризующие новый сервис, среди них:

  • Строго типизированный доступ к элементам коллекции: в отличие от коллекций типа Application, Session, Context, Cache, да и всех остальных коллекций, перешедших по наследству от ASP.NET 1.x, которые осуществляли доступ к значениям своих элементов по ключу, профиль пользователя – класс HttpProfile – использует строго типизированные именованные свойства, работать с которыми гораздо удобнее. Запоминать названия и типы свойств больше не нужно, теперь это удел Intellisense, который справляется с этим гораздо лучше. Другой полезный эффект - проверка типов на этапе компиляции. Например, следующий фрагмент кода демонстрирует два варианта получения даты последней активности пользователя:
    • старый, с использованием сессии:
      DateTime LastLogin = (DateTime)Session[“LastLogin"];
    • новый, с привлечением сервиса персонализации:
      DateTime LastLogin = Profile.LastLogin;
    Заметьте, что во втором случае приведение типов не потребовалось, поскольку дата уже хранится как дата, а не упаковывается в object.
  • Выборка данных из хранилища производится только при необходимости. В отличие от класса Session данные извлекаются не при каждом запросе страницы, занимая ресурсы сервера, а только тогда, когда в них действительно есть потребность.
  • Время хранения данных не ограничено. В отличие от всех остальных коллекций, время жизни сохраненных данных в профиле бесконечно и никак не зависит ни от приложения, ни от текущей сессии. Фактически данные будут храниться вечно, если хранилище достаточно надежно и Вы сами не решите их однажды удалить оттуда.
  • Данные могут храниться как для известных (зарегистрированных и прошедших аутентификацию в системе), так и для неизвестных (анонимных, то есть еще не зарегистрированных или просто не вошедших в систему) посетителей сайта.
  • Доступ к атрибутам профиля осуществляется так же просто, как и при работе с коллекцией Session. Это возможно благодаря новому свойству Profile, доступному во всех производных от System.Web.UI.Control классах приложения. Либо во всех классах приложения через контекст веб-приложения, используя следующий синтаксис: System.Web.HttpContext.Current.Profile или ((ProfileCommon)System.Web.HttpContext.Current.Profile).MessagesPosted если нужен доступ к собственным свойствам профиля. ProfileCommon - это специальный класс, автоматически создаваемый компилятором при включенном профиле и содержащий все пользовательские свойства, добавленные через web.config.
  • Хранилище для данных расширяемо и может быть любым. По-умолчанию в поставку ASP.NET 2.0 входит один провайдер для профиля пользователя – провайдер для Microsoft SQL Server. Но возможно и создание своего собственного провайдера данных. Для этого предлагается новая модель реализации провайдеров. Она подразумевает выделение из программного интерфейса хранилища уровня работы с данными. Так достигается возможность прозрачного доступа к любым данным, независимо от типа физического хранилища – это может быть база данных и файл на жестком диске или даже выделенный сервер данных. Подобная архитектура провайдера данных используется и в других сервисах ASP.NET 2.0. Позже мы рассмотрим пример создания собственного провайдера данных и увидим, насколько это просто. Провайдер данных может быть задан статически в файле конфигурации приложения или динамически назначен в режиме выполнения.

Давайте рассмотрим, как можно начать использовать профиль. Итак, профиль сохраняет данные о конкретном пользователе вашего сайта и позволяет затем эти получать. По умолчанию все эти данные будут сохраняться в таблицах базы данных SQL Server Express. Строка соединения по умолчанию называется "LocalSqlServer" и задана она в глобальном файле настроек machine.config. Вот как она выглядит:

            
<add name="LocalSqlServer" connectionString="data source=.\SQLEXpreSS; Integrated
          Security=SSPI; AttachDBFilename=|DataDirectory|aspnetdb.mdf; User Instance=true" providerName="System.Data.SqlClient" />
		

то есть база данных будет работать в режиме User Instance, название файла базы данных ASPNETDB.MDF и при первой попытке сохранения профиля база данных будет автоматически создана в подпапке App_Data корневой директории сайта.

Отлично, оказывается все уже настроено, все что нам остается сделать - это описать нужные нам поля профиля в файле конфигурации приложения web.config. Настроим профиль на хранение имени и фамилии пользователя, а также счетчика его посещений нашего сайта:

<configuration> 
 <system.web> 
  <anonymousIdentification enabled="true"/> 
  <profile> 
   <properties> 
    <add name="FirstName" allowAnonymous="true" /> 
    <add name="LastName" allowAnonymous="true" /> 
    <add name="Visits" allowAnonymous="true" type="System.Int32" defaultValue="1" /> 
   </properties> 
  </profile> 
 </system.web> 
</configuration> 

По умолчанию тип параметра профиля - это System.String, поэтому, для того, чтобы хранить количество посещений сайта как число, нам необходимо явно задать его тип. Также параметр может иметь значение по умолчанию (в нашем случае это 1). Если провайдер данных не обнаружит значения параметра в хранилище данных, то будет возвращено значение параметра по умолчанию.

После того как профиль настроен, использовать его очень просто. Приведенный ниже код отображает данные из профиля текущего пользователя и обновляет их при нажатии на кнопку. Заметьте, никакого дополнительного кода для сохранения этих сведений где-либо в базе данных или получения их оттуда писать не нужно, об этом позаботится инфраструктура ASP.NET.

<%@ Page Language="C#" %>
<html>
   <head>
    <script runat="server">
      protected override void OnLoad(EventArgs e)
      {
        if (!IsPostBack)
        {
          tbFirstName.Text = Profile.FirstName;
          tbLastName.Text = Profile.LastName;
                 lblVisits.Text = Profile.Visits.ToString();
        }
      }

      protected void Update(object s, EventArgs e)
      {
        Profile.FirstName = tbFirstName.Text;
        Profile.LastName = tbLastName.Text;
        Profile.Visits += 1;
      }
    </script>
  </head>
  <body>
        Имя: <asp:TextBox runat="server" ID="tbFirstName" /><br />
        Фамилия: <asp:TextBox runat="server" ID="tbLastName" /><br />
        Кол-во посещений: <asp:Label runat="server" ID="lblVisits" /><br />
        <asp:Button runat="server" ID="updateProfileButton"
           Text="Update profile"
           OnClick="Update" />
  </body >
</html> 

Расширение профиля пользователя

Профиль содержит следующие базовые параметры:

Название Тип Описание
UserName String Имя пользователя
IsAnonymous Boolean Имеет значение “Ложь", если это профиль зарегистрированного пользователя и “ Истина" в случае анонимного пользователя, имеет смысл только в том случае, если включен профиль для анонимных пользователей
IsDirty Boolean Показывает, есть ли в профиле измененные, но еще не сохраненные в хранилище данные
LastActivityDate DateTime Дата последней активности пользователя в системе (в данном случае это последнее сохранение или получение свойств профиля), в UTC
LastUpdatedDate DateTime Дата последнего сохранения профиля, в UTC

Для расширения класса Profile используется элемент <add /> раздела <properties> элемента <profile> файла конфигурации приложения - web.config. С помощью этого элемента мы можем добавлять новые свойства к классу Profile. При компиляции страницы ASP.NET заменит класс Profile, генерируемый по умолчанию, классом построенным на основании свойств, заданных в разделе <properties> элемента <profile>. Все это произойдет автоматически, без нашего участия. Поддержка новых свойств IntelliSense-ом в Visual Studio начинается с сохранения конфигурационного файла.

Наиболее простой вариант использования элемента <add /> - это определение нового свойства индивидуализации с единственным атрибутом - name:

 

<profile> 
    <properties> 
        <add name="Nickname" /> 
    </properties> 
</profile> 

В данном случае инфраструктура ASP.NET создаст свойство с названием Nickname, имеющее тип данных по умолчанию - String, недоступное для неаутентифицированных пользователей и использующее для работы с хранилищем данных провайдер по умолчанию (это провайдер для работы с базой данных SQL Server). Кстати, имена новых свойств возможно задавать и на русском языке, а вот пробелы в них не допускаются.

<profile> 
    <properties> 
        <add name="ИмяПользователя" /> 
    </properties>
</profile> 

Список атрибутов, доступных в теге <add />:

Элемент Тип Описание
allowAnonymous Boolean При установке в true позволяет неаутентифицированным пользователям хранить данные в системе индивидализации. При этом подразумевается, что для сайта включена возможность идентификации анонимных пользователей, то есть в конфигурационном файле присутствует элемент <anonymousIdentification enabled="true" />. Значением по умолчанию данного атрибута является false.
defaultValue String Значение свойства по умолчанию. Например, для сайта может быть задана тема по умолчанию.
name String Название свойства. Используется как ключ для доступа к значению свойства, а также появляется как название открытого свойства класса Profile. Является обязательным при добавлении нового свойства.
provider String Название провайдера, используемого системой индивидуализации для взаимодействия с хранилищем данных. Если не задано явно, то используется значение по умолчанию из файла machine.config.
readOnly Boolean Служит для указания того, что свойство является свойством только для чтения. Значение по умолчанию - false.
serializeAs String Определяет метод сериализации данных. Возможны следующие значения:
  • String: значение будет сериализовано как строка.
  • Xml: данные сериализуются в XML, необходимо учесть, что будут сериализованы только открытые (public) поля класса;
  • Binary: двоичная сериализация, наиболее «глубокий» метод - сериализации подвергаются все поля класса, однако он и наиболее «дорогой», с точки зрения потребляемых ресурсов. Тип параметра должен быть сериализуемым;
  • ProviderSpecific: формат данных на усмотрение провайдера данных. Позволяет поставщику данных самому определять формат хранения данных. Является значением по умолчанию.
type String Тип данных хранимого свойства. По умолчанию используется тип String, но можно задать и любой другой тип (для типа сериалиазации Binary можно задавать только сериализуемый тип, то есть тип, помеченный атрибутом Serializable, а для типа сериалиазации String класс должен иметь своего наследника класса TypeConverter). В последнем случае необходимо указать полное название класса, включая пространство имен.

Ниже приведен простейший вариант реализации собственного класса, который удовлетворяет всем условиям профиля и может быть сериализован всеми возможными способами:

using System;
using System.ComponentModel;
using System.Xml.Serialization;

[TypeConverter(typeof(AddressTypeConverter))]
[Serializable]   
public class Address  
{  
    string _country;
    string _city;
    string _street;
    int _building;
    int _room;

    [XmlAttribute]
    public string Country
    {
      get { return _country; }
      set { _country = value; }
    }
    [XmlAttribute]
    public string City
    {
      get { return _city; }
      set { _city = value; }
    }
    [XmlAttribute]
    public string Street
    {
      get { return _street; }
      set { _street = value; }
    }
    [XmlAttribute]
    public int Building
    {
      get { return _building; }
      set { _building = value; }
    }
    [XmlAttribute]
    public int Room
    {
      get { return _room; }
      set { _room = value; }
    }
}

Реализация класса - наследника TypeConverter, позволяющая сериализовать наш класс, как строку:

using System;
using System.ComponentModel;
using System.Globalization;

public class AddressTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context,
     Type sourceType)
     {
      if (sourceType == typeof(string))
      {
        return true;
      }
      return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context,
      CultureInfo culture, object value)
    {
      if (value is string)
      {
        string[] v = ((string)value).Split(new char[] { '|' });
        Address address = new Address();
        address.Country = v[0];
        address.City = v[1];
        address.Street = v[2];
        address.Building = Convert.ToInt32(v[3]);
        address.Room = Convert.ToInt32(v[4]);
        return address;
      }
      return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context,
      CultureInfo culture, object value, Type destinationType)
    {
      if (destinationType == typeof(string))
      {
        Address address = (Address)value;
        return address.Country
          + "|" + address.City
          + "|" + address.Street
          + "|" + address.Building
          + "|" + address.Room;
      }
      return base.ConvertTo(context, culture, value, destinationType);
    }
} 

Хранение данных Generic-типов

Для описания подобных данных как свойств профиля используется специальный синтаксис. Рассмотрим пример - в качестве свойства профиля пользователя нам нужно хранить свойство с названием Ints имеющее тип данных System.Collections.Generic.List<int>. В данном случае соответствующий параметр в файле Web.config должен выглядеть так:

        <add name="Ints" type="System.Collections.Generic.List`1[[System.Int32]]" /> 
    

То есть сначала указывается полный тип класса - коллекции, затем количество параметров с префиксом апостроф (‘1), а затем в квадратных скобках идет список типов, каждый из которых также обрамляется квадратными скобками. Для типа данных System.Collections.Generic.Dictionary<System.String, System.Double> запись в конфиге будет выглядеть как

        <add name="Registry" type="System.Collections.Generic.List`2[[System.String],[System.Double]]" /> 

Идентификация анонимных пользователей

Данный код будет сохранять настройки любого пользователя, даже "анонимного", то есть незарегистрированного или просто еще не выполнившего вход в систему. По умолчанию профиль сохраняется только для аутентифицированных пользователей. Для того, чтобы он начал работать и для анонимных пользователей необходимо включить модуль распознавания анонимных пользователей. За это отвечает раздел <anonymousIdentification /> файла настроек web.config. Также необходимо для каждого параметра профиля, который должен храниться и для анонимных пользователей, установить атрибут allowAnonymous в значение "true" (по умолчанию значение этого атрибута - ложь). Если этого не сделать, то при каждой попытке установить такое свойство для анонимного пользователя будет генерироваться исключение. Рекомендуется разумно подходить к данному вопросу и не перегружать профиль анонимного пользователя бесполезными для него свойствами.

Включение распознавания анонимных пользователй приводит к тому, чnо в цепочку обработки входящего запроса добавляется еще один модуль - AnonymousIdentificationModule. Работает он следующим образом - при поступлении запроса от анонимного пользователя модуль создает глобально уникальный идентификатор (System.Guid) и записывает его в постоянно хранимый файл cookie с именем по умолчанию .ASPXANONYMOUS. С этого момента этот Guid и будет временным именем пользователя. Поскольку файл cookie создается постоянный, то система сможет "узнавать" пользователя при каждом его последующем посещении сайта. Все параметры модуля настраиваемы и могут быть изменены в файле конфигурации, в разделе анонимной идентификации.

Зачем это нужно? Допустим вы создаете электронный магазин посещая который пользователь может сформировать корзину интересующих его товаров не регистрируясь на сайте и не проходя авторизации. Затем он смотрит во что ему обойдутся его покупки и, если сумма его устраивает, входит в систему и завершает оформление заказа. При этом он может отложить покупку на неделю или на месяц, все это время корзина будет аккуратно хранить все выбранные им в прошлый раз товары, несмотря на то что он даже не был зарегистрирован на сайте. Для"миграции" пользователя с анонимного профиля на профиль зарегистрированного пользователя в профиле предусмотрено специальное событие - MigrateAnonymous. Оно происходит в тот момент, когда анонимный пользователь выполняет вход на сайт. Это событие может быть обработано в файле Global.asax при помощи следующего кода:

void Profile_MigrateAnonymous(object sender, ProfileMigrateEventArgs e)
{
   // получаем профиль анонимного пользователя по его ID
   ProfileCommon anonymous = Profile.GetProfile(e.AnonymousID);
   // Переносим данные в профиль текущего зарегистр. пользователя
  //if( !isMigrated )
   //{
   Profile.FirstName = anonymous.FirstName;
   Profile.LastName = anonymous.LastName;
   Profile.SiteLook.MasterPage = anonymous.SiteLook.MasterPage;
   Profile.SiteLook.Theme = anonymous.SiteLook.Theme;
   //}
   // стираем cookie ".ASPXANONYMOUS" с анонимным идентификатором
   AnonymousIdentificationModule.ClearAnonymousIdentifier();
}

Особенно важно выполнить удаление cookie с идентификатором анонимного пользователя. В противном случае модуль будет вызывать это событие при каждом новом запросе пользователя к сайту.

Следует также учесть, что событие MigrateAnonymous вызывается каждый раз когда пользователь авторизуется в системе, даже если профиль пользователя уже был однажды мигрирован. Поэтому имеет смысл добавить в профиль еще один параметр "isMigrated" типа System.Boolean, который бы имел значением по умолчанию ложь, а после миграции выставлялся бы в истину. Таким образом миграцию следовало бы проводить только если этот параметр имеет значение по умолчанию (то есть профиль еще ни разу не был мигрирован).

Группирование параметров профиля

При большом количестве параметров допускается их объединение в логические подгруппы. Это делается с помощью элемента <group>, имеющего единственный атрибут name, который является обязательным и должен иметь значение, уникальное в рамках приложения. Рассмотрим другой пример задания профиля:

<profile>
 <properties>
  <add name="FirstName" allowAnonymous="true" />
  <add name="LastName" allowAnonymous="true" />
  <group name="SiteLook" >
   <add name="Theme" defaultValue="Orange" />
   <add name="MasterPage" defaultValue="Basic.master" />
  </group>
 </properties>
</profile>

Здесь параметры, имеющие отношение к внешнему виду сайта, объединены в одну группу с общим названием SiteLook. Количество групп не ограничено, однако вложение групп не допускается. Объединение параметров в группу добавляет дополнительный уровень и в коде, обращение к свойствам группы в нашем случае будет выглядеть так:

Profile.FirstName = "test";
Profile.SiteLook.MasterPage = "Extreme.master";
Profile.SiteLook.Theme = "Yellow";

Работа с профилем произвольного пользователя

До сих пор мы работали только с профилем текущего пользователя, однако в ряде случаев бывает необходимо получить профиль другого пользователя. Это с легкостью может быть выполнено при помощи метода GetProfile() класса HttpProfile, достаточно лишь передать ему имя пользователя, профиль которого мы бы хотели получить. Данный метод возвращает новый экземпляр класса HttpProfile, с которым можно работать так же, как и с профилем текущего пользователя. Возможно также и изменение свойств профиля, полученного таким образом. Однако, в этом случае, автоматического сохранения изменений не произойдет. Для того чтобы изменения вступили в силу, необходимо будет принудительно вызвать метод Save() изменяемого профиля. При использовании профиля текущего пользователя в веб-приложении не нужно вызывать этот метод для сохранения профиля, поскольку он вызывается автоматически модулем профиля при срабатывании события EndRequest.

ProfileCommon profile = Profile.GetProfile("Nisus"  );
profile.FirstName = "SeaEagle";
profile.Save(); 

Получить профили всех пользователей сайта также не составит большого труда:

public List<ProfileCommon> GetProfiles() 
{ 
  List<ProfileCommon> profiles = new List<ProfileCommon>(); 
  ProfileInfoCollection profilesInfos = ProfileManager.GetAllProfiles( 
    ProfileAuthenticationOption.All 
    ); 
  foreach (ProfileInfo profileInfo in profilesInfos) 
  { 
    profiles.Add(Profile.GetProfile(profileInfo.UserName)); 
  } 
  return profiles; 
}
        

Перечисление ProfileAuthenticationOption, определенное в пространстве имен System.Web.Profile включает три элемента:

  • All – все пользователи, независимо от их статуса;
  • Anonymous – анонимные пользователи;
  • Authenticated – зарегистрированные пользователи.

Доступ к профилю из внешних компонент

Возможно вам потребуется доступ к профилю пользователя из внешних компонент, например из слоя работы с данными. Если просто написать Profile, как мы это делали на странице aspx, то код не будет компилироваться, поскольку во внешнем приложении ASP.NET не будет создавать ни класс ProfileCommon, ни уж тем более свойство Profile. Тем не менее такая возможность есть – доступ к профилю можно получить через свойство Profile контекста запроса (HttpContext). Контекст - это объект, который содержит все сведения о текущем запросе, известные ASP.NET. Одно из новых свойств контекста в ASP.NET 2.0 - это свойство Profile, содержащее ссылку на профиль текущего пользователя.

System.Web.HttpContext context = System.Web.HttpContext.Current;
context.Profile["FirstName"] = "Adam";
context.Profile.Save(); 

Другим, более удобным для использования вариантом, является создание класса - наследника от класса ProfileBase. Добавим в папку App_Code новый класс, описывающий нужный нам профиль:
 

using System;
using System.Web.Profile;
using System.Collections.Generic;

public class CustomProfile : ProfileBase
{
  [SettingsAllowAnonymous(true)]
   public string FirstName
  {
    get { return base["FirstName"] as string; }
     set { base["FirstName"] = value; }
  }
 
  [SettingsAllowAnonymous(true)]
  public string LastName
  {
     get { return (string)base["LastName"]; }
     set { base["LastName"] = value; }
  }
}

Данный класс является наследником класса ProfileBase и лишь немного расширяет его, описывая нужные нам свойства. Всю остальныю черновую работу по общению с провайдером для получениия и сохранения значений наших свойств выполянет базовый класс. Чтобы указать инфраструктуре что в качестве базового класса для профиля следует использовать наш класс изменим описание профиля в файле конфигурации, плюс добавим новое свойство - телефон:

<profile inherits="CustomProfile" >
 <properties>
  <add name="Phone" allowAnonymous="true" serializeAs="ProviderSpecific" />
 </properties>
</profile> 

Теперь как и раньше мы сможем беспрепятственно получать доступ к свойствам профиля на стрницах нашего сайта:

Profile.FirstName = "John";
Profile.LastName = "Smith";
    

А если мы вынесем этот класс в отдельную сборку, то сможем использовать его в любом проекте используя явное приведение типов:

System.Web.HttpContext context = System.Web.HttpContext.Current;
string firstName = ((CustomProfile)context.Profile).FirstName; 

Минус данного подхода в том, что теряется преимущество гибкой настройки всех свойств профиля через изменение схемы в файле настроек (базовые свойства, защитые в код класса без перекомпиляции изменить уже не удастся), а плюсом является то, что теперь становится возможным добавление дополнительной логики к объекту профиля. Например мы сможем проверять, что имя пользователя состоит только из букв.

Управление профилями

Для управления профилями существует специальный класс, ProfileManager. В нем определен ряд статических методов, позволяющих производить разнообразные вспомогательные операции. Например, удаление неиспользуемых профилей. Удаление лишних профилей играет очень важную роль, поскольку при активной работе сайта количество хранимых профилей будет расти очень быстро, особенно если используются профили для анонимных профилей. Автоматически очистка хранилища данных от неактивных профилей не производится, вы должны реализовать ее самостоятельно. Например можно выполнять очистку при каждом старте приложения

void Application_Start(object sender, EventArgs e)
{
  ProfileManager.DeleteInactiveProfiles(
    ProfileAuthenticationOption.Anonymous,
    DateTime.Now.AddMonths(-2)//Удалим все профили старше 2-х месяцев
  );
}

Также данный класс предоставляет ряд методов для получения отчетов, например метод GetAllProfiles, позволяющий получать список всех хранящихся профилей постранично.

Настройка хранилища данных

Microsoft SQL Server

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

Чтобы создать новое хранилище нам потребуется создать базу данных. Делается это очень просто с помощью утилиты aspnet_regsql, которая поставляется в составе .NET Framework 2.0 и, соответственно, находится в папке "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\". Утилита работает в двух режимах – в режиме мастера и в режиме командной строки. Чтобы использовать ее в графическом режиме мастера достаточно просто запустить ее на выполнение или вызвать с параметром “-W". Режим мастера весьма беден и выполняет только примитивные общие функции – выполняет в базе данных скрипты для создания или удаления всех новых возможностей, предоставляемых инфраструктурой ASP.NET (среди них Membership, Role manager, Profile, Personalization, и т.д.). Режим командной строки позволяет управлять поддержкой всех нужных Вам возможностей. Воспользуемся утилитой в режиме графического интерфейса для создания новой базы данных и установки в нее всех новых возможностей, предоставляемых ASP.NET. Данная утилита позволяет работать как с новой версией - SQL Server 2005, так и с предыдущей версией 2000, также поддерживается SQL Server Express Edition (SSE).

Первые два окна мастера оставляем без изменений, а в третьем нам предлагают указать название инстанса SQL Server-а. Далее оставляем тип аутентификации в режиме по умолчанию – Windows и наибиваем в поле выбора базы данных имя желаемой новой базы данных – "MyOwnAspnetDB".

Далее нажимаем два раза кнопку Next и, при небольшой доле везения, получаем сообщение о том, что скрипты были успешно инсталлированы. Остается только скопировать новую базу данных из папки Data сервера (для SSE ее расположение можно узнать в реестре – ветка HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\SQLEXpreSS\Setup) в папку App_Data нужного вам проекта, чтобы начать ее использовать в режиме UserInstanse при использовании SSE или просто указать корректную строку подключения в случае использования SQL Server полных редакций.

Microsoft Access

Чтобы использовать Access в качестве хранилища данных придется скачать Sample Access Provider Starter Kit с сайта http://msdn.microsoft.com/vstudio/downloads/starterkits/. Затем его нужно будет скомпилировать при помощи студии или C# Developer Express, получив в итоге ASP.NET Access Providers.dll и файл базы данных ASPNetDB.mdb, который следует положить в подпаку App_Data своего сайта, а dll-ку провайдера соотвественно в подпапку bin корневой директории сайта ( если у вас нет такой папки создайте ее).

Собственный провайдер данных

Возможно также использование любого другого хранилища данных, однако в этом случае придется самостоятельно его реализовать. Задача эта в большинстве случаев будет несложной, но в данной статье она не рассматривается.

Настройка сервиса на работу с определенным хранилищем данных.

Изначально сервис уже настроен на работу с SSE в режиме UserInstance. Настройки эти заданы в глобальном файле конфигурации machine.config (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config) и могут быть переопределены в файле настроек сайта web.config. Вот как выглядят соответствующие настройки, заданные по умолчанию:

<connectionStrings>
  <add name="LocalSqlServer" connectionString="data source=.\SQLEXpreSS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
  <profile>
    <providers>
      <add name="AspNetSqlProfileProvider" connectionStringName="LocalSqlServer" applicationName="/" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
  </profile>
</system.web>
            
То есть сервис настроен на использование SSE провайдера, и считается, что база данных должна называться "aspnetdb.mdf" и расположена она должна быть в папке данных ASP.NET (это подпапка App_Data корневой директории сайта). Если провайдер обнаруживает, что подобная база данных не создана, то он создает ее и все необходимые для работы объекты при первом обращении.

 

Использование режима User Instance чрезвычайно удобно при разработке и тестировании приложения, однако едва ли применимо при релизной работе сайта, поэтому будьте готовы к тому, что при выставлении приложения на боевой сервер придется аттачить базу данных к инстансу SQL Server и модификации строки соединения.

Итак, чтобы приложение смогло использовать сервис профиля с провайдером данных SSE можно ничего не менять в файле web.config, однако лучше продублировать настройки из глобального файла конфигурации, соответственно Web.config должен будет выглядеть примерно вот так:

 

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <connectionStrings>
	<remove name="LocalSqlServer"/>
	<add name="LocalSqlServer" connectionString="Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=|DataDirectory|aspnetdb.mdf"/>
  </connectionStrings>
  <system.web>
	<profile defaultProvider="AspNetSqlProfileProvider">
	  <properties />
	</profile>
  </system.web>
</configuration>
        

В случае использования Sample Access Provider Starter Kit файл настроек несколько усложнится, за счет необходимости описания нового провайдера:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
	<connectionStrings>
		<add name="AccessFileName" connectionString="~/App_Data/ASPNetDB.mdb" providerName="System.Data.OleDb"/>
	</connectionStrings>
	<system.web>
		<profile enabled="true" defaultProvider="AccessProfileProvider">
			<providers>
				<add name="AccessProfileProvider" type="Samples.AccessProviders.AccessProfileProvider, ASP.NET Access Providers" connectionStringName="AccessFileName" applicationName="SampleSite" description="Stores and retrieves profile data from an ASP.NET_Access_Providers database."/>
			</providers>
			<properties />
		</profile>
		<anonymousIdentification enabled="true" cookieName=".ASPXANONYMOUS" cookieTimeout="100000" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="None" domain=""/>
		<compilation debug="true"/>
	</system.web>
</configuration>

Где “ASP.NET Access Providers" в строке type="Samples.AccessProviders.AccessProfileProvider, ASP.NET Access Providers" – это название сборки (ASP.NET Access Providers.dll у вас может иметь другое название), которая получается в результате компиляции проекта Sample Access Provider Starter Kit и которую следует положить в подпапку bin корневой папки вашего сайта. Также нужно не забыть скопировать файл ASPNetDB.mdb из папки bin проекта провайдера Access в папку App_Data вашего проекта.

Заключение

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


Может пригодится:


Автор: Nisus
Прочитано: 8767
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (1)

Прислал: max
...Собственный провайдер данных Возможно также использование любого другого хранилища данных, однако в этом случае придется самостоятельно его реализовать. Задача эта в большинстве случаев будет несложной, но в данной статье она не рассматривается..

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру