Современные веб-технологии

Разработка на ASP.NET. Жизненный цикл страницы, пользовательский интерфейс

Разбить на страницы
Показывать лекцию целиком

Презентацию к данной лекции Вы можете скачать здесь.

6.1. Описание .NET Framework

Платформа .NET Framework – это интегрированный компонент Windows, который поддерживает создание и выполнение нового поколения приложений и Веб-служб XML [1].

Двумя основными компонентами платформы .NET Framework являются общеязыковая среда выполнения (CLR) и библиотека классов .NET Framework. Основой платформы .NET Framework является среда CLR. Среду выполнения можно считать агентом, который управляет кодом во время выполнения и предоставляет основные службы, такие, как управление памятью, управление потоками и удаленное взаимодействие. При этом накладываются условия строгой типизации и другие виды проверки точности кода, обеспечивающие безопасность и надежность. Фактически основной задачей среды выполнения является управление кодом. Код, который обращается к среде выполнения, называют управляемым кодом, иначе код называется неуправляемым. Другой основной компонент платформы .NET Framework – библиотека классов, представляет полную объектно-ориентированную коллекцию типов, которые применяются для разработки приложений, начиная от обычных, запускаемых из командной строки или с графическим интерфейсом пользователя, и заканчивая приложениями, использующими последние технологические возможности ASP.NET, такие как Web Forms и Веб-службы XML.

Платформа .NET Framework может размещаться неуправляемыми компонентами, которые загружают среду CLR в собственные процессы и запускают выполнение управляемого кода, создавая, таким образом, программную среду, позволяющую использовать средства как управляемого, так и неуправляемого выполнения. Платформа .NET Framework не только предоставляет несколько базовых сред выполнения, но также поддерживает разработку базовых сред выполнения независимыми производителями.

На рис. 6.1 приведена общая архитектура .NET Framework в проекции на версии этой платформы [2].

(рис 6.1) Общая архитектура .NET Framework

6.1.1. Возможности среды CLR

Среда CLR управляет памятью, выполнением потоков, выполнением кода, проверкой безопасности кода, компиляцией и другими системными службами [3]. Эти средства являются внутренними для управляемого кода, который выполняется в среде CLR.

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

Среда выполнения обеспечивает управление доступом для кода. Например, пользователи могут доверить исполняемому приложению, внедренному в веб-страницу, воспроизведение анимации на экране или звукозаписи, не позволяя ему при этом получить доступ к личным данным, файловой системе или сети. Таким образом, средства безопасности CLR предоставляют подлинному развернутому в Интернете программному обеспечению исключительно богатые функции.

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

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

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

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

И наконец, среда выполнения может размещаться в высокопроизводительных серверных приложениях, таких как Microsoft SQL Server и Internet Information Services (IIS). Такая инфраструктура позволяет использовать управляемый код для написания собственной логики программ, пользуясь при этом высочайшей производительностью лучших производственных серверов, которые поддерживают размещение среды выполнения.

6.1.2. Библиотека классов платформы .NET Framework

Над уровнем CLR находится набор базовых классов платформы, а над ним расположены слой классов данных и XML, а также слой классов для создания Веб-служб (Web Services), Веб- и Windows-приложений (Web Forms и Windows Forms). Собранные воедино, эти классы известны под общим названием FCL (Framework Class Library) (рис. 6.2). Эта библиотека открывает доступ к системным функциям, включая и те, что прежде были доступны только через API Windows, а также к прикладным функциям для Веб-разработки ( ASP.NET ), для доступа к данным (ADO.NET), обеспечения безопасности и удаленного управления. Имея в своем составе более 4000 классов, библиотека FCL способствует быстрой разработке настольных, клиент-серверных и других приложений и Веб-служб [4].

(рис 6.2) Библиотека классов платформы .NET Framework

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

Над этим уровнем находится уровень классов, которые расширяют базовые классы с целью обеспечения управления данными и XML. Классы данных позволяют реализовать управление информацией, хранящейся в серверных базах данных. В число этих классов входят классы SQL, дающие программисту возможность обращаться к долговременным хранилищам данных через стандартный интерфейс SQL. Кроме того, набор классов, называемый ADO.NET, позволяет оперировать постоянными данными. Платформа .NET Framework поддерживает также целый ряд классов, позволяющих манипулировать XML-данными и выполнять поиск и преобразования XML.

Базовые классы, классы данных и XML расширяются классами, предназначенными для построения приложений на основе трех различных технологий: (Web Forms, Веб-формы) и Windows Forms (Windows-формы). Веб-службы включают в себя ряд классов, поддерживающих разработку облегченных распределяемых компонентов, которые могут работать даже с брандмауэрами и программами трансляции сетевых адресов (NAT). Поскольку Веб-службы применяют в качестве базовых протоколов связи стандартные протоколы HTTP и SOAP, эти компоненты поддерживают в киберпространстве подход "plug-and-play".

Инструментальные средства Web Forms и Windows Forms позволяют применять технику Rapid Application Development (RAD, быстрая разработка приложений) для построения Веб- и Windows-приложений. Эта техника сводится к перетаскиванию элементов управления с панели инструментов на форму, двойному щелчку по элементу и написанию кода, обрабатывающего события, связанные с этим элементом.

