Опубликован: 25.09.2008 | Доступ: свободный | Студентов: 3223 / 516 | Оценка: 4.32 / 3.98 | Длительность: 18:50:00
ISBN: 978-5-94774-991-5
Лекция 4:

Основы Web-программирования с использованием ASP.NET

< Лекция 3 || Лекция 4: 12345 || Лекция 5 >

Сохранение объектов в состоянии вида

Как уже говорилось, состояние вида позволяет хранить, кроме простых типов, также и объекты. Для того чтобы элемент мог быть сохранен в состояние вида, он должен быть сперва преобразован в последовательность байтов. Такой процесс называется сериализацией. При создании нового класса по умолчанию его объекты не поддаются сериализации. При попытке поместить их в состояние вида появляется сообщение об ошибке. Для того чтобы создать объект, поддающийся сериализации, необходимо перед объявлением класса данного объекта разместить атрибут Serializable. Пример создания и сохранения класса в состоянии вида приведен ниже.

Здесь создается класс User, который может быть подвергнут сериализации, и создается объект этого класса, который затем сохраняется в состояние вида. Полный исходный текст приложения приведен ниже.

public partial class _Default : System.Web.UI.Page
{
  [Serializable]
  public class User
  {
    public string FirstName;
    public string LastName;
    public User(string firstName, string lastName)
    {
      FirstName = firstName;
      LastName = lastName;
    }
  }
  protected void Button1_Click(object sender, EventArgs e)
  {
    lbl_Result.Text = "Здравствуйте, "+tb_FirstName.Text+" "+
     tb_LastName.Text+"! Добро пожаловать в приложение ASP.NET";
    lbl_Result.ForeColor = Color.Red;
    //Сохраняем объект в ViewState
    User user = new User(tb_FirstName.Text, tb_LastName.Text);
    ViewState["CurrentUser"] = user;
    tb_FirstName.Text = "";
    tb_LastName.Text = "";
  }
  protected void btn_RestoreTextBox_Click(object sender, EventArgs e)
  {
    //Восстанавливаем значение объекта User
    User user;
    if (ViewState["CurrentUser"] != null)
    {
      user = (User)ViewState["CurrentUser"];
      tb_LastName.Text = user.LastName;
      tb_FirstName.Text = user.FirstName;
    }
  }
  protected void Page_Load(object sender, EventArgs e)
  {

  }
}

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

1. Данные ViewState сохраняются в скрытых полях страницы и передаются на сторону клиента. В этом можно убедиться, просмотрев исходный код такой страницы. Конечно, эти данные не хранятся в открытом виде, они представлены в формате Base64, однако их легко можно преобразовать в массив байт, представляющих символы ASCII. Для этого достаточно использовать функцию FromBase64String как показано в следующем примере:

Byte[] stringBytes=Convert.FromBase64String(ViewStateString);
String decodedString=System.Text.Encoding.ASCII.GetString(stringBytes);

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

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

2. ViewState не позволяет сохранять информацию, которая будет использоваться несколькими страницами. В этом случае лучше воспользоваться состоянием сеанса, наборами cookie либо строкой запроса.

Объект Session

Объект Session предназначен для реализации механизма состояния сеанса, используемого для хранения любого типа пользовательских данных, которые необходимо сохранять между запросами Web-страниц. Пользовательские данные при этом сохраняются в формате "имя-значение". Такой механизм, в частности, можно применять при создании Интернет-магазина, где покупатель перед покупкой складывает товары в виртуальную корзину, которая после завершения сеанса (перехода на другую страницу либо завершения работы с браузером) должна быть удалена. Для сохранения данных о выбранных товарах можно воспользоваться объектом Session.

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

Работа с состоянием сеанса практически аналогична работе с состоянием вида, за исключением того, что вместо ключевого слова ViewState применяется ключевое слово Session. Например, для сохранения объекта user в памяти сеанса необходимо выполнить следующий код:

Session["user"]=user;

Для восстановления сохраненного объекта user необходимо воспользоваться следующим кодом:

user=(User)Session["user"];

Состояние сеанса уничтожается в следующих случаях:

  1. если пользователь закрывает браузер;
  2. по истечении 20 минут с момента последней активности пользователя;
  3. при явном завершении сеанса из программного кода с помощью вызова метода Session.Abandon() ;

Объект Application

Объект Application во многом аналогичен объекту Session. Различие заключается только в том, что данные, хранящиеся в нем, глобальны для всего приложения. Это так называемое состояние приложения, доступ к данным которого может получить любой клиент.

Состояние приложения похоже на состояние сеанса, т. к. хранит информацию на сервере, позволяет сохранять объекты такого же типа и использует формат "имя-значение" для хранения данных.

С помощью состояния приложения можно создать счетчик и отслеживать информацию о том, сколько раз то или иное действие выполнялось всеми клиентами данного приложения.

Для этого можно воспользоваться следующим кодом:

protected void Page_Load(object sender, EventArgs e)
{
  int count;
  if (Application["HitsNumber"] == null)
  {
    Application["HitsNumber"] = 1;
    count = (int)Application["HitsNumber"];
    Label1.Text = count.ToString();
    return;
  }
  count = (int)Application["HitsNumber"];
  count++;
  Application["HitsNumber"]=count;
  Label1.Text = count.ToString();
}

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

В современной практике состояние приложения применяется крайне редко, т. к. не является эффективным. Так, предыдущий пример не гарантирует корректного отображения значения счетчика. Это происходит в том случае, если к приложению одновременно обращаются несколько клиентов. В этом случае каждый из них считывает одно и то же текущее значение состояния приложения HitsNumber, затем увеличивает его на единицу и вновь записывает в состояние приложения. Таким образом, все одновременные подключения, сколько бы их ни было, приводят к увеличению состояния приложения лишь на единицу. Для того чтобы избежать этой проблемы, возможно применение методов Lock() и Unlock(), которые позволяют одновременно получить доступ к коллекции только одному клиенту. Например, таким образом:

protected void Page_Load(object sender, EventArgs e)
{
  int count;
  Application.Lock();
  if (Application["HitsNumber"] == null)
  {
    Application["HitsNumber"] = 1;
    count = (int)Application["HitsNumber"];
    Label1.Text = count.ToString();
    return;
  }
  count = (int)Application["HitsNumber"];
  count++;
  Application["HitsNumber"]=count;
  Application.UnLock();
  Label1.Text = count.ToString();
}

Недостатком этого подхода является то, что все клиенты, которые запрашивают страницу, должны ожидать, пока коллекция Application не освободится. Это может привести к задержкам и значительно снизить производительность приложения. Вот почему рекомендуется использовать файл web.config для хранения констант уровня приложения, а часто используемую информацию лучше всего сохранять в кэше ASP.NET.

< Лекция 3 || Лекция 4: 12345 || Лекция 5 >