В общем, FCL можно использовать для разработки следующих типов приложений и служб:

  • консольные приложения;
  • приложения с графическим интерфейсом пользователя Windows (Windows Forms);
  • приложения ASP.NET ;
  • Веб-службы;
  • службы Windows.
  • Например, классы Windows Forms представляют собой полный набор типов, существенно упрощающих разработку графических интерфейсов пользователя Windows. При написании приложения форм ASP.NET можно использовать классы Web Forms.

    6.1.3. Развитие платформы .NET

    Версия .NET Framework 3 является ничем иным как: .NET Framework 2.0 + 4 новые подсистемы [5]:

  • Windows Presentation Foundation (WPF) – новая подсистема интерфейса пользователя и программный интерфейс на основе XML и векторной графики [6].
  • Windows Workflow Foundation (WF) – новая идеология программирования, предлагаемая компанией Microsoft, основанная на бизнес-сущностях и потоках [7].
  • Windows Communication Foundation (WCF) – сервис-ориентированная система обмена сообщениями, которая позволяет программам взаимодействовать локально или удаленно подобно веб-сервисам [8].
  • Windows CardSpace (WCS) – это способ безопасной идентификации пользователей при перемещении между ресурсами Интернета без необходимости повторного ввода имен и паролей [9].
  • .NET Framework 3.5 предоставляет новые возможности технологий из версий 2.0 и 3.0 и дополнительные технологии в виде новых сборок. В .NET Framework 3.5 впервые представлены следующие технологии:

  • LINQ;
  • новые компиляторы для C#, Visual Basic, C++ и J#;
  • ASP.NET AJAX.
  • Пакет обновления 1 (SP1) для .NET Framework 3.5 содержит обновления нескольких сборок, поставляемых с .NET Framework 3.5 [10]. Обновления включают изменения, не затрагивающие связанные компоненты, а также дополнительные функциональные возможности технологий, вошедших в состав .NET Framework 3.5. В .NET Framework 3.5 с пакетом обновления 1 (SP1) входят следующие технологии:

  • платформа динамических данных ASP.NET ;
  • ADO.NET Entity Framework;
  • поддержка поставщика данных SQL Server 2008;
  • поддержка .NET Framework Client Profile.
  • 6.1.4. Ключевые термины

    Платформа .NET Framework, Среда CLR, Библиотека классов платформы .NET Framework.

    6.2. Обзор технологии ASP.NET

    ASP.NET – это платформа для создания Веб-приложений и Веб-сервисов, работающих под управлением IIS [11]. Сегодня существуют другие технологии, позволяющие создавать Веб-приложения. К ним, прежде всего, относятся популярные сегодня языки PHP и PERL, технологии JSP, CSP, более старая технология CGI и т.д. Однако, ASP.NET отличается от них высокой степенью интеграции с серверными продуктами, а также с инструментами Microsoft для разработки, доступа к данным и обеспечения безопасности. Кроме того, использование ASP.NET позволяет разрабатывать Веб- и Windows приложения, используя очень похожие технологические цепочки, одинаковые языки программирования, технологии доступа к данным и т.д. Более того, базовые языки программирования, с помощью которых сегодня возможна разработка Веб-приложений являются полностью объектно-ориентированными, что делает разработку исполнимой части, а также ее модификацию, обслуживание, отладку и повторное использование гораздо более простым занятием, чем в других технологиях.

    6.2.1. Жизненный цикл Веб-страниц ASP.NET

    При выполнении страницы ASP.NET осуществляется ее жизненный цикл, во время которого исполняется ряд шагов обработки, такие как: инициализация, определение элементов управления, восстановление и поддержание рабочего состояния, выполнение кода обработчика событий, а также отрисовка. Знание жизненного цикла страницы необходимо, чтобы иметь возможность записывать код в нужный шаг жизненного цикла с нужным результатом. Кроме этого, при создании собственных элементов управления необходимо ознакомиться с жизненным циклом страницы, чтобы гарантировать правильную инициализацию элементов управления, сбор свойств элементов управления и текущих данных состояния, а также запуска любого управляющего кода [12].

    Примечание: Далее будут использоваться такие термины, как состояние просмотра (оно же – состояние вида, ViewState ), сессия (Session) и другие. Их объяснение будет дано позднее, в разделе " Управление состоянием в ASP.NET "

    6.2.1.1. Общие этапы жизненного цикла страницы

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

    Этапы жизненного цикла страницы
    Этап Описание
    Запрос страницы Запрос страницы происходит перед началом жизненного цикла страницы. При запросе страницы пользователем ASP.NET определяет, нужно ли обрабатывать и компилировать страницу (до начала жизненного цикла страницы ), или отправить в ответ на запрос кэшированную версию страницы, не запуская ее обработку.
    Запуск На начальном этапе устанавливаются свойства страницы, например Request и Response. На этом этапе страница также определяет, является ли запрос обратной передачей или новым запросом, и устанавливает свойство IsPostBack. Кроме этого, на этом этапе устанавливается свойство страницы UICulture.
    Инициализация страницы Во время инициализации страницы элементы управления страницы являются доступными, устанавливаются все свойства элементов управления UniqueID. На странице также применяются темы. Если текущий запрос является обратным запросом, данные обратного запроса не загружены, а значения свойств элементов управления не восстановлены к значениям в состоянии просмотра.
    Загрузка Во время загрузки, если текущий запрос является обратным запросом, в свойства элементов управления будут переданы данные, восстановленные из состояния просмотра и состояния управления.
    Проверка Во время проверки вызывается метод Validate всех проверяющих элементов управления, который устанавливает свойство IsValid отдельных проверяющих элементов управления и страницы.
    Обработка событий обратного запроса Если запрос является обратным, вызывается любой из обработчиков событий.
    Отрисовка Перед отрисовкой производится сохранение состояния просмотра страницы и всех элементов управления. На этапе отрисовки страница вызывает метод Render для каждого элемента управления, предоставляя модуль записи текста, который записывает полученные данные в OutputStream свойства страницы Response.
    Выгрузка Выгрузка вызывается после завершения отрисовки страницы, отправки клиенту и готовности к удалению. На данном этапе свойства страницы, например Response и Request, выгружаются, производится очистка.

    6.2.1.2. События жизненного цикла

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

    Страницы также поддерживают автоматическую обработку: ASP.NET производит поиск методов с соответствующими именами и автоматически выполняет эти методы при возникновении определенных событий. Если атрибут AutoEventWireup в директиве @Page установлен в значение true (или не установлен, так как он имеет значение true по умолчанию), события страницы автоматически привязываются к методам, которые используют правила именования Page_event, например Page_Load и Page_Init..

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

    События жизненного цикла страницы
    Событие страницы Типичные случаи использования
    PreInit Событие используется:
  • С помощью свойства IsPostBack нужно проверить, обрабатывается ли страница в первый раз.
  • Создание или повторное создание динамических элементов управления.
  • Init Возникает после инициализации всех элементов управления и применения параметров обложки. Это событие используется для чтения или инициализации свойств элемента управления.
    InitComplete Вызывается объектом Page. Это событие используется для обработки заданий, требующих завершения всех инициализаций.
    PreLoad Это событие используется при необходимости обработки страницы или элемента управления до наступления события Load. После вызова события при помощи Page оно загружает состояние просмотра для себя и всех элементов управления, затем обрабатывает все данные из обратных запросов, включенных в экземпляр Request.
    Load Page вызывает метод события OnLoad в Page, затем рекурсивно выполняет это действие для каждого дочернего элемента управления, до выполнения загрузки страницы и всех элементов управления. Метод события OnLoad используется для установки свойств элементов управления и создания подключения к базе данных.
    События элементов управления Эти события используются для обработки определенными событиями в элементах управления, например Button события элемента управления Click или TextBox события TextChanged.
    LoadComplete Это событие используется для обработки заданий, требующих полной загрузки всех других элементов управления страницы.
    PreRender До события:
  • Объект Page вызывает EnsureChildControls для каждого элемента управления и для страницы.
  • Каждый связанный элемент управления, свойство которого DataSourceID установлено, вызывает свой метод DataBind. Событие PreRender происходит для каждого элемента управления на странице. Это событие используется для внесения окончательных изменений на странице или в ее элементах управления.
  • SaveStateComplete До этого события ViewState сохраняется для страницы и всех элементов управления. Все изменения на странице или в ее элементах управления на данном этапе будут проигнорированы. Эти задачи используются для сохранения состояния просмотра без внесения изменений в элементы управления.
    Render Это не событие; вместо этого на данном этапе обработки объект Page вызывает этот метод для каждого элемента управления. Все серверные Веб-элементы управления ASP.NET обладают методом Render, который записывает разметку элемента управления, отправляемую клиенту. Обычно во время создания пользовательских элементов управления при выводе разметки элемента управления этот метод переопределяется. Однако если пользовательский элемент управления содержит только стандартные серверные элементы управления ASP.NET и не содержат пользовательской разметки, переопределять метод Render не требуется. Пользовательский элемент управления (файл с расширением ASCX) содержит отрисовку по умолчанию, таким образом, нет необходимости отрисовывать элемент управления явным образом.
    Unload Это событие происходит для всех элементов управления и затем для страницы. При работе с элементами управления это событие используется для выполнения окончательной очистки определенных элементов управления, например, для закрытия подключений отдельных элементов управления к базам данных. Относительно страницы это событие используется для выполнения окончательных действий, например, для закрытия открытых файлов и подключений к базам данных, а также закрытия пользовательских сеансов или других задач, связанных с запросами.

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

    (рис 6.3) 05_03(рис 6.3) Жизненный цикл страницы ASP

    Источник: ASP.NET 2.0 Page LifeCycle [13]

    6.2.1.3. Дополнительные аспекты жизненного цикла страницы

    Отдельные серверные элементы управления ASP.NET обладают собственным жизненным циклом, сходным с жизненным циклом страницы. Например, события Init и Load происходят во время соответствующих событий страницы.

    Хотя Init и Load рекурсивно происходят с каждым элементом, они выполняются в обратном порядке. Событие Init (а также Unload ) для каждого дочернего элемента происходят до возникновения соответствующего события в его контейнере (снизу вверх). Однако событие Load в контейнере происходит до событий Load в дочерних элементах управления (сверху вниз).

    При наследовании класса из класса Page кроме обработки событий страницы можно также переопределять методы базовых классов страницы. Например, при переопределении метода страницы InitializeCulture для динамической установки языка и региональных параметров. Стоит обратить внимание на то, что при создании обработчика событий с использованием синтаксиса Page_event базовая реализация вызывается явным образом и поэтому не требует вызова в методе. Например, метод базового класса страницы OnLoad вызывается вне зависимости от создания метода Page_Load. Однако при переопределении метода OnLoad с применением ключевого слова override ( Overrides в Visual Basic) необходимо вызвать базовый метод явным образом. Например, при переопределении метода страницы OnLoad необходимо вызвать base.OnLoad() ( MyBase.OnLoad() в Visual Basic) для запуска базовой реализации.

    6.2.2. Управление состоянием в ASP.NET

    Если просмотреть HTML-код любой aspx-страницы, то можно обратить внимание, что внутри формы страницы находятся скрытые поля:

    <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
    <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTY1NDU2MTA1MmRkIrOULfk+GC2eXyao7O8emfNAp+4=" />

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

    ViewState используется для сохранения состояний между отправками страниц на сервер и обратно на клиент, и позволяет серверу понять, как восстановить страницу к прежнему виду и узнать, какие поля пользователь изменил на странице. Это не единственный механизм сохранения состояния, используемый в ADO.NET. Рассмотрим эти механизмы [14, 15].

    В табл. 6.3, табл. 6.4, табл. 6.5 приводится краткий сравнительный анализ всех доступных для управления состоянием опций.

    Сравнение опций для управления состоянием (часть 1)
    Состояние просмотра Строка запроса Специальные cookie-наборы
    Допустимые типы данных Все поддающиеся сериализации .NET-типы данных. Ограниченное количество строковых данных. Строковые данные.
    Место хранения Скрытое поле на текущей Веб-странице. Строка URL-адреса в браузере. Компьютер клиента (в памяти или небольшом текстовом файле, в зависимости от срока жизни данного cookie-набора).
    Срок жизни Сохраняется постоянно для отправки данных на одну страницу. Утрачивается, когда пользователь вводит новый URL-адрес или закрывает окно браузера, однако, может быть сохранена в ссылках. Срок жизни cookie-наборов определяется программистом. Они могут использоваться на нескольких страницах и могут сохраняться между посещениями.
    Контекст Ограничивается, но текущей страницей. Ограничивается целевой страницей Все ASP.NET -приложение целиком.
    Безопасность По умолчанию является незащищенным, хотя можно воспользоваться директивами Page и принудительно применить шифрование и хеширование. Доступна для просмотра и запросто может быть изменена пользователем. Никак не защищены и могут изменяться пользователем.
    Сложности, влияющие на производительность Хранение большого количества информации замедлит процесс передачи, но никак не отразится на производительности сервера. Никаких, потому что количество данных очевидно. Никаких, потому что количество данных очевидно.
    Обычно применяется для: Для настройки параметров конкретной страницы. Для отправки идентификационного номера продукта со страницы каталога на страницу подробностей. Для определения персонализированных предпочтений на Веб-сайте
    Сравнение опций для управления состоянием (часть 2)
    Состояние сеанса (Session) Состояние приложения (Application)
    Допустимые типы данных Все поддающиеся сериализации .NET-типы данных. Не поддающиеся сериализации типы поддерживаются, если используется внутрипроцессная служба состояний. Все .NET-типы данных.
    Местонахождение хранилища/Место хранения данных В памяти сервера В памяти сервера.
    Время жизни Истекает по прошествии предопределенного периода времени (который, как правило, длится 20 минут, но может быть изменен глобально или программно). Совпадает со сроком жизни приложения (который обычно длится до перезагрузки сервера).
    Контекст Все ASP.NET -приложение. Все ASP.NET -приложение. В отличие от большинства других типов методов, данные приложения являются глобальными для всех пользователей.
    Безопасность Является безопасным/защищенным, потому что данные никогда не передаются клиенту. Однако, подвержено атакам типа перехвата сеанса, если не используется SSL. Является очень безопасным, потому что данные никогда не передаются клиенту.
    Сложности, влияющие на производительность Сохранение большого количества информации может значительно замедлить работу сервера, особенно в случае, когда к нему подключается одновременно большое количество пользователей, потому что для каждого пользователя будет создаваться отдельная копия данных сеанса. Сохранение большого количества информации может замедлить работу сервера, потому что срок жизни этих данных никогда не будет заканчиваться, и они и никогда не будут удаляться.
    Обычно применяется: Для хранения элементов в "корзине для покупок". Для хранения глобальных данных любого типа.
    Сравнение опций для управления состоянием (часть 3)
    Профили Кэширование
    Допустимые типы данных Все поддающиеся сериализации .NET-типы данных. Не поддающиеся сериализации типы поддерживаются, если создается специальный профиль. Все .NET-типы данных.
    Местонахождение хранилища/место хранения данных В конечной базе данных В памяти сервера.
    Срок жизни Постоянный Зависит от применяемой вами политики истечения сроков, но может оканчиваться раньше, если серверу перестает хватать ресурсов памяти.
    Контекст Все ASP.NET -приложение. К ним также могут доступ и другие приложения. Тот же, что и состояния приложения (глобальный для всех пользователей и всех страниц).
    Безопасность Являются довольно безопасными, потому что хотя данные и никогда не передаются клиенту, они хранятся в базе данных, которая может быть "взломана". Является достаточно безопасным, потому что данные никогда не передаются клиенту.
    Сложности, влияющие на производительность Позволяют легко сохранять большое количество данных, но не исключают возникновение нетривиальных непроизводительных издержек при извлечении и записи данных для каждого запроса. Сохранение большого количества информации может привести к вытеснению другой более полезной, находящейся в кэше информации. Однако, ASP.NET имеет возможность удалять элементы заблаговременно для гарантии оптимальной производительности.
    Обычно применяется: Для хранения информации об учетной записи пользователя. Для хранения данных, извлекаемых из базы данных.

    6.2.3. Состояние просмотра ViewState

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

    Как и в основе большинства опций для управления состоянием в ASP.NET, в основе состояния просмотра лежит коллекция типа словаря, где каждый элемент индексируется с помощью уникального строкового имени. Например:

    ViewState["CurrentPage"] = 3;

    Этот код помещает в коллекцию ViewState значение 3 (или, скорее, целое число, которое содержит значение 3) и присваивает ему описательное имя CurrentPage. Если в коллекции ViewState на текущий момент нет элемента с именем CurrentPage, в нее будет автоматически добавлен такой новый элемент. Если элемент с таким именем уже существует, он будет заменен.

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

    Ниже показан код, который извлекает значение CurrentPage и преобразовывает его в целое число:

    int counter;
    if (ViewState["CurrentPage"] != null)
    {
       counter = (int)ViewState["CurrentPage"];
    }

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

    6.2.3.1. Сохранение объектов в состоянии просмотра

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

    Чтобы сделать объекты пригодными для сериализации, следует просто добавить перед объявлением соответствующего класса атрибут Serializable. Например, ниже показан чрезвычайно простой класс BookPage:

    [Serializable]
    public class BookPage
    {
       public int PageNamber;
       public string Text;
       
       public BookPage(int pageNamber, string text)
       {
          PageNamber = pageNamber;
          Text = text;
       }
    }

    Поскольку класс BookPage помечен как пригодный для сериализации/поддающийся сериализации, он может быть сохранен в состоянии просмотра:

    BookPage page = new BookPage (3, "Понедельник начинается в субботу");
    ViewState["CurrentPage"] = page;

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

    BookPage cust = (BookPage)ViewState["CurrentPage"];

    Чтобы класс поддавался сериализации, он должен отвечать следующим требованиям:

  • он должен иметь атрибут Serializable ;
  • все порождаемые от него классы тоже должны иметь атрибут Serializable ;
  • все индивидуальные переменные этого класса должны представлять собой поддающиеся сериализации типы данных, а все не поддающиеся сериализации типы данных должны сопровождаться атрибутом NonSerialized (во время процесса сериализации они будут просто игнорироваться).
  • 6.2.3.2. Оценивание преимуществ использования состояния просмотра

    Применение состояния просмотра является идеальным вариантом, потому что не предполагает использования никаких ресурсов памяти сервера и появления случайных ограничений (типа таймаута). Но есть и некоторые причины, когда состояние просмотра лучше не применять:

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

  • Когда этот элемент управления никогда не изменяется. Например, кнопка со статическим текстом не нуждается в состоянии просмотра.
  • Когда этот элемент управления заново заполняется данными после каждой отправки данных. Например, элемент управления типа надписи ( Label ), отображающий текущее время, значение для которого устанавливается в обработчике событий Page.Load, не нуждается в состоянии просмотра.
  • Когда этот элемент управления представляет собой элемент управления для ввода данных и изменяется только после того, как пользователь выполнит соответствующие действия. После каждой отправки данных ASP.NET будет заполнять такие элементы управления данными, используя введенные в форме значения. Это означает, что текст в текстовом поле или выбранный элемент в поле со списком не будут утрачиваться, даже если состояние просмотра не используется.
  • Чтобы отключить состояние просмотра для какого-нибудь одного элемента управления, необходимо установить для свойства EnableViewState этого элемента управления значение false. Чтобы отключить состояние просмотра для всей страницы и всех отображаемых на ней элементов управления, необходимо установить значение false для свойства EnableViewState этой страницы или используйте в директиве Page атрибут EnableViewState, как показано ниже:

    <%@ Page Language="c#" EnableViewState="false" ... %>

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

    6.2.4. Строка запроса

    Одним из самых серьезных ограничений состояния просмотра является то, что оно работает только на одной странице. Если пользователь переходит на другую страницу, сохраненная в нем информация утрачивается. Существует несколько способов решить эту проблему; то, какой из них будет наиболее подходящим, зависит от имеющихся требований.

    Наиболее распространенный подход – передавать информацию с помощью строки запроса в URL-адресе. Именно этот подход часто применяется в поисковых службах. Например, при выполнении поиска на Веб-сайте Google, пользователь будет перенаправлен на новый URL-адрес, включающий указанные им параметры поиска:

    http://www.google.ru/search?ie=UTF-8hl=ruq=evolutionredir_esc=yei=iRKRS5ndN5-inQOH96DTBg

    Строка запроса – это та часть URL-адреса, которая находится после вопросительного знака.

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

  • она может передавать информацию только в виде простых строк, которые должны содержать допустимые для использования в URL-адресе символы;
  • передаваемая с помощью строки запроса информация визуально доступна для пользователя и любого другого работающего в Интернете человека;
  • инициативный пользователь может решить изменить строку запроса и предоставить новые значения, которые программа никак не ожидает получить и от которых она не имеет защиты;
  • многие браузеры имеют ограничения касательно длины URL-адреса (которая, как правило, не должна превышать 1-2 КБ), поэтому в строку запроса нельзя поместить большое количество информации, и все равно придется выполнять проверку на совместимость с большинством браузеров.
  • И все-таки добавление информации в строку запроса является полезной технологией. Она особенно подходит для приложений баз данных, в которых пользователю отображается список элементов, соответствующих записям в базе данных (например, это может быть список продуктов): пользователь выбирает элемент, после чего он перенаправляется на другую страницу, содержащую детальную информацию о том элементе, который был им выбран. Один из наиболее простых способов реализовать такую схему – это заставить первую страницу отправлять идентификатор элемента второй странице. Вторая страница затем будет отыскивать этот элемент в базе данных и отображать детальную информацию о нем. Эта технология очень часть применяется на сайтах электронной коммерции, таких как Amazon.com.

    6.2.4.1. Использование строки запроса

    Чтобы сохранить информацию в строке запроса, ее придется сначала самостоятельно поместить туда. Как правило, это означает, что придется использовать специальный элемент управления HyperLink или оператор Response.Redirect(), подобный тому, который показан ниже:

    // Переходим на страницу products/default.aspx. 
    int categoryID = 10;
    Response.Redirect("products/default.aspx?category=" + recordID.ToString());

    Отправлять можно и несколько параметров, только тогда их следует разделять с помощью амперсанда ( ), как показано ниже:

    Response.Redirect("products/default.aspx?category=" + categoryID.ToString()+"subcategory="+subcategoryId.ToString());

    Получающей странице легче работать со строкой запроса. Она может получать значения из коллекции типа словаря QueryString, предоставляемой встроенным объектом Request, как показано ниже:

    string ID = Request.QueryString["category"];

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

    6.2.5. Cookie

    Специальные cookie-наборы – это еще один способ сохранить информацию для последующего использования. Cookie-наборы представляют собой небольшие файлы, которые создаются на жестком диске клиента (или, если они являются временными, в памяти Веб-браузера). Одним из преимуществ cookie-наборов является то, что они работают "прозрачно" и пользователь даже не знает о том, что эта информация должна быть сохранена. Они также могут запросто использоваться любой страницей в приложении и даже сохраняться между посещениями, что подразумевает действительно долгосрочное хранение. Они имеет те же недостатки, что и строки запросов. А именно: они могут хранить только простую строковую информацию, и пользователь запросто может получить к ним доступ и просмотреть их, отыскав и открыв соответствующий файл. Эти факторы делают их неподходящим вариантом, когда требуется сохранить сложную или секретную информацию или просто большие объемы данных.

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

    Прежде чем использовать cookie-наборы, следует импортировать пространство имен System.NET, которое позволяет работать с соответствующими типами, как показано ниже:

    using System.Net;

    В использовании cookie-наборов в принципе нет ничего особого сложного. Коллекцию Cookies предоставляют два объекта: объект Request и объект Response (оба из которых предоставляются через свойства объекта Page ). Главное запомнить следующее: извлекать cookie-наборы следует из объекта Request, а устанавливать их следует с помощью объекта Response.

    Чтобы установить cookie-набор, необходимо создать новый объект System.Net.HttpCookie. Затем, необходимо заполнить его строковой информацией и присоединить его к текущему Веб-ответу, как показано ниже:

    // Создаем объект cookie
    HttpCookie cookie = new HttpCookie("Language");
    // Устанавливаем в нем значение
    cookie["LanguagePref"] = "English";
    // Добавляем его в текущий Веб-ответ
    Response.Cookies.Add(cookie);

    Cookie-набор, добавленный таким образом, будет сохраняться до тех пор, пока пользователь не закроет окно браузера, и будет отправляться вместе с каждым запросом. Чтобы создать cookie-набор с более длинным сроком хранения, необходимо установить дату истечения срока, как показано ниже:

    // Этот cookie будет оставаться действительным в течение одного года.
    cookie.Expires = DateTime.Now.AddYears(1);

    Извлекаются cookie по имени с помощью коллекции Request.Cookies, как показано ниже:

    HttpCookie cookie = Request.Cookies["Language"];
    // Проверяем, был ли найден cookie с таким именем.
    // Это хорошая мера предосторожности, потому что пользователь может отключить поддержку cookie's, 
    //а в таком случае cookie не будет существовать.
    string language;
    if (cookie != null)
    {
       language = cookie["LanguagePref"];
    }

    Единственный способ удалить cookie – это заменить его на cookie-набор, дата истечения срока хранения которого уже прошла. Следующий фрагмент кода демонстрирует, как это можно сделать:

    HttpCookie cookie = new HttpCookie("LanguagePref");
    cookie.Expires = DateTime.Now.AddDays(-1);
    Response.Cookies.Add(cookie);

    6.2.6. Использование Session

    Состояние сеанса (Session) – это самая сложная технология управления состояниями. Она позволяет сохранять информацию на одной странице и затем получать к ней доступ с другой страницы, а также поддерживает объекты любого типа, включая специальные, создаваемые самим разработчиком, типы данных. Лучше всего то, что состояние сеанса использует тот же основанный на коллекциях синтаксис, что и состояние просмотра. Единственное отличие – имя встроенного свойства страницы, которое в данном случае выглядит так: Session.

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

    6.2.6.1. Архитектура сеанса

    Управление сеансом не является частью HTTP-стандарта. Поэтому ASP.NET приходится выполнять некоторую дополнительную работу, чтобы отследить информацию сеанса и привязать ее к соответствующему ответу.

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

    Рассмотрим, как ASP.NET хранит данные в сессии.

    Когда ASP.NET обрабатывает HTTP-запрос, тот проходит через конвейер различных модулей, которые могут реагировать на события приложения. Одним из модулей в этой цепочке является модуль SessionStateModule (который находится в пространстве имен System.Web.SessionState ). Этот модуль генерирует идентификатор сеанса, извлекает из внешних поставщиков состояния данные сеанса и затем привязывает эти данные к контексту вызовов запроса. Он также сохраняет данные состояния сеанса, когда обработка страницы завершается. Однако важно понимать, что модуль SessionStateModule фактически не хранит данные сеанса. Вместо этого, состояние сеанса сохраняется во внешних компонентах, которые называются поставщиками состояния. Весь этот процесс показан на рис. 6.4.

    (рис 6.4) Архитектура состояния сеанса в ASP.NET

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

    6.2.6.2. Использование состояния сеанса

    Взаимодействовать с состоянием сеанса можно используя класс System.Web.SessionState.HttpSessionState, который на Веб-странице ASP.NET доступен в виде встроенного объекта Session. Синтаксис для добавления элементов в эту коллекцию и их извлечения выглядит практически точно так же, как и синтаксис, который используется для добавления элементов в состояние просмотра страницы.

    Например, сохранить объект DataSet в памяти сеанса можно следующим образом:

    Session["ds"] = ds;

    После этого, его можно извлечь с помощью соответствующей операции преобразования:

    ds = (DataSet)Session["ds"];

    Контекст состояния сеанса охватывает все приложение и является глобальным для текущего пользователя. Состояние сеанса утрачивается в следующих случаях:

  • если пользователь закрывает и заново запускает браузер;
  • если пользователь получает доступ к той же странице через другое окно браузера при сохранении доступа к Веб-странице из исходного окна браузера (разные браузеры ведут себя по-разному в такой ситуации);
  • если сеанс завершается из-за отсутствия активности со стороны пользователя (по умолчанию сеанс автоматически завершается после 20 минут простоя);
  • если программист завершает сеанс, вызывая метод Session.Abandon().
  • В первых двух случаях, сеанс фактически остается в памяти, потому что Веб-сервер не имеет ни малейшего понятия о том, что клиент закрыл или сменил окно браузера. Сеанс будет находиться в памяти, оставаясь недоступным, до тех пор, пока, в конце концов, не истечет срок его действия.

    6.2.6.3. Поставщики состояния сеанса

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

    6.2.6.3.1. Off

    Установка значения Off приводит к отключению функции управления состоянием сеанса для всех страниц в приложении. Это может немного повысить производительность Веб-сайтов, которые не используют состояние сеанса.

    6.2.6.3.2. InProc

    Установка значения InProc напоминает подход, который использовался для хранения состояния сеанса в классической версии ASP. Это значение указывает ASP.NET хранить информацию в текущем домене приложения, что обеспечивает наилучшую производительность, но наименьший срок службы: если администратор перезапустит сервер, данные состояния будут утрачены.

    Значение InProc используется по умолчанию и подходит для большинства Веб-сайтов небольшого размера. Однако в сценарии с группой серверов от него не будет никакого толку. Сделать так, чтобы состояние сеанса могли совместно использовать сразу несколько серверов, можно только воспользовавшись внепроцессным поставщиком или службой состояний SQL Server. Еще одна причина, по которой установка значения InProc может быть нежелательной, состоит в том, что оно подразумевает создание более "хрупких" сеансов. В ASP.NET, домены приложений нередко создаются заново в ответ на различные операции типа изменения конфигурационных настроек или обновления страниц, а так же при достижении определенных пороговых значений (независимо от того, произошла ошибка или нет). Если будет обнаружено, что домен приложения часто перезапускается, что приводит к преждевременному завершению сеансов, можно попытаться устранить этот эффект, изменив те или иные параметры модели процесса, или воспользоваться другим более надежным поставщиком состояния сеанса.

    Прежде чем использовать внепроцессную модель (StateServer) или службу состояний SQL Server, придется принять во внимание следующие моменты:

  • Когда выбирается режим StateServer или SqlServer, сохраняемые в состоянии сеанса объекты должны допускать сериализацию. Иначе ASP.NET не сможет передавать их службе состояний или сохранять в базе данных.
  • Если ASP.NET обслуживает группа Веб-серверов, придется выполнить некоторые дополнительные конфигурационные шаги для гарантии того, что все Веб-серверы будут работать синхронно. Иначе, не исключено, что один сервер будет кодировать информацию не так, как другой, а это, несомненно, приведет к появлению проблем, если во время сеанса пользователь будет перенаправляться от одного сервера к другому (решением этой проблемы является изменение раздела <machineKey> файла machine.config так, чтобы он был одинаковым на всех серверах).
  • Если не используется внутрипроцессный поставщик состояния, событие SessionStateModule.End не будет инициироваться, и все обработчики этого события в файле global.asax или HTTP-модуле будут игнорироваться.
  • 6.2.6.3.3. StateServer

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

    Выбрав режим StateServer, обязательно следует указать значение для параметра stateConnectionString. Эта строка сообщает TCP/IP-адрес компьютера, на котором запускается служба StateServer, и номер его порта (который определяется ASP.NET и который, как правило, не требуется изменять). Это позволяет обслуживать службу StateServer на другом компьютере. Если не изменить значение этого параметра, будет использоваться локальный сервер (адрес которого выглядит так: 127.0.0.1).

    6.2.6.3.4. SqlServer

    Это значение указывает ASP.NET использовать для хранения данных сеанса базу данных SQL Server, применяя параметры, определенные в атрибуте sqlConnectionString. Такой способ управления состоянием является самым удобным, но и пока что самым медленным. Чтобы его можно было использовать, на сервере должна быть установлена база данных SQL Server.

    Установка значения для атрибута sqlConnectionString выполняется по схеме, подобной той, что используется для получения доступа к данным ADO.NET. В целом это подразумевает указание источника данных (т.е. адреса сервера), имени пользователя и пароля, если только не используется интегрированная система безопасности SQL.

    Обычно база данных состояния всегда называется "ASPState". Поэтому строка подключения в файле web.config не отображает явно имя базы данных. Вместо этого, она просто отражает месторасположение сервера и тип аутентификации, который будет использоваться:

    <sessionState sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI" ... />

    При желании использовать другую базу данных (с такой же структурой), необходимо установить для атрибута allowCustomSqlDatabase значение true и убедиться в том, что строка подключения включает параметр Initial Catalog, указывающий имя базы данных, которую следует использовать:

    <sessionState allowCustomSqlDatabase="false" sqlConnectionString=
    "data source=127.0.0.1;Integrated Security=SSPI;Initial Catalog=CustDatabase"
    ... />

    Выбрав режим SqlServer, также можное установить значение для необязательного атрибута sqlCommandTimeout. Этот атрибут указывает максимальное количество секунд, в течение которых должен ожидаться ответ от базы данных, прежде чем запрос будет отменен. По умолчанию ему присваивается значение, равное 30 секундам.

    6.2.7. Ключевые термины

    ASP.NET, Жизненный цикл страницы, Управление состоянием, ViewState, Строка запроса, Cookies, Состояние сеанса.

    6.3. Принципы разработки пользовательского интерфейса Интернет-приложений

    Вопросы построения пользовательского интерфейса являются одними из самых важных в процессе разработки приложения [1]. В случае разработки Веб-приложения, они являются особенно актуальными, т.к. процесс создания пользовательского интерфейса здесь имеет ряд существенных отличий от традиционных Windows-приложений [15]. При построении Веб-приложения необходимо учитывать тот факт, что его интерфейс отображается в окне браузера, и, следовательно, ограничен его возможностями.

    Разработку пользовательского интерфейса Веб-приложения можно производить как с помощью редактирования исходного кода страницы, так и с использованием встроенного в Visual Studio визуального редактора. Наиболее эффективным способом является использование комбинированного метода, при котором в некоторых режимах редактирования целесообразно пользоваться визуальными средствами, в других же случаях – средствами редактирования исходного кода.

    Основной сложностью при разработке пользовательского интерфейса Веб-приложения является позиционирование его элементов. Существует четыре основных режима размещения элементов управления Веб-страницы:

  • Абсолютное позиционирование (absolutely positioned) – позволяет располагать элементы в точности там, куда их помещает разработчик. При этом элементы управления имеют абсолютное положение на странице.
  • Относительное позиционирование (relatively positioned) – очень похоже на абсолютное с той разницей, что позиция элемента задается относительно элемента, имеющего статическое расположение на странице.
  • Статическое позиционирование (statically positioned) – при котором положение элементов управления определяется относительно других элементов управления, размещенных на странице. При этом все элементы располагаются последовательно один за другим.
  • Без заданного атрибута позиционирования (no positioning attribute) – при котором редактором удаляется любая информация относительно позиционирования элемента управления. При этом используется статическое позиционирование.
  • Статическое позиционирование рекомендуется использовать в случае, когда расположенный на странице текст чередуется с элементами управления.

    При использовании абсолютного и относительного позиционирования Visual Studio добавляет специальные атрибуты, задающие положение элемента. В следующем примере показан фрагмент кода HTML, в котором описывается расположение трех кнопок с разными атрибутами позиционирования [16]:

    <asp:Button ID="Button1" runat="server" Style="z-index: 100; left: 436px; position: absolute;top: 187px" Text="Button1" />
    <asp:Button ID="Button2" runat="server" Style="left: 245px; position: relative; top: 266px" Text="Button2" />
    <asp:Button ID="Button3" runat="server" Style="position: static" Text="Button3" />

    Для элемента Button1 использовалось абсолютное позиционирование, для Button2 – относительное, Button3 – статическое (рис. 6.5).

    (рис 6.5) Перегрузка данных и обработка запроса

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

    Если сгруппировать HTML и серверные элементы управления, по видам задач программирования, можно получить табл. 6.6 [1, 17].

    Группировка HTML и серверных компонент
    Задача HTML элементы Серверные элементы
    Отображение текста Input (Text), Textarea Label, TextBox, Literal
    Отображение таблиц Table Table, DataGrid
    Выбор значения из списка Select DropDownList, ListBox, DataList, Repeater
    Исполнение команд Input (Button), Input (Reset), Input (Submit) Button, LinkButton, ImageButton
    Установка значений Input (CheckBox), Input (Radio) CheckBox, CheckBoxList, RadioButton, RadioButtonList
    Отображение графики Image Image, ImageButton
    Работа с датами Calendar
    Демонстрация рекламных изображений AdRotator
    Отображение горизонтальной линии Horizontal Rule Literal
    Получение файлов от клиентов Input (File) FileUpload
    Сохранение введенных на странице данных Input (Hidden) ViewState
    Проверка вводимых данных Страничные сценарии RequiredFildValidator, RangeValidator, RegularExpressionValidator, CompareValidator, CustomValudator, ValidationSummary

    6.3.1. Работа с текстом

    Одной из наиболее часто возникающих задач при создании Веб-приложения, является работа с текстом. Для этого существует несколько различных способов, начиная от Response.Write("Текст") и заканчивая использованием элемента Label или TextBox с установленным в True значением свойства ReadOnly.

    Рассмотрим небольшой пример, который переопределяет текст, отображаемый при помощи элемента Label, на текст, набранный пользователем в элемент TextBox. Для этого реализуем следующую страницу:

    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
            <br />
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            <br />
            <asp:Button ID="Button1" runat="server" Text="Button" OnClick="OnClick"/>
        </div>
        </form>
    </body>

    Как видно, изначально компонент Label1 отображает текст Label. Реализуем обработчик события OnClick кнопки так, чтобы она отображала в Label набранный пользователем текст:

    protected void OnClick(object sender, EventArgs e)
    {
        Label1.Text = TextBox1.Text;
    }

    Результат работы представлен на рис. 6.6.

    (рис 6.6) Смена выводимой надписи в элементе Label при нажатии на соответствующую кнопку

    6.3.2. Использование элементов CheckBox, CheckBoxList, RadioButton, RadioButtonList и BulletedList

    В ряде случаев необходимо принимать от пользователя булевые значения, для этих целей применяются элементы CheckBox, CheckBoxList, RadioButton и RadioButtonList. Элементы CheckBox и RadioButton отличаются тем, что CheckBox позволяет устанавливать значения одного или нескольких флажков одновременно, в то время как RadioButton – только одно значение. Окончание List говорит о том, что данный элемент управления представляет собой целый набор флажков, объединенных в группу. Группы флажков легче привязывать к источникам данных, поэтому их целесообразнее использовать в случае, если флажки должны отображать данные, находящиеся в БД, либо с помощью них данные должны вводиться в базу данных, либо если флажки логически связаны между собой.

    Для получения значений элементов управления CheckBox и RadioButton необходимо использовать свойство Checked. Например, в следующем коде осуществляется проверка значения флажка, которое выводится на экран:

    protected void Button1_Click(object sender, EventArgs e)
    {
    Response.Write("Флажок установлен в значение "+CheckBox1.Checked.ToString());
    }

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

    Для получения и установки значений элементов управления RadioButtonList и CheckBoxList необходимо последовательно опрашивать все элементы управления списка проверяя их значения. Для этого очень удобно использовать цикл For Each.

    В следующем примере последовательно проверяются значения всех флажков элемента CheckBoxList1. Если флажок выбран, на экран выводится соответствующее сообщение:

    protected void Button1_Click(object sender, EventArgs e)
    {
    foreach (ListItem l in CheckBoxList1.Items)
    {
          if (l.Selected)
                       Response.Write("выбран " + l.Text + "<br/>");
    }
    }

    Следует обратить внимание на тот факт, что элемент управления CheckBoxList, как и RadioButtonList содержит элементы управления ListControl, а не CheckBox или RadioButton, как можно было бы предположить.

    Аналогичным образом производятся проверки и для элемента RadioButtonList.

    BulletedList является аналогом HTML элементов, предназначенных для организации упорядоченных и неупорядоченных списков с помощью тэгов <ul> и <ol> соответственно, однако позволяет обращаться к списку программно. Для установки элементов, отображаемых в списке, необходимо ввести их с помощью средств, аналогичных рассмотренным ранее для CheckBoxList и RadioButtonList.

    Особенностью BulletedList является возможность настройки внешнего вида и типа элементов списка. Основные свойства этого элемента управления показаны в табл. 6.7.

    Свойства элемента BulletedList
    Свойство Описание
    BulletedStyle Позволяет задавать тип списка numbered – нумерованный, loweralpha – маленькие латинские буквы, upperalpha – большие латинские буквы, lowerroman – маленькие римские цифры, upperroman – большие римские цифры, disc, circle, square – символы маркеров
    BulletedStyleImageUrl Устанавливает изображение, расположенное слева от каждого элемента списка. Для установки изображения необходимо, чтобы значение BulletedStyle= CustomImage
    FirstBulletNumber Устанавливает значение для первого элемента списка, относительно которого в дальнейшем будет продолжена нумерация
    DisplayMode Устанавливает тип элемента списка ( Text, HyperLink, LinkButton )

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

    protected void BulletedList1_Click(object sender, BulletedListEventArgs e)
    {
    Response.Write("Вы щелкнули по элементу списка "+BulletedList1.Items[e.Index].ToString());
    }

    6.3.3. Использование Image, ImageButton

    Отображение графики на Веб-странице является абсолютно необходимым условием. ASP.NET предоставляет несколько возможностей отображения графики:

  • Как фон, заполняющий всю страницу, для этого можно воспользоваться свойством Background Веб-формы. Можно также использовать свойство BackImageUrl элемента Panel.
  • На переднем плане. Для этого используется элемент управления Image.
  • На кнопке, способной реагировать на действия пользователя. Для этого используется элемент управления ImageButton.
  • С помощью карты изображений, реализуемой посредством элемента управления ImageMap.
  • Элемент управления Image позволяет отображать графические изображения. При этом он неспособен реагировать на действия пользователя, однако способен отображать графические элементы в зависимости от действий, выполненных над другими элементами управления.

    В следующем примере при нажатии на соответствующую кнопку отображается изображение машины, мотоцикла либо велосипеда (рис. 6.7):

    protected void buttonCar_Click(object sender, EventArgs e)
    {
        Image1.ImageUrl = "~//Images//car.jpg";
    }
    protected void buttonBike_Click(object sender, EventArgs e)
    {
        Image1.ImageUrl = "~//Images//bike.jpg";
    }
    protected void buttonCycle_Click(object sender, EventArgs e)
    {
        Image1.ImageUrl = "~//Images//cycle.jpg";
    }
    (рис 6.7) Смена выводимого на экран изображения при нажатии на соответствующую кнопку

    Элемент управления ImageButton имеет встроенную возможность реагирования на события, совершаемые пользователем. При этом в обработчик события щелчка левой кнопкой мыши по нему отправляется специальный объект ImageClickEventArgs, предоставляющий свойства X и Y, которые определяют место изображения, на котором был совершен щелчок. Используя эти свойства, можно создать карту изображения. Ниже показан код, который отображает координаты точки, в которой был произведен щелчок мыши, а также определяет, в пределах какой фигуры он был произведен (рис. 6.8):

    protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
    {
        string strClickFigure="";
        if (!(e.X <= 380  e.X >= 20  e.Y <= 380  e.Y >= 20)) 
           strClickFigure = "рамка";
        if (e.X>=60  e.X<=210  e.Y>=60  e.Y<=210) 
           strClickFigure="квадрат";
        if ((e.Y>=495-e.X)  (e.Y>=e.X-45)  e.Y<=332) 
           strClickFigure="треугольник";
        Label1.Text = "Вы щелкнули в точке Х="+e.X.ToString()+"; 
        Y="+e.Y.ToString()+" это "+strClickFigure;
    }
    (рис 6.8) Пример использования элемента ImageButton

    6.3.4. Использование Literal и HiddenField

    Элемент управления Literal представляет собой один из способов вывода информации на экран. Literal можно использовать в качестве контейнера для размещения HTML элементов на странице. Чаще всего его используют для динамического добавления текста. Схожие возможности по добавлению текста предоставляет элемент Label, Literal отличается от него тем, что не добавляет дополнительных HTML элементов к тексту. Label, например, размещает текст внутри тэга <span>, Panel – внутри <div> и т.д. Размещение элементов внутри тэгов создает возможность для поддержки ими стилей оформления, Literal же, не имеет такой возможности. Рекомендуется использовать элемент Literal в том случае, когда необходимо размещать текст на странице без использования дополнительной разметки, либо в том случае, когда существует HTML текст (например, хранящийся в файле или базе данных), содержащий форматирование с использованием тэгов, и его необходимо вывести на экран.

    Самым важным свойством элемента управления Literal является Mode. Возможны три значения этого свойства (табл. 6.8).

    Значения свойства Mode элемента управления Literal
    Значения Описание
    Transform Любая разметка, добавляемая к элементу управления, преобразуется таким образом, чтобы максимально удовлетворять особенностям протокола браузера, запрашивающего страницу.
    PassThrough Добавляемая к элементу управления разметка передается браузеру как есть, без каких-либо модификаций.
    Encode Добавляемая к элементу управления разметка декодируется с использованием метода HtmlEncode, преобразующего HTML представление страницы в текст.

    Например, при использовании следующего примера элемента Literal могут быть получены различные результаты.

    При использовании значения Mode=PassThrough, как показано в следующем фрагменте исходного кода:

    private string s = 
    "<input id='Button1' type='button' value='Добавить' /><br/>
          <table border='1' cellpadding='1' cellspacing='0'>
            <tr>
              <td>Идентификатор</td>
              <td>наименование</td>
              <td>кол-во</td>
            </tr>
            <tr>
              <td>1</td>
              <td>Велосипед горный</td>
              <td>10</td>
            </tr>
            <tr>
              <td>2</td>
              <td>Велосипед дорожный</td>
              <td>50</td>
            </tr>
          </table>";
    protected void Page_Load(object sender, EventArgs e)
    {
        Literal1.Mode = LiteralMode.PassThrough;
        Literal1.Text = s;
    }

    будет получен результат, изображенный на рис. 6.9.

    (рис 6.9) Использование Literal для отображения информации в режиме PassThrough

    А при использовании режима Encode результат, изображенный на рис. 6.10.

    (рис 6.10) Использование Literal для отображения информации в режиме Encode.

    Элемент управления HiddenField целесообразно использовать в том случае, когда на странице необходимо сохранить какие-то данные, но не отображать их. Например, это может быть какая-нибудь информация о пользователе, которая необходима для выполнения сервисных функций.

    У элемента HiddenField существует лишь одно свойство, заслуживающее внимания. Это Value, посредством которого ему и присваивается значение.

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

    6.3.5. Использование Panel

    Элемент управления Panel (при рендеренге страницы заменяется на div ) используется для группирования элементов управления. При этом он выступает в качестве контейнера, способного вмещать в себя различные другие элементы управления, манипулирование которыми становится возможным как единым целым. Например, возможно скрытие или показ элемента Panel со всеми входящими в него элементами путем задания значения свойства Visible равным true или false.

    При размещении внутри Panel элементов для ввода текста и кнопок, становится возможным определение кнопки, используемой по умолчанию. Это означает, что при вводе текста в элементы управления, размещенные внутри Panel, пользователь имеет возможность нажать кнопку Enter, что будет равносильно щелчку левой кнопки мыши по кнопке, указанной в свойстве DefaultButton элемента Panel. Это позволяет создавать более эффективные пользовательские формы для ввода данных.

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

  • С помощью Panel можно создать область, содержащую полосы прокрутки. Для этого достаточно установить соответствующее значение свойства ScrollBars, а также установить необходимые значения свойств Height и Width.
  • С помощью (рис 6.11) Пример изображения группы элементов

    Следует отметить, что при установке свойства GroupingText становится невозможным использование полос прокрутки.

  • С помощью Panel можно создать область страницы, имеющей отдельно заданные свойства, такие как цвет фона, рамка и т.д.
  • 6.3.7. Использование LinkButton

    Элемент управления LinkButton представляет собой кнопку, которая выглядит как гиперссылка, но имеет поведение кнопки. Этот элемент управления внедряет в HTML код страницы элементы JavaScript, необходимые для обработки событий кнопки, поэтому необходимо, чтобы клиентский браузер поддерживал JavaScript.

    LinkButton может быть двух разновидностей: командная кнопка и кнопка перенаправления. Кнопка перенаправления не содержит сопоставленного с ней обработчика события и просто инициирует событие postback. Командная кнопка ведет себя как обычная кнопка и может иметь несколько обработчиков событий, сопоставленных с ней. Как и обычная кнопка, она может реагировать на щелчок левой кнопки мыши с помощью события LinkButton_Click, кроме того, возможна обработка события LinkButton_Command. В качестве аргументов, обработчику события Command передаются значения свойств CommandName и CommandArgument. С помощью этого события становится возможным определение того, какая из нескольких, расположенных на странице кнопок была нажата.

    В следующем примере на странице размещены два элемента LinkButton:

    <asp:LinkButton ID="LinkButton1" runat="server" CommandName="Открыть" 
          CommandArgument="c:\1.txt" OnCommand="LinkButton_Command"> Открыть 
    </asp:LinkButton>
    <asp:LinkButton ID="LinkButton2" runat="server" 
          CommandArgument= "http://www.yandex.ru" CommandName="Перейти" 
          OnCommand="LinkButton_Command"> Перейти</asp:LinkButton>

    Процедура LinkButton_Command выводит на экран сообщение, в котором указаны аргументы, передаваемые обеими кнопками в случае их нажатия:

    protected void LinkButton_Command(object sender, CommandEventArgs e)
    {
        Response.Write("Команда: " + e.CommandName + ", параметр: " +
        e.CommandArgument);
    }

    6.3.8. Ключевые термины

    Пользовательский интерфейс.

    6.4. Краткие итоги

    Платформа .NET Framework – это интегрированный компонент Windows, который поддерживает создание и выполнение нового поколения приложений и Веб-служб XML.

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

    Библиотека классов FCL (Framework Class Library) открывает доступ к системным функциям, включая и те, что прежде были доступны только через API Windows, а также к прикладным функциям для Веб-разработки ( ASP.NET ), для доступа к данным (ADO.NET), обеспечения безопасности и удаленного управления.

    ASP.NET – это платформа для создания Веб-приложений и Веб-сервисов, работающих под управлением IIS.

    При выполнении страницы ASP.NET осуществляется ее жизненный цикл, во время которого исполняется ряд шагов обработки, такие как: инициализация, определение элементов управления, восстановление и поддержание рабочего состояния, выполнение кода обработчика событий, а также отрисовка.

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

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

    Возврат информации серверу осуществляется с помощью механизма состояний просмотра (состояние вида, ViewState ).

    Существует несколько способов сохранения состояния просмотра:

  • строка запроса в URL-адресе;
  • cookie;
  • состояние сеанса (Session).
  • Основной сложностью при разработке пользовательского интерфейса Веб-приложения является позиционирование его элементов.

    Для создания пользовательского интерфейса Веб-приложения возможно использование как серверных, так и HTML элементов управления.

    Одной из наиболее часто возникающих задач при создании Веб-приложения, является работа с текстом.

    В ряде случаев необходимо принимать от пользователя булевые значения, для этих целей применяются элементы CheckBox, CheckBoxList, RadioButton и RadioButtonList.

    ASP.NET предоставляет несколько возможностей отображения графики.

    Элемент управления Literal представляет собой один из способов вывода информации на экран.

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

    Элемент управления Panel используется для группирования элементов управления.

    Элемент управления LinkButton представляет собой кнопку, которая выглядит как гиперссылка, но имеет поведение кнопки.

    Страницы:

    Презентацию к данной лекции Вы можете скачать здесь.

    6.1. Описание .NET Framework

    Платформа .NET Framework – это интегрированный компонент Windows, который поддерживает создание и выполнение нового поколения приложений и Веб-служб XML [1].

    Двумя основными компонентами платформы .NET Framework являются общеязыковая среда выполнения (CLR) и библиотека классов .NET Framework. Основой платформы .NET Framework является среда CLR. Среду выполнения можно считать агентом, который управляет кодом во время выполнения и предоставляет основные службы, такие, как управление памятью, управление потоками и удаленное взаимодействие. При этом накладываются условия строгой типизации и другие виды проверки точности кода, обеспечивающие безопасность и надежность. Фактически основной задачей среды выполнения является управление кодом. Код, который обращается к среде выполнения, называют управляемым кодом, иначе код называется неуправляемым. Другой основной компонент платформы .NET Framework – библиотека классов, представляет полную объектно-ориентированную коллекцию типов, которые применяются для разработки приложений, начиная от обычных, запускаемых из командной строки или с графическим интерфейсом пользователя, и заканчивая приложениями, использующими последние технологические возможности ASP.NET, такие как Web Forms и Веб-службы XML.

    Платформа .NET Framework может размещаться неуправляемыми компонентами, которые загружают среду CLR в собственные процессы и запускают выполнение управляемого кода, создавая, таким образом, программную среду, позволяющую использовать средства как управляемого, так и неуправляемого выполнения. Платформа .NET Framework не только предоставляет несколько базовых сред выполнения, но также поддерживает разработку базовых сред выполнения независимыми производителями.

    На рис. 6.1 приведена общая архитектура .NET Framework в проекции на версии этой платформы [2].

    (рис 6.1) Общая архитектура .NET Framework

    6.1.1. Возможности среды CLR

    Среда CLR управляет памятью, выполнением потоков, выполнением кода, проверкой безопасности кода, компиляцией и другими системными службами [3]. Эти средства являются внутренними для управляемого кода, который выполняется в среде CLR.

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

    Среда выполнения обеспечивает управление доступом для кода. Например, пользователи могут доверить исполняемому приложению, внедренному в веб-страницу, воспроизведение анимации на экране или звукозаписи, не позволяя ему при этом получить доступ к личным данным, файловой системе или сети. Таким образом, средства безопасности CLR предоставляют подлинному развернутому в Интернете программному обеспечению исключительно богатые функции.

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

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

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

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

    И наконец, среда выполнения может размещаться в высокопроизводительных серверных приложениях, таких как Microsoft SQL Server и Internet Information Services (IIS). Такая инфраструктура позволяет использовать управляемый код для написания собственной логики программ, пользуясь при этом высочайшей производительностью лучших производственных серверов, которые поддерживают размещение среды выполнения.

    6.1.2. Библиотека классов платформы .NET Framework

    Над уровнем CLR находится набор базовых классов платформы, а над ним расположены слой классов данных и XML, а также слой классов для создания Веб-служб (Web Services), Веб- и Windows-приложений (Web Forms и Windows Forms). Собранные воедино, эти классы известны под общим названием FCL (Framework Class Library) (рис. 6.2). Эта библиотека открывает доступ к системным функциям, включая и те, что прежде были доступны только через API Windows, а также к прикладным функциям для Веб-разработки ( ASP.NET ), для доступа к данным (ADO.NET), обеспечения безопасности и удаленного управления. Имея в своем составе более 4000 классов, библиотека FCL способствует быстрой разработке настольных, клиент-серверных и других приложений и Веб-служб [4].

    (рис 6.2) Библиотека классов платформы .NET Framework

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

    Над этим уровнем находится уровень классов, которые расширяют базовые классы с целью обеспечения управления данными и XML. Классы данных позволяют реализовать управление информацией, хранящейся в серверных базах данных. В число этих классов входят классы SQL, дающие программисту возможность обращаться к долговременным хранилищам данных через стандартный интерфейс SQL. Кроме того, набор классов, называемый ADO.NET, позволяет оперировать постоянными данными. Платформа .NET Framework поддерживает также целый ряд классов, позволяющих манипулировать XML-данными и выполнять поиск и преобразования XML.

    Базовые классы, классы данных и XML расширяются классами, предназначенными для построения приложений на основе трех различных технологий: (Web Forms, Веб-формы) и Windows Forms (Windows-формы). Веб-службы включают в себя ряд классов, поддерживающих разработку облегченных распределяемых компонентов, которые могут работать даже с брандмауэрами и программами трансляции сетевых адресов (NAT). Поскольку Веб-службы применяют в качестве базовых протоколов связи стандартные протоколы HTTP и SOAP, эти компоненты поддерживают в киберпространстве подход "plug-and-play".

    Инструментальные средства Web Forms и Windows Forms позволяют применять технику Rapid Application Development (RAD, быстрая разработка приложений) для построения Веб- и Windows-приложений. Эта техника сводится к перетаскиванию элементов управления с панели инструментов на форму, двойному щелчку по элементу и написанию кода, обрабатывающего события, связанные с этим элементом.

    В общем, FCL можно использовать для разработки следующих типов приложений и служб:

  • консольные приложения;
  • приложения с графическим интерфейсом пользователя Windows (Windows Forms);
  • приложения ASP.NET ;
  • Веб-службы;
  • службы Windows.
  • Например, классы Windows Forms представляют собой полный набор типов, существенно упрощающих разработку графических интерфейсов пользователя Windows. При написании приложения форм ASP.NET можно использовать классы Web Forms.

    6.1.3. Развитие платформы .NET

    Версия .NET Framework 3 является ничем иным как: .NET Framework 2.0 + 4 новые подсистемы [5]:

  • Windows Presentation Foundation (WPF) – новая подсистема интерфейса пользователя и программный интерфейс на основе XML и векторной графики [6].
  • Windows Workflow Foundation (WF) – новая идеология программирования, предлагаемая компанией Microsoft, основанная на бизнес-сущностях и потоках [7].
  • Windows Communication Foundation (WCF) – сервис-ориентированная система обмена сообщениями, которая позволяет программам взаимодействовать локально или удаленно подобно веб-сервисам [8].
  • Windows CardSpace (WCS) – это способ безопасной идентификации пользователей при перемещении между ресурсами Интернета без необходимости повторного ввода имен и паролей [9].
  • .NET Framework 3.5 предоставляет новые возможности технологий из версий 2.0 и 3.0 и дополнительные технологии в виде новых сборок. В .NET Framework 3.5 впервые представлены следующие технологии:

  • LINQ;
  • новые компиляторы для C#, Visual Basic, C++ и J#;
  • ASP.NET AJAX.
  • Пакет обновления 1 (SP1) для .NET Framework 3.5 содержит обновления нескольких сборок, поставляемых с .NET Framework 3.5 [10]. Обновления включают изменения, не затрагивающие связанные компоненты, а также дополнительные функциональные возможности технологий, вошедших в состав .NET Framework 3.5. В .NET Framework 3.5 с пакетом обновления 1 (SP1) входят следующие технологии:

  • платформа динамических данных ASP.NET ;
  • ADO.NET Entity Framework;
  • поддержка поставщика данных SQL Server 2008;
  • поддержка .NET Framework Client Profile.
  • 6.1.4. Ключевые термины

    Платформа .NET Framework, Среда CLR, Библиотека классов платформы .NET Framework.

    6.2. Обзор технологии ASP.NET

    ASP.NET – это платформа для создания Веб-приложений и Веб-сервисов, работающих под управлением IIS [11]. Сегодня существуют другие технологии, позволяющие создавать Веб-приложения. К ним, прежде всего, относятся популярные сегодня языки PHP и PERL, технологии JSP, CSP, более старая технология CGI и т.д. Однако, ASP.NET отличается от них высокой степенью интеграции с серверными продуктами, а также с инструментами Microsoft для разработки, доступа к данным и обеспечения безопасности. Кроме того, использование ASP.NET позволяет разрабатывать Веб- и Windows приложения, используя очень похожие технологические цепочки, одинаковые языки программирования, технологии доступа к данным и т.д. Более того, базовые языки программирования, с помощью которых сегодня возможна разработка Веб-приложений являются полностью объектно-ориентированными, что делает разработку исполнимой части, а также ее модификацию, обслуживание, отладку и повторное использование гораздо более простым занятием, чем в других технологиях.

    6.2.1. Жизненный цикл Веб-страниц ASP.NET

    При выполнении страницы ASP.NET осуществляется ее жизненный цикл, во время которого исполняется ряд шагов обработки, такие как: инициализация, определение элементов управления, восстановление и поддержание рабочего состояния, выполнение кода обработчика событий, а также отрисовка. Знание жизненного цикла страницы необходимо, чтобы иметь возможность записывать код в нужный шаг жизненного цикла с нужным результатом. Кроме этого, при создании собственных элементов управления необходимо ознакомиться с жизненным циклом страницы, чтобы гарантировать правильную инициализацию элементов управления, сбор свойств элементов управления и текущих данных состояния, а также запуска любого управляющего кода [12].

    Примечание: Далее будут использоваться такие термины, как состояние просмотра (оно же – состояние вида, ViewState ), сессия (Session) и другие. Их объяснение будет дано позднее, в разделе " Управление состоянием в ASP.NET "

    6.2.1.1. Общие этапы жизненного цикла страницы

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

    Этапы жизненного цикла страницы
    Этап Описание
    Запрос страницы Запрос страницы происходит перед началом жизненного цикла страницы. При запросе страницы пользователем ASP.NET определяет, нужно ли обрабатывать и компилировать страницу (до начала жизненного цикла страницы ), или отправить в ответ на запрос кэшированную версию страницы, не запуская ее обработку.
    Запуск На начальном этапе устанавливаются свойства страницы, например Request и Response. На этом этапе страница также определяет, является ли запрос обратной передачей или новым запросом, и устанавливает свойство IsPostBack. Кроме этого, на этом этапе устанавливается свойство страницы UICulture.
    Инициализация страницы Во время инициализации страницы элементы управления страницы являются доступными, устанавливаются все свойства элементов управления UniqueID. На странице также применяются темы. Если текущий запрос является обратным запросом, данные обратного запроса не загружены, а значения свойств элементов управления не восстановлены к значениям в состоянии просмотра.
    Загрузка Во время загрузки, если текущий запрос является обратным запросом, в свойства элементов управления будут переданы данные, восстановленные из состояния просмотра и состояния управления.
    Проверка Во время проверки вызывается метод Validate всех проверяющих элементов управления, который устанавливает свойство IsValid отдельных проверяющих элементов управления и страницы.
    Обработка событий обратного запроса Если запрос является обратным, вызывается любой из обработчиков событий.
    Отрисовка Перед отрисовкой производится сохранение состояния просмотра страницы и всех элементов управления. На этапе отрисовки страница вызывает метод Render для каждого элемента управления, предоставляя модуль записи текста, который записывает полученные данные в OutputStream свойства страницы Response.
    Выгрузка Выгрузка вызывается после завершения отрисовки страницы, отправки клиенту и готовности к удалению. На данном этапе свойства страницы, например Response и Request, выгружаются, производится очистка.

    6.2.1.2. События жизненного цикла

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

    Страницы также поддерживают автоматическую обработку: ASP.NET производит поиск методов с соответствующими именами и автоматически выполняет эти методы при возникновении определенных событий. Если атрибут AutoEventWireup в директиве @Page установлен в значение true (или не установлен, так как он имеет значение true по умолчанию), события страницы автоматически привязываются к методам, которые используют правила именования Page_event, например Page_Load и Page_Init..

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

    События жизненного цикла страницы
    Событие страницы Типичные случаи использования
    PreInit Событие используется:
  • С помощью свойства IsPostBack нужно проверить, обрабатывается ли страница в первый раз.
  • Создание или повторное создание динамических элементов управления.
  • Init Возникает после инициализации всех элементов управления и применения параметров обложки. Это событие используется для чтения или инициализации свойств элемента управления.
    InitComplete Вызывается объектом Page. Это событие используется для обработки заданий, требующих завершения всех инициализаций.
    PreLoad Это событие используется при необходимости обработки страницы или элемента управления до наступления события Load. После вызова события при помощи Page оно загружает состояние просмотра для себя и всех элементов управления, затем обрабатывает все данные из обратных запросов, включенных в экземпляр Request.
    Load Page вызывает метод события OnLoad в Page, затем рекурсивно выполняет это действие для каждого дочернего элемента управления, до выполнения загрузки страницы и всех элементов управления. Метод события OnLoad используется для установки свойств элементов управления и создания подключения к базе данных.
    События элементов управления Эти события используются для обработки определенными событиями в элементах управления, например Button события элемента управления Click или TextBox события TextChanged.
    LoadComplete Это событие используется для обработки заданий, требующих полной загрузки всех других элементов управления страницы.
    PreRender До события:
  • Объект Page вызывает EnsureChildControls для каждого элемента управления и для страницы.
  • Каждый связанный элемент управления, свойство которого DataSourceID установлено, вызывает свой метод DataBind. Событие PreRender происходит для каждого элемента управления на странице. Это событие используется для внесения окончательных изменений на странице или в ее элементах управления.
  • SaveStateComplete До этого события ViewState сохраняется для страницы и всех элементов управления. Все изменения на странице или в ее элементах управления на данном этапе будут проигнорированы. Эти задачи используются для сохранения состояния просмотра без внесения изменений в элементы управления.
    Render Это не событие; вместо этого на данном этапе обработки объект Page вызывает этот метод для каждого элемента управления. Все серверные Веб-элементы управления ASP.NET обладают методом Render, который записывает разметку элемента управления, отправляемую клиенту. Обычно во время создания пользовательских элементов управления при выводе разметки элемента управления этот метод переопределяется. Однако если пользовательский элемент управления содержит только стандартные серверные элементы управления ASP.NET и не содержат пользовательской разметки, переопределять метод Render не требуется. Пользовательский элемент управления (файл с расширением ASCX) содержит отрисовку по умолчанию, таким образом, нет необходимости отрисовывать элемент управления явным образом.
    Unload Это событие происходит для всех элементов управления и затем для страницы. При работе с элементами управления это событие используется для выполнения окончательной очистки определенных элементов управления, например, для закрытия подключений отдельных элементов управления к базам данных. Относительно страницы это событие используется для выполнения окончательных действий, например, для закрытия открытых файлов и подключений к базам данных, а также закрытия пользовательских сеансов или других задач, связанных с запросами.

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

    (рис 6.3) 05_03(рис 6.3) Жизненный цикл страницы ASP

    Источник: ASP.NET 2.0 Page LifeCycle [13]

    6.2.1.3. Дополнительные аспекты жизненного цикла страницы

    Отдельные серверные элементы управления ASP.NET обладают собственным жизненным циклом, сходным с жизненным циклом страницы. Например, события Init и Load происходят во время соответствующих событий страницы.

    Хотя Init и Load рекурсивно происходят с каждым элементом, они выполняются в обратном порядке. Событие Init (а также Unload ) для каждого дочернего элемента происходят до возникновения соответствующего события в его контейнере (снизу вверх). Однако событие Load в контейнере происходит до событий Load в дочерних элементах управления (сверху вниз).

    При наследовании класса из класса Page кроме обработки событий страницы можно также переопределять методы базовых классов страницы. Например, при переопределении метода страницы InitializeCulture для динамической установки языка и региональных параметров. Стоит обратить внимание на то, что при создании обработчика событий с использованием синтаксиса Page_event базовая реализация вызывается явным образом и поэтому не требует вызова в методе. Например, метод базового класса страницы OnLoad вызывается вне зависимости от создания метода Page_Load. Однако при переопределении метода OnLoad с применением ключевого слова override ( Overrides в Visual Basic) необходимо вызвать базовый метод явным образом. Например, при переопределении метода страницы OnLoad необходимо вызвать base.OnLoad() ( MyBase.OnLoad() в Visual Basic) для запуска базовой реализации.

    6.2.2. Управление состоянием в ASP.NET

    Если просмотреть HTML-код любой aspx-страницы, то можно обратить внимание, что внутри формы страницы находятся скрытые поля:

    <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
    <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTY1NDU2MTA1MmRkIrOULfk+GC2eXyao7O8emfNAp+4=" />

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

    ViewState используется для сохранения состояний между отправками страниц на сервер и обратно на клиент, и позволяет серверу понять, как восстановить страницу к прежнему виду и узнать, какие поля пользователь изменил на странице. Это не единственный механизм сохранения состояния, используемый в ADO.NET. Рассмотрим эти механизмы [14, 15].

    В табл. 6.3, табл. 6.4, табл. 6.5 приводится краткий сравнительный анализ всех доступных для управления состоянием опций.

    Сравнение опций для управления состоянием (часть 1)
    Состояние просмотра Строка запроса Специальные cookie-наборы
    Допустимые типы данных Все поддающиеся сериализации .NET-типы данных. Ограниченное количество строковых данных. Строковые данные.
    Место хранения Скрытое поле на текущей Веб-странице. Строка URL-адреса в браузере. Компьютер клиента (в памяти или небольшом текстовом файле, в зависимости от срока жизни данного cookie-набора).
    Срок жизни Сохраняется постоянно для отправки данных на одну страницу. Утрачивается, когда пользователь вводит новый URL-адрес или закрывает окно браузера, однако, может быть сохранена в ссылках. Срок жизни cookie-наборов определяется программистом. Они могут использоваться на нескольких страницах и могут сохраняться между посещениями.
    Контекст Ограничивается, но текущей страницей. Ограничивается целевой страницей Все ASP.NET -приложение целиком.
    Безопасность По умолчанию является незащищенным, хотя можно воспользоваться директивами Page и принудительно применить шифрование и хеширование. Доступна для просмотра и запросто может быть изменена пользователем. Никак не защищены и могут изменяться пользователем.
    Сложности, влияющие на производительность Хранение большого количества информации замедлит процесс передачи, но никак не отразится на производительности сервера. Никаких, потому что количество данных очевидно. Никаких, потому что количество данных очевидно.
    Обычно применяется для: Для настройки параметров конкретной страницы. Для отправки идентификационного номера продукта со страницы каталога на страницу подробностей. Для определения персонализированных предпочтений на Веб-сайте
    Сравнение опций для управления состоянием (часть 2)
    Состояние сеанса (Session) Состояние приложения (Application)
    Допустимые типы данных Все поддающиеся сериализации .NET-типы данных. Не поддающиеся сериализации типы поддерживаются, если используется внутрипроцессная служба состояний. Все .NET-типы данных.
    Местонахождение хранилища/Место хранения данных В памяти сервера В памяти сервера.
    Время жизни Истекает по прошествии предопределенного периода времени (который, как правило, длится 20 минут, но может быть изменен глобально или программно). Совпадает со сроком жизни приложения (который обычно длится до перезагрузки сервера).
    Контекст Все ASP.NET -приложение. Все ASP.NET -приложение. В отличие от большинства других типов методов, данные приложения являются глобальными для всех пользователей.
    Безопасность Является безопасным/защищенным, потому что данные никогда не передаются клиенту. Однако, подвержено атакам типа перехвата сеанса, если не используется SSL. Является очень безопасным, потому что данные никогда не передаются клиенту.
    Сложности, влияющие на производительность Сохранение большого количества информации может значительно замедлить работу сервера, особенно в случае, когда к нему подключается одновременно большое количество пользователей, потому что для каждого пользователя будет создаваться отдельная копия данных сеанса. Сохранение большого количества информации может замедлить работу сервера, потому что срок жизни этих данных никогда не будет заканчиваться, и они и никогда не будут удаляться.
    Обычно применяется: Для хранения элементов в "корзине для покупок". Для хранения глобальных данных любого типа.
    Сравнение опций для управления состоянием (часть 3)
    Профили Кэширование
    Допустимые типы данных Все поддающиеся сериализации .NET-типы данных. Не поддающиеся сериализации типы поддерживаются, если создается специальный профиль. Все .NET-типы данных.
    Местонахождение хранилища/место хранения данных В конечной базе данных В памяти сервера.
    Срок жизни Постоянный Зависит от применяемой вами политики истечения сроков, но может оканчиваться раньше, если серверу перестает хватать ресурсов памяти.
    Контекст Все ASP.NET -приложение. К ним также могут доступ и другие приложения. Тот же, что и состояния приложения (глобальный для всех пользователей и всех страниц).
    Безопасность Являются довольно безопасными, потому что хотя данные и никогда не передаются клиенту, они хранятся в базе данных, которая может быть "взломана". Является достаточно безопасным, потому что данные никогда не передаются клиенту.
    Сложности, влияющие на производительность Позволяют легко сохранять большое количество данных, но не исключают возникновение нетривиальных непроизводительных издержек при извлечении и записи данных для каждого запроса. Сохранение большого количества информации может привести к вытеснению другой более полезной, находящейся в кэше информации. Однако, ASP.NET имеет возможность удалять элементы заблаговременно для гарантии оптимальной производительности.
    Обычно применяется: Для хранения информации об учетной записи пользователя. Для хранения данных, извлекаемых из базы данных.

    6.2.3. Состояние просмотра ViewState

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

    Как и в основе большинства опций для управления состоянием в ASP.NET, в основе состояния просмотра лежит коллекция типа словаря, где каждый элемент индексируется с помощью уникального строкового имени. Например:

    ViewState["CurrentPage"] = 3;

    Этот код помещает в коллекцию ViewState значение 3 (или, скорее, целое число, которое содержит значение 3) и присваивает ему описательное имя CurrentPage. Если в коллекции ViewState на текущий момент нет элемента с именем CurrentPage, в нее будет автоматически добавлен такой новый элемент. Если элемент с таким именем уже существует, он будет заменен.

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

    Ниже показан код, который извлекает значение CurrentPage и преобразовывает его в целое число:

    int counter;
    if (ViewState["CurrentPage"] != null)
    {
       counter = (int)ViewState["CurrentPage"];
    }

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

    6.2.3.1. Сохранение объектов в состоянии просмотра

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

    Чтобы сделать объекты пригодными для сериализации, следует просто добавить перед объявлением соответствующего класса атрибут Serializable. Например, ниже показан чрезвычайно простой класс BookPage:

    [Serializable]
    public class BookPage
    {
       public int PageNamber;
       public string Text;
       
       public BookPage(int pageNamber, string text)
       {
          PageNamber = pageNamber;
          Text = text;
       }
    }

    Поскольку класс BookPage помечен как пригодный для сериализации/поддающийся сериализации, он может быть сохранен в состоянии просмотра:

    BookPage page = new BookPage (3, "Понедельник начинается в субботу");
    ViewState["CurrentPage"] = page;

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

    BookPage cust = (BookPage)ViewState["CurrentPage"];

    Чтобы класс поддавался сериализации, он должен отвечать следующим требованиям:

  • он должен иметь атрибут Serializable ;
  • все порождаемые от него классы тоже должны иметь атрибут Serializable ;
  • все индивидуальные переменные этого класса должны представлять собой поддающиеся сериализации типы данных, а все не поддающиеся сериализации типы данных должны сопровождаться атрибутом NonSerialized (во время процесса сериализации они будут просто игнорироваться).
  • 6.2.3.2. Оценивание преимуществ использования состояния просмотра

    Применение состояния просмотра является идеальным вариантом, потому что не предполагает использования никаких ресурсов памяти сервера и появления случайных ограничений (типа таймаута). Но есть и некоторые причины, когда состояние просмотра лучше не применять:

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

  • Когда этот элемент управления никогда не изменяется. Например, кнопка со статическим текстом не нуждается в состоянии просмотра.
  • Когда этот элемент управления заново заполняется данными после каждой отправки данных. Например, элемент управления типа надписи ( Label ), отображающий текущее время, значение для которого устанавливается в обработчике событий Page.Load, не нуждается в состоянии просмотра.
  • Когда этот элемент управления представляет собой элемент управления для ввода данных и изменяется только после того, как пользователь выполнит соответствующие действия. После каждой отправки данных ASP.NET будет заполнять такие элементы управления данными, используя введенные в форме значения. Это означает, что текст в текстовом поле или выбранный элемент в поле со списком не будут утрачиваться, даже если состояние просмотра не используется.
  • Чтобы отключить состояние просмотра для какого-нибудь одного элемента управления, необходимо установить для свойства EnableViewState этого элемента управления значение false. Чтобы отключить состояние просмотра для всей страницы и всех отображаемых на ней элементов управления, необходимо установить значение false для свойства EnableViewState этой страницы или используйте в директиве Page атрибут EnableViewState, как показано ниже:

    <%@ Page Language="c#" EnableViewState="false" ... %>

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

    6.2.4. Строка запроса

    Одним из самых серьезных ограничений состояния просмотра является то, что оно работает только на одной странице. Если пользователь переходит на другую страницу, сохраненная в нем информация утрачивается. Существует несколько способов решить эту проблему; то, какой из них будет наиболее подходящим, зависит от имеющихся требований.

    Наиболее распространенный подход – передавать информацию с помощью строки запроса в URL-адресе. Именно этот подход часто применяется в поисковых службах. Например, при выполнении поиска на Веб-сайте Google, пользователь будет перенаправлен на новый URL-адрес, включающий указанные им параметры поиска:

    http://www.google.ru/search?ie=UTF-8hl=ruq=evolutionredir_esc=yei=iRKRS5ndN5-inQOH96DTBg

    Строка запроса – это та часть URL-адреса, которая находится после вопросительного знака.

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

  • она может передавать информацию только в виде простых строк, которые должны содержать допустимые для использования в URL-адресе символы;
  • передаваемая с помощью строки запроса информация визуально доступна для пользователя и любого другого работающего в Интернете человека;
  • инициативный пользователь может решить изменить строку запроса и предоставить новые значения, которые программа никак не ожидает получить и от которых она не имеет защиты;
  • многие браузеры имеют ограничения касательно длины URL-адреса (которая, как правило, не должна превышать 1-2 КБ), поэтому в строку запроса нельзя поместить большое количество информации, и все равно придется выполнять проверку на совместимость с большинством браузеров.
  • И все-таки добавление информации в строку запроса является полезной технологией. Она особенно подходит для приложений баз данных, в которых пользователю отображается список элементов, соответствующих записям в базе данных (например, это может быть список продуктов): пользователь выбирает элемент, после чего он перенаправляется на другую страницу, содержащую детальную информацию о том элементе, который был им выбран. Один из наиболее простых способов реализовать такую схему – это заставить первую страницу отправлять идентификатор элемента второй странице. Вторая страница затем будет отыскивать этот элемент в базе данных и отображать детальную информацию о нем. Эта технология очень часть применяется на сайтах электронной коммерции, таких как Amazon.com.

    6.2.4.1. Использование строки запроса

    Чтобы сохранить информацию в строке запроса, ее придется сначала самостоятельно поместить туда. Как правило, это означает, что придется использовать специальный элемент управления HyperLink или оператор Response.Redirect(), подобный тому, который показан ниже:

    // Переходим на страницу products/default.aspx. 
    int categoryID = 10;
    Response.Redirect("products/default.aspx?category=" + recordID.ToString());

    Отправлять можно и несколько параметров, только тогда их следует разделять с помощью амперсанда ( ), как показано ниже:

    Response.Redirect("products/default.aspx?category=" + categoryID.ToString()+"subcategory="+subcategoryId.ToString());

    Получающей странице легче работать со строкой запроса. Она может получать значения из коллекции типа словаря QueryString, предоставляемой встроенным объектом Request, как показано ниже:

    string ID = Request.QueryString["category"];

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

    6.2.5. Cookie

    Специальные cookie-наборы – это еще один способ сохранить информацию для последующего использования. Cookie-наборы представляют собой небольшие файлы, которые создаются на жестком диске клиента (или, если они являются временными, в памяти Веб-браузера). Одним из преимуществ cookie-наборов является то, что они работают "прозрачно" и пользователь даже не знает о том, что эта информация должна быть сохранена. Они также могут запросто использоваться любой страницей в приложении и даже сохраняться между посещениями, что подразумевает действительно долгосрочное хранение. Они имеет те же недостатки, что и строки запросов. А именно: они могут хранить только простую строковую информацию, и пользователь запросто может получить к ним доступ и просмотреть их, отыскав и открыв соответствующий файл. Эти факторы делают их неподходящим вариантом, когда требуется сохранить сложную или секретную информацию или просто большие объемы данных.

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

    Прежде чем использовать cookie-наборы, следует импортировать пространство имен System.NET, которое позволяет работать с соответствующими типами, как показано ниже:

    using System.Net;

    В использовании cookie-наборов в принципе нет ничего особого сложного. Коллекцию Cookies предоставляют два объекта: объект Request и объект Response (оба из которых предоставляются через свойства объекта Page ). Главное запомнить следующее: извлекать cookie-наборы следует из объекта Request, а устанавливать их следует с помощью объекта Response.

    Чтобы установить cookie-набор, необходимо создать новый объект System.Net.HttpCookie. Затем, необходимо заполнить его строковой информацией и присоединить его к текущему Веб-ответу, как показано ниже:

    // Создаем объект cookie
    HttpCookie cookie = new HttpCookie("Language");
    // Устанавливаем в нем значение
    cookie["LanguagePref"] = "English";
    // Добавляем его в текущий Веб-ответ
    Response.Cookies.Add(cookie);

    Cookie-набор, добавленный таким образом, будет сохраняться до тех пор, пока пользователь не закроет окно браузера, и будет отправляться вместе с каждым запросом. Чтобы создать cookie-набор с более длинным сроком хранения, необходимо установить дату истечения срока, как показано ниже:

    // Этот cookie будет оставаться действительным в течение одного года.
    cookie.Expires = DateTime.Now.AddYears(1);

    Извлекаются cookie по имени с помощью коллекции Request.Cookies, как показано ниже:

    HttpCookie cookie = Request.Cookies["Language"];
    // Проверяем, был ли найден cookie с таким именем.
    // Это хорошая мера предосторожности, потому что пользователь может отключить поддержку cookie's, 
    //а в таком случае cookie не будет существовать.
    string language;
    if (cookie != null)
    {
       language = cookie["LanguagePref"];
    }

    Единственный способ удалить cookie – это заменить его на cookie-набор, дата истечения срока хранения которого уже прошла. Следующий фрагмент кода демонстрирует, как это можно сделать:

    HttpCookie cookie = new HttpCookie("LanguagePref");
    cookie.Expires = DateTime.Now.AddDays(-1);
    Response.Cookies.Add(cookie);

    6.2.6. Использование Session

    Состояние сеанса (Session) – это самая сложная технология управления состояниями. Она позволяет сохранять информацию на одной странице и затем получать к ней доступ с другой страницы, а также поддерживает объекты любого типа, включая специальные, создаваемые самим разработчиком, типы данных. Лучше всего то, что состояние сеанса использует тот же основанный на коллекциях синтаксис, что и состояние просмотра. Единственное отличие – имя встроенного свойства страницы, которое в данном случае выглядит так: Session.

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

    6.2.6.1. Архитектура сеанса

    Управление сеансом не является частью HTTP-стандарта. Поэтому ASP.NET приходится выполнять некоторую дополнительную работу, чтобы отследить информацию сеанса и привязать ее к соответствующему ответу.

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

    Рассмотрим, как ASP.NET хранит данные в сессии.

    Когда ASP.NET обрабатывает HTTP-запрос, тот проходит через конвейер различных модулей, которые могут реагировать на события приложения. Одним из модулей в этой цепочке является модуль SessionStateModule (который находится в пространстве имен System.Web.SessionState ). Этот модуль генерирует идентификатор сеанса, извлекает из внешних поставщиков состояния данные сеанса и затем привязывает эти данные к контексту вызовов запроса. Он также сохраняет данные состояния сеанса, когда обработка страницы завершается. Однако важно понимать, что модуль SessionStateModule фактически не хранит данные сеанса. Вместо этого, состояние сеанса сохраняется во внешних компонентах, которые называются поставщиками состояния. Весь этот процесс показан на рис. 6.4.

    (рис 6.4) Архитектура состояния сеанса в ASP.NET

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

    6.2.6.2. Использование состояния сеанса

    Взаимодействовать с состоянием сеанса можно используя класс System.Web.SessionState.HttpSessionState, который на Веб-странице ASP.NET доступен в виде встроенного объекта Session. Синтаксис для добавления элементов в эту коллекцию и их извлечения выглядит практически точно так же, как и синтаксис, который используется для добавления элементов в состояние просмотра страницы.

    Например, сохранить объект DataSet в памяти сеанса можно следующим образом:

    Session["ds"] = ds;

    После этого, его можно извлечь с помощью соответствующей операции преобразования:

    ds = (DataSet)Session["ds"];

    Контекст состояния сеанса охватывает все приложение и является глобальным для текущего пользователя. Состояние сеанса утрачивается в следующих случаях:

  • если пользователь закрывает и заново запускает браузер;
  • если пользователь получает доступ к той же странице через другое окно браузера при сохранении доступа к Веб-странице из исходного окна браузера (разные браузеры ведут себя по-разному в такой ситуации);
  • если сеанс завершается из-за отсутствия активности со стороны пользователя (по умолчанию сеанс автоматически завершается после 20 минут простоя);
  • если программист завершает сеанс, вызывая метод Session.Abandon().
  • В первых двух случаях, сеанс фактически остается в памяти, потому что Веб-сервер не имеет ни малейшего понятия о том, что клиент закрыл или сменил окно браузера. Сеанс будет находиться в памяти, оставаясь недоступным, до тех пор, пока, в конце концов, не истечет срок его действия.

    6.2.6.3. Поставщики состояния сеанса

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

    6.2.6.3.1. Off

    Установка значения Off приводит к отключению функции управления состоянием сеанса для всех страниц в приложении. Это может немного повысить производительность Веб-сайтов, которые не используют состояние сеанса.

    6.2.6.3.2. InProc

    Установка значения InProc напоминает подход, который использовался для хранения состояния сеанса в классической версии ASP. Это значение указывает ASP.NET хранить информацию в текущем домене приложения, что обеспечивает наилучшую производительность, но наименьший срок службы: если администратор перезапустит сервер, данные состояния будут утрачены.

    Значение InProc используется по умолчанию и подходит для большинства Веб-сайтов небольшого размера. Однако в сценарии с группой серверов от него не будет никакого толку. Сделать так, чтобы состояние сеанса могли совместно использовать сразу несколько серверов, можно только воспользовавшись внепроцессным поставщиком или службой состояний SQL Server. Еще одна причина, по которой установка значения InProc может быть нежелательной, состоит в том, что оно подразумевает создание более "хрупких" сеансов. В ASP.NET, домены приложений нередко создаются заново в ответ на различные операции типа изменения конфигурационных настроек или обновления страниц, а так же при достижении определенных пороговых значений (независимо от того, произошла ошибка или нет). Если будет обнаружено, что домен приложения часто перезапускается, что приводит к преждевременному завершению сеансов, можно попытаться устранить этот эффект, изменив те или иные параметры модели процесса, или воспользоваться другим более надежным поставщиком состояния сеанса.

    Прежде чем использовать внепроцессную модель (StateServer) или службу состояний SQL Server, придется принять во внимание следующие моменты:

  • Когда выбирается режим StateServer или SqlServer, сохраняемые в состоянии сеанса объекты должны допускать сериализацию. Иначе ASP.NET не сможет передавать их службе состояний или сохранять в базе данных.
  • Если ASP.NET обслуживает группа Веб-серверов, придется выполнить некоторые дополнительные конфигурационные шаги для гарантии того, что все Веб-серверы будут работать синхронно. Иначе, не исключено, что один сервер будет кодировать информацию не так, как другой, а это, несомненно, приведет к появлению проблем, если во время сеанса пользователь будет перенаправляться от одного сервера к другому (решением этой проблемы является изменение раздела <machineKey> файла machine.config так, чтобы он был одинаковым на всех серверах).
  • Если не используется внутрипроцессный поставщик состояния, событие SessionStateModule.End не будет инициироваться, и все обработчики этого события в файле global.asax или HTTP-модуле будут игнорироваться.
  • 6.2.6.3.3. StateServer

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

    Выбрав режим StateServer, обязательно следует указать значение для параметра stateConnectionString. Эта строка сообщает TCP/IP-адрес компьютера, на котором запускается служба StateServer, и номер его порта (который определяется ASP.NET и который, как правило, не требуется изменять). Это позволяет обслуживать службу StateServer на другом компьютере. Если не изменить значение этого параметра, будет использоваться локальный сервер (адрес которого выглядит так: 127.0.0.1).

    6.2.6.3.4. SqlServer

    Это значение указывает ASP.NET использовать для хранения данных сеанса базу данных SQL Server, применяя параметры, определенные в атрибуте sqlConnectionString. Такой способ управления состоянием является самым удобным, но и пока что самым медленным. Чтобы его можно было использовать, на сервере должна быть установлена база данных SQL Server.

    Установка значения для атрибута sqlConnectionString выполняется по схеме, подобной той, что используется для получения доступа к данным ADO.NET. В целом это подразумевает указание источника данных (т.е. адреса сервера), имени пользователя и пароля, если только не используется интегрированная система безопасности SQL.

    Обычно база данных состояния всегда называется "ASPState". Поэтому строка подключения в файле web.config не отображает явно имя базы данных. Вместо этого, она просто отражает месторасположение сервера и тип аутентификации, который будет использоваться:

    <sessionState sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI" ... />

    При желании использовать другую базу данных (с такой же структурой), необходимо установить для атрибута allowCustomSqlDatabase значение true и убедиться в том, что строка подключения включает параметр Initial Catalog, указывающий имя базы данных, которую следует использовать:

    <sessionState allowCustomSqlDatabase="false" sqlConnectionString=
    "data source=127.0.0.1;Integrated Security=SSPI;Initial Catalog=CustDatabase"
    ... />

    Выбрав режим SqlServer, также можное установить значение для необязательного атрибута sqlCommandTimeout. Этот атрибут указывает максимальное количество секунд, в течение которых должен ожидаться ответ от базы данных, прежде чем запрос будет отменен. По умолчанию ему присваивается значение, равное 30 секундам.

    6.2.7. Ключевые термины

    ASP.NET, Жизненный цикл страницы, Управление состоянием, ViewState, Строка запроса, Cookies, Состояние сеанса.

    6.3. Принципы разработки пользовательского интерфейса Интернет-приложений

    Вопросы построения пользовательского интерфейса являются одними из самых важных в процессе разработки приложения [1]. В случае разработки Веб-приложения, они являются особенно актуальными, т.к. процесс создания пользовательского интерфейса здесь имеет ряд существенных отличий от традиционных Windows-приложений [15]. При построении Веб-приложения необходимо учитывать тот факт, что его интерфейс отображается в окне браузера, и, следовательно, ограничен его возможностями.

    Разработку пользовательского интерфейса Веб-приложения можно производить как с помощью редактирования исходного кода страницы, так и с использованием встроенного в Visual Studio визуального редактора. Наиболее эффективным способом является использование комбинированного метода, при котором в некоторых режимах редактирования целесообразно пользоваться визуальными средствами, в других же случаях – средствами редактирования исходного кода.

    Основной сложностью при разработке пользовательского интерфейса Веб-приложения является позиционирование его элементов. Существует четыре основных режима размещения элементов управления Веб-страницы:

  • Абсолютное позиционирование (absolutely positioned) – позволяет располагать элементы в точности там, куда их помещает разработчик. При этом элементы управления имеют абсолютное положение на странице.
  • Относительное позиционирование (relatively positioned) – очень похоже на абсолютное с той разницей, что позиция элемента задается относительно элемента, имеющего статическое расположение на странице.
  • Статическое позиционирование (statically positioned) – при котором положение элементов управления определяется относительно других элементов управления, размещенных на странице. При этом все элементы располагаются последовательно один за другим.
  • Без заданного атрибута позиционирования (no positioning attribute) – при котором редактором удаляется любая информация относительно позиционирования элемента управления. При этом используется статическое позиционирование.
  • Статическое позиционирование рекомендуется использовать в случае, когда расположенный на странице текст чередуется с элементами управления.

    При использовании абсолютного и относительного позиционирования Visual Studio добавляет специальные атрибуты, задающие положение элемента. В следующем примере показан фрагмент кода HTML, в котором описывается расположение трех кнопок с разными атрибутами позиционирования [16]:

    <asp:Button ID="Button1" runat="server" Style="z-index: 100; left: 436px; position: absolute;top: 187px" Text="Button1" />
    <asp:Button ID="Button2" runat="server" Style="left: 245px; position: relative; top: 266px" Text="Button2" />
    <asp:Button ID="Button3" runat="server" Style="position: static" Text="Button3" />

    Для элемента Button1 использовалось абсолютное позиционирование, для Button2 – относительное, Button3 – статическое (рис. 6.5).

    (рис 6.5) Перегрузка данных и обработка запроса

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

    Если сгруппировать HTML и серверные элементы управления, по видам задач программирования, можно получить табл. 6.6 [1, 17].

    Группировка HTML и серверных компонент
    Задача HTML элементы Серверные элементы
    Отображение текста Input (Text), Textarea Label, TextBox, Literal
    Отображение таблиц Table Table, DataGrid
    Выбор значения из списка Select DropDownList, ListBox, DataList, Repeater
    Исполнение команд Input (Button), Input (Reset), Input (Submit) Button, LinkButton, ImageButton
    Установка значений Input (CheckBox), Input (Radio) CheckBox, CheckBoxList, RadioButton, RadioButtonList
    Отображение графики Image Image, ImageButton
    Работа с датами Calendar
    Демонстрация рекламных изображений AdRotator
    Отображение горизонтальной линии Horizontal Rule Literal
    Получение файлов от клиентов Input (File) FileUpload
    Сохранение введенных на странице данных Input (Hidden) ViewState
    Проверка вводимых данных Страничные сценарии RequiredFildValidator, RangeValidator, RegularExpressionValidator, CompareValidator, CustomValudator, ValidationSummary

    6.3.1. Работа с текстом

    Одной из наиболее часто возникающих задач при создании Веб-приложения, является работа с текстом. Для этого существует несколько различных способов, начиная от Response.Write("Текст") и заканчивая использованием элемента Label или TextBox с установленным в True значением свойства ReadOnly.

    Рассмотрим небольшой пример, который переопределяет текст, отображаемый при помощи элемента Label, на текст, набранный пользователем в элемент TextBox. Для этого реализуем следующую страницу:

    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
            <br />
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            <br />
            <asp:Button ID="Button1" runat="server" Text="Button" OnClick="OnClick"/>
        </div>
        </form>
    </body>

    Как видно, изначально компонент Label1 отображает текст Label. Реализуем обработчик события OnClick кнопки так, чтобы она отображала в Label набранный пользователем текст:

    protected void OnClick(object sender, EventArgs e)
    {
        Label1.Text = TextBox1.Text;
    }

    Результат работы представлен на рис. 6.6.

    (рис 6.6) Смена выводимой надписи в элементе Label при нажатии на соответствующую кнопку

    6.3.2. Использование элементов CheckBox, CheckBoxList, RadioButton, RadioButtonList и BulletedList

    В ряде случаев необходимо принимать от пользователя булевые значения, для этих целей применяются элементы CheckBox, CheckBoxList, RadioButton и RadioButtonList. Элементы CheckBox и RadioButton отличаются тем, что CheckBox позволяет устанавливать значения одного или нескольких флажков одновременно, в то время как RadioButton – только одно значение. Окончание List говорит о том, что данный элемент управления представляет собой целый набор флажков, объединенных в группу. Группы флажков легче привязывать к источникам данных, поэтому их целесообразнее использовать в случае, если флажки должны отображать данные, находящиеся в БД, либо с помощью них данные должны вводиться в базу данных, либо если флажки логически связаны между собой.

    Для получения значений элементов управления CheckBox и RadioButton необходимо использовать свойство Checked. Например, в следующем коде осуществляется проверка значения флажка, которое выводится на экран:

    protected void Button1_Click(object sender, EventArgs e)
    {
    Response.Write("Флажок установлен в значение "+CheckBox1.Checked.ToString());
    }

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

    Для получения и установки значений элементов управления RadioButtonList и CheckBoxList необходимо последовательно опрашивать все элементы управления списка проверяя их значения. Для этого очень удобно использовать цикл For Each.

    В следующем примере последовательно проверяются значения всех флажков элемента CheckBoxList1. Если флажок выбран, на экран выводится соответствующее сообщение:

    protected void Button1_Click(object sender, EventArgs e)
    {
    foreach (ListItem l in CheckBoxList1.Items)
    {
          if (l.Selected)
                       Response.Write("выбран " + l.Text + "<br/>");
    }
    }

    Следует обратить внимание на тот факт, что элемент управления CheckBoxList, как и RadioButtonList содержит элементы управления ListControl, а не CheckBox или RadioButton, как можно было бы предположить.

    Аналогичным образом производятся проверки и для элемента RadioButtonList.

    BulletedList является аналогом HTML элементов, предназначенных для организации упорядоченных и неупорядоченных списков с помощью тэгов <ul> и <ol> соответственно, однако позволяет обращаться к списку программно. Для установки элементов, отображаемых в списке, необходимо ввести их с помощью средств, аналогичных рассмотренным ранее для CheckBoxList и RadioButtonList.

    Особенностью BulletedList является возможность настройки внешнего вида и типа элементов списка. Основные свойства этого элемента управления показаны в табл. 6.7.

    Свойства элемента BulletedList
    Свойство Описание
    BulletedStyle Позволяет задавать тип списка numbered – нумерованный, loweralpha – маленькие латинские буквы, upperalpha – большие латинские буквы, lowerroman – маленькие римские цифры, upperroman – большие римские цифры, disc, circle, square – символы маркеров
    BulletedStyleImageUrl Устанавливает изображение, расположенное слева от каждого элемента списка. Для установки изображения необходимо, чтобы значение BulletedStyle= CustomImage
    FirstBulletNumber Устанавливает значение для первого элемента списка, относительно которого в дальнейшем будет продолжена нумерация
    DisplayMode Устанавливает тип элемента списка ( Text, HyperLink, LinkButton )

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

    protected void BulletedList1_Click(object sender, BulletedListEventArgs e)
    {
    Response.Write("Вы щелкнули по элементу списка "+BulletedList1.Items[e.Index].ToString());
    }

    6.3.3. Использование Image, ImageButton

    Отображение графики на Веб-странице является абсолютно необходимым условием. ASP.NET предоставляет несколько возможностей отображения графики:

  • Как фон, заполняющий всю страницу, для этого можно воспользоваться свойством Background Веб-формы. Можно также использовать свойство BackImageUrl элемента Panel.
  • На переднем плане. Для этого используется элемент управления Image.
  • На кнопке, способной реагировать на действия пользователя. Для этого используется элемент управления ImageButton.
  • С помощью карты изображений, реализуемой посредством элемента управления ImageMap.
  • Элемент управления Image позволяет отображать графические изображения. При этом он неспособен реагировать на действия пользователя, однако способен отображать графические элементы в зависимости от действий, выполненных над другими элементами управления.

    В следующем примере при нажатии на соответствующую кнопку отображается изображение машины, мотоцикла либо велосипеда (рис. 6.7):

    protected void buttonCar_Click(object sender, EventArgs e)
    {
        Image1.ImageUrl = "~//Images//car.jpg";
    }
    protected void buttonBike_Click(object sender, EventArgs e)
    {
        Image1.ImageUrl = "~//Images//bike.jpg";
    }
    protected void buttonCycle_Click(object sender, EventArgs e)
    {
        Image1.ImageUrl = "~//Images//cycle.jpg";
    }
    (рис 6.7) Смена выводимого на экран изображения при нажатии на соответствующую кнопку

    Элемент управления ImageButton имеет встроенную возможность реагирования на события, совершаемые пользователем. При этом в обработчик события щелчка левой кнопкой мыши по нему отправляется специальный объект ImageClickEventArgs, предоставляющий свойства X и Y, которые определяют место изображения, на котором был совершен щелчок. Используя эти свойства, можно создать карту изображения. Ниже показан код, который отображает координаты точки, в которой был произведен щелчок мыши, а также определяет, в пределах какой фигуры он был произведен (рис. 6.8):

    protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
    {
        string strClickFigure="";
        if (!(e.X <= 380  e.X >= 20  e.Y <= 380  e.Y >= 20)) 
           strClickFigure = "рамка";
        if (e.X>=60  e.X<=210  e.Y>=60  e.Y<=210) 
           strClickFigure="квадрат";
        if ((e.Y>=495-e.X)  (e.Y>=e.X-45)  e.Y<=332) 
           strClickFigure="треугольник";
        Label1.Text = "Вы щелкнули в точке Х="+e.X.ToString()+"; 
        Y="+e.Y.ToString()+" это "+strClickFigure;
    }
    (рис 6.8) Пример использования элемента ImageButton

    6.3.4. Использование Literal и HiddenField

    Элемент управления Literal представляет собой один из способов вывода информации на экран. Literal можно использовать в качестве контейнера для размещения HTML элементов на странице. Чаще всего его используют для динамического добавления текста. Схожие возможности по добавлению текста предоставляет элемент Label, Literal отличается от него тем, что не добавляет дополнительных HTML элементов к тексту. Label, например, размещает текст внутри тэга <span>, Panel – внутри <div> и т.д. Размещение элементов внутри тэгов создает возможность для поддержки ими стилей оформления, Literal же, не имеет такой возможности. Рекомендуется использовать элемент Literal в том случае, когда необходимо размещать текст на странице без использования дополнительной разметки, либо в том случае, когда существует HTML текст (например, хранящийся в файле или базе данных), содержащий форматирование с использованием тэгов, и его необходимо вывести на экран.

    Самым важным свойством элемента управления Literal является Mode. Возможны три значения этого свойства (табл. 6.8).

    Значения свойства Mode элемента управления Literal
    Значения Описание
    Transform Любая разметка, добавляемая к элементу управления, преобразуется таким образом, чтобы максимально удовлетворять особенностям протокола браузера, запрашивающего страницу.
    PassThrough Добавляемая к элементу управления разметка передается браузеру как есть, без каких-либо модификаций.
    Encode Добавляемая к элементу управления разметка декодируется с использованием метода HtmlEncode, преобразующего HTML представление страницы в текст.

    Например, при использовании следующего примера элемента Literal могут быть получены различные результаты.

    При использовании значения Mode=PassThrough, как показано в следующем фрагменте исходного кода:

    private string s = 
    "<input id='Button1' type='button' value='Добавить' /><br/>
          <table border='1' cellpadding='1' cellspacing='0'>
            <tr>
              <td>Идентификатор</td>
              <td>наименование</td>
              <td>кол-во</td>
            </tr>
            <tr>
              <td>1</td>
              <td>Велосипед горный</td>
              <td>10</td>
            </tr>
            <tr>
              <td>2</td>
              <td>Велосипед дорожный</td>
              <td>50</td>
            </tr>
          </table>";
    protected void Page_Load(object sender, EventArgs e)
    {
        Literal1.Mode = LiteralMode.PassThrough;
        Literal1.Text = s;
    }

    будет получен результат, изображенный на рис. 6.9.

    (рис 6.9) Использование Literal для отображения информации в режиме PassThrough

    А при использовании режима Encode результат, изображенный на рис. 6.10.

    (рис 6.10) Использование Literal для отображения информации в режиме Encode.

    Элемент управления HiddenField целесообразно использовать в том случае, когда на странице необходимо сохранить какие-то данные, но не отображать их. Например, это может быть какая-нибудь информация о пользователе, которая необходима для выполнения сервисных функций.

    У элемента HiddenField существует лишь одно свойство, заслуживающее внимания. Это Value, посредством которого ему и присваивается значение.

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

    6.3.5. Использование Panel

    Элемент управления Panel (при рендеренге страницы заменяется на div ) используется для группирования элементов управления. При этом он выступает в качестве контейнера, способного вмещать в себя различные другие элементы управления, манипулирование которыми становится возможным как единым целым. Например, возможно скрытие или показ элемента Panel со всеми входящими в него элементами путем задания значения свойства Visible равным true или false.

    При размещении внутри Panel элементов для ввода текста и кнопок, становится возможным определение кнопки, используемой по умолчанию. Это означает, что при вводе текста в элементы управления, размещенные внутри Panel, пользователь имеет возможность нажать кнопку Enter, что будет равносильно щелчку левой кнопки мыши по кнопке, указанной в свойстве DefaultButton элемента Panel. Это позволяет создавать более эффективные пользовательские формы для ввода данных.

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

  • С помощью Panel можно создать область, содержащую полосы прокрутки. Для этого достаточно установить соответствующее значение свойства ScrollBars, а также установить необходимые значения свойств Height и Width.
  • С помощью (рис 6.11) Пример изображения группы элементов

    Следует отметить, что при установке свойства GroupingText становится невозможным использование полос прокрутки.

  • С помощью Panel можно создать область страницы, имеющей отдельно заданные свойства, такие как цвет фона, рамка и т.д.
  • 6.3.7. Использование LinkButton

    Элемент управления LinkButton представляет собой кнопку, которая выглядит как гиперссылка, но имеет поведение кнопки. Этот элемент управления внедряет в HTML код страницы элементы JavaScript, необходимые для обработки событий кнопки, поэтому необходимо, чтобы клиентский браузер поддерживал JavaScript.

    LinkButton может быть двух разновидностей: командная кнопка и кнопка перенаправления. Кнопка перенаправления не содержит сопоставленного с ней обработчика события и просто инициирует событие postback. Командная кнопка ведет себя как обычная кнопка и может иметь несколько обработчиков событий, сопоставленных с ней. Как и обычная кнопка, она может реагировать на щелчок левой кнопки мыши с помощью события LinkButton_Click, кроме того, возможна обработка события LinkButton_Command. В качестве аргументов, обработчику события Command передаются значения свойств CommandName и CommandArgument. С помощью этого события становится возможным определение того, какая из нескольких, расположенных на странице кнопок была нажата.

    В следующем примере на странице размещены два элемента LinkButton:

    <asp:LinkButton ID="LinkButton1" runat="server" CommandName="Открыть" 
          CommandArgument="c:\1.txt" OnCommand="LinkButton_Command"> Открыть 
    </asp:LinkButton>
    <asp:LinkButton ID="LinkButton2" runat="server" 
          CommandArgument= "http://www.yandex.ru" CommandName="Перейти" 
          OnCommand="LinkButton_Command"> Перейти</asp:LinkButton>

    Процедура LinkButton_Command выводит на экран сообщение, в котором указаны аргументы, передаваемые обеими кнопками в случае их нажатия:

    protected void LinkButton_Command(object sender, CommandEventArgs e)
    {
        Response.Write("Команда: " + e.CommandName + ", параметр: " +
        e.CommandArgument);
    }

    6.3.8. Ключевые термины

    Пользовательский интерфейс.

    6.4. Краткие итоги

    Платформа .NET Framework – это интегрированный компонент Windows, который поддерживает создание и выполнение нового поколения приложений и Веб-служб XML.

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

    Библиотека классов FCL (Framework Class Library) открывает доступ к системным функциям, включая и те, что прежде были доступны только через API Windows, а также к прикладным функциям для Веб-разработки ( ASP.NET ), для доступа к данным (ADO.NET), обеспечения безопасности и удаленного управления.

    ASP.NET – это платформа для создания Веб-приложений и Веб-сервисов, работающих под управлением IIS.

    При выполнении страницы ASP.NET осуществляется ее жизненный цикл, во время которого исполняется ряд шагов обработки, такие как: инициализация, определение элементов управления, восстановление и поддержание рабочего состояния, выполнение кода обработчика событий, а также отрисовка.

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

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

    Возврат информации серверу осуществляется с помощью механизма состояний просмотра (состояние вида, ViewState ).

    Существует несколько способов сохранения состояния просмотра:

  • строка запроса в URL-адресе;
  • cookie;
  • состояние сеанса (Session).
  • Основной сложностью при разработке пользовательского интерфейса Веб-приложения является позиционирование его элементов.

    Для создания пользовательского интерфейса Веб-приложения возможно использование как серверных, так и HTML элементов управления.

    Одной из наиболее часто возникающих задач при создании Веб-приложения, является работа с текстом.

    В ряде случаев необходимо принимать от пользователя булевые значения, для этих целей применяются элементы CheckBox, CheckBoxList, RadioButton и RadioButtonList.

    ASP.NET предоставляет несколько возможностей отображения графики.

    Элемент управления Literal представляет собой один из способов вывода информации на экран.

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

    Элемент управления Panel используется для группирования элементов управления.

    Элемент управления LinkButton представляет собой кнопку, которая выглядит как гиперссылка, но имеет поведение кнопки.

    Вернуться к учебному плану