Сообщений 6    Оценка 90        Оценить  
Система Orphus

Создание приложений ASP.NET 2.0

Глава из книги “Знакомство с MS ASP.NET 2.0”

Автор: Д. Эспозито
Источник: Знакомство с MS ASP.NET 2.0
Материал предоставил: Издательство "Питер"
Опубликовано: 29.06.2006
Исправлено: 01.07.2006
Версия текста: 1.0
Начало работы с Visual Studio 2005
Недостатки Visual Studio .NET 2003
Отличительные черты Visual Studio 2005
Создание Web-сайта
Проектирование Web-форм
Добавление кода к Web-формам
Локальный Web-сервер
Специальные папки в приложениях ASP.NET 2.0
Модель смежного кода
Эволюция модели отделенного кода
Компиляция по требованию для всех ресурсов
Совместное использование исходного кода компонентов
Объектная модель страницы
Что нового в классе Page
Программирование страницы
Объектная модель сценариев страницы
Обзор серверных элементов управления
Новые возможности элементов управления
Новые базовые элементы управления
Заключение

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

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

Ключевой инструмент разработки приложений ASP.NET 2.0 — Microsoft Visual Studio 2005 — преемница Visual Studio .NET 2003. Она содержит массу новых возможностей и усовершенствований, разработанных специально для того, чтобы позволить Web-программистам преодолеть некоторые ограничения, возникавшие при использовании Visual Studio .NET 2003.

В этой главе мы рассмотрим три основных элемента приложения ASP.NET — среду разработки (IDE) для его построения, страницу и основные элементы управления для ее создания. Начнем с Visual Studio 2005.

Начало работы с Visual Studio 2005

Visual Studio 2005 — это среда-контейнер, объединяющая функциональность нескольких визуальных дизайнеров. Один дизайнер служит для создания приложений на основе Windows Forms, один — для создания ASP.NET-сайтов, еще один — для Web-сервисов и т. д. Visual Studio .NET 2003 использовала единственную модель для разработки приложений — проектно-ориентированный подход. Однако в реальности такой подход оказался не лучшим вариантом — во всяком случае, для ASP.NET и Web-приложений.

Недостатки Visual Studio .NET 2003

В Visual Studio .NET 2003 приложения создаются в соответствии с концепцией проекта, представляющего собой логическую сущность, порождающую любое приложение — будь то Windows Forms, Web, консольная программа или Web-сервис. Разработчики строят приложение, создавая новый проект, настраивая его, а затем до- бавляя страницы, Web-сервисы, классы и управляющие элементы. В терминах реализации проект представляет собой XML-файл, объединяющий несколько файлов и каталогов. Что касается Web-приложений, проект Visual Studio требует наличия виртуального каталога Microsoft Internet Information Services (IIS), а кроме того имеет и другие существенные недостатки. Хотя разработчики вполне успешно применяют Visual Studio .NET для создания реальных приложений, этот инструмент нельзя назвать идеальным для относительно простых проектов.

ПРИМЕЧАНИЕ

Microsoft также предлагает Web Matrix — свободно распространяемый, поддерживаемый на общественных началах инструмент для разработки приложений ASP.NET. Web Matrix реализует большую часть функциональности современных редакторов кода, например, подсветку синтаксиса, дизайнеры WYSIWYG, различные представления кода. В отличие от Visual Studio .NET работа Web Matrix строится вокруг отдельной страницы ASP.NET. Инструмент поддерживает только страницы со встроенным кодом и позволяет разрабатывать приложения в виде набора отдельных страниц и ресурсов.

Один из недостатков заключается в том, что Visual Studio .NET требует применения Microsoft FrontPage Server Extensions (FPSE) и не поддерживает FTP, локальную файловую систему или прямой доступ к IIS. Кроме того, она зависит от IIS, который должен быть установлен на машине программиста или на сервере разработки. Эти ограничения оказывают гораздо большее влияние на процесс разработки, чем кажется. Отладка конфигураций и сценариев представляет большие сложности, для создания новых проектов разработчикам нужны административные привилегии, кроме того, необходимо определить эффективную корпоративную политику безопасности применительно к машинам программистов.

В Visual Studio .NET 2003 файл проекта — единственный пункт управления всеми компонентами приложения. В результате для того, чтобы файл стал составной частью проекта, вы должны явно добавить его в проект и сконфигурировать — вы не можете просто указать на существующий виртуальный каталог и считать дело сделанным. Информация, закодированная в файле проекта, имеет большее значение, чем действительное содержимое каталога, что приводит к появлению забытых и ненужных файлов, болтающихся в каталоге сайта. Синхронизация сотен файлов в большом приложении — нелегкая задача, а развертывание проектов на других машинах может доставить еще больше хлопот. Кроме того, Visual Studio .NET не умеет взаимодействовать с IIS и не позволяет просматривать и редактировать виртуальные корневые каталоги.

Однако проблема номер один при разработке Web-приложений с помощью Visual Studio .NET заключается в невозможности открыть отдельную страницу вне проекта. Вы, конечно, можете открыть и отредактировать страницу, но IntelliSense работать не будет; то же случится и с другими ключевыми возможностями, такими как выполнение и отладка страниц. Честно говоря, в этом случае Visual Studio .NET имеет только одно преимущество перед Notepad — подсветку синтаксиса HTML.

Отличительные черты Visual Studio 2005

Visual Studio 2005 предоставляет более простой и дружественный способ создания приложений Web Forms. Существенные улучшения коснулись всех недоработок, упомянутых ранее. Давайте коротко рассмотрим новую функциональность.

Visual Studio 2005 позволяет работать с Web-сайтами различными способами. В дополнение к использованию FrontPage Server Extensions вы можете обращаться к исходным файлам с помощью FTP или указав непосредственный путь в файловой системе. Вы также можете напрямую обращаться к локальному IIS и просматривать существующую иерархию виртуальных каталогов. Вы получаете доступ к существующим виртуальным корневым каталогам и можете создавать новые. IIS больше не является необходимым требованием для функционирования инструментов разработки. Как и Web Matrix, Visual Studio 2005 поставляется вместе с локальным Web-сервером, что делает наличие IIS необязательным, по крайней мере, для целей отладки и тестирования.

Этот локальный Web-сервер представляет собой переработанную версию Cassini — бесплатного Web-сервера, изначально поставлявшегося вместе с Web Matrix. Локальный Web-сервер используется по умолчанию, если только вы явно не откроете проект из существующего виртуального каталога IIS. Вы можете открывать свой Web-сайт, указывая путь в файловой системе или виртуальный каталог IIS. В первом варианте для тестирования сайта будет применяться локальный Web-сервер.

Взаимодействие с IIS значительно упрощено. При попытке открыть Web-сайт вам предлагается несколько вариантов. Вы можете указать местонахождение проекта, задав путь в файловой системе, используя иерархию виртуальных каталогов IIS (только в случае локального IIS), используя FTP или просто введя URL сайта, сконфигурированного с помощью FrontPage Server Extensions. На вкладке IIS также находятся кнопки для создания новых виртуальных каталогов и приложений.

Visual Studio 2005 не компилирует все содержимое сайта в сборку, как это делает Visual Studio .NET 2003. Вместо этого используется механизм динамической компиляции ASP.NET. Этот механизм позволяет сразу же подхватывать изменения не только в файлах .aspx, но и в файлах .cs или .vb, что достигается благодаря особой разновидности динамической компиляции классов отделенного кода (code-behind classes).

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

И, наконец, если вы дважды щелкните файл .aspx в Проводнике, запустится Visual Studio 2005 и предложит отредактировать исходный код. В отличие от Visual Studio .NET 2003 IntelliSense работает прекрасно, а страницу можно просмотреть во встроенном браузере с помощью локального Web-сервера. IntelliSense работает везде, даже в выражениях связывания с данными и директивах страницы.

Создание Web-сайта

Давайте создадим демонстрационный Web-сайт с помощью Visual Studio 2005. Новый Web-сайт можно создать, выбрав пункт меню File | New, а затем Web Site. Появившееся диалоговое окно предлагает выбрать тип сайта, который вы хотите создать. Обратите внимание на два похожих варианта: ASP.NET Web Site и ASP.NET Internet Site.

Если вы выберете пункт Web Site, Visual Studio сгенерирует минимальное число файлов, необходимых для создания Web-сайта. В сущности, будут созданы страница default.aspx и пустой каталог Data. Если же вы укажете вариант Internet Site, то будет задействован стартовый набор ASP.NET — образец персонального Web-сайта с некоторыми встроенными стандартными возможностями. Давайте выберем вариант под названием Web Site.

ПРЕДУПРЕЖДЕНИЕ

Visual Studio 2005 создает файл проекта, но не использует его для отслеживания всех файлов, входящих в приложение. Корневой каталог сайта сам неявно определяет Web-проект. Для добавления к проекту нового файла его надо просто скопировать или создать в этом каталоге, и он тут же появится в проекте. Если этого не происходит, щелкните правой кнопкой в Solution Explorer и выберите Refresh Folder.

Для редактирования Web-страницы можно выбрать одно из трех представлений —Design, Source и Server Code. Режим Design показывает HTML-страницу, позволяя выбирать и редактировать управляющие и статические элементы, а также предоставляет возможность предварительного графического просмотра страницы. Режим Source показывает разметку HTML вместе со встроенным кодом, используя при этом такие богатые возможности, как подсветку синтаксиса, IntelliSense, подсказки и автозавершение. Режим Server Code показывает только встроенный код, если он есть. Хорошая новость: теперь Visual Studio поддерживает подсветку синтаксиса и встроенного кода.

Выберем в меню шаблон элемента, который будем добавлять к нашему сайту.

Обратите внимание на два флажка в нижней части окна. Вы можете указать, что хотите сохранить код страницы в отдельном файле (подобно модели отделенного кода в Visual Studio .NET 2003), а также можете связать данную страницу с эталонной (master page). (Эталонные страницы — новое крутое средство ASP.NET 2.0, которое мы подробно обсудим в следующей главе.) Схема отделенного кода, усиленно рекламируемая в Visual Studio .NET 2003, была существенно пересмотрена и доработана. В результате страницы, созданные в Visual Studio 2005, не обязаны разбиваться на файлы .aspx и .cs. Теперь разделение кода не является обязательным, хотя и поддерживается в полной мере.

Добавим HTML-код для создания страницы Hello, World. Как минимум, нам нужно текстовое поле для ввода сообщения и кнопка, чтобы послать его всему миру. Следующий HTML-код формирует страницу:

<% @Page language="C#" %>
<script runat="server">
void Send_Click(object sender, EventArgs e)
{
    MsgSent.Text = Msg.Text;
}
</script>

<html>
<head runat="server">
    <title>Hello, World</title>
</head>
<body>
    <form runat="server" id="MainForm">
        <h1>Send a message to the world</h1>
        <asp:textbox runat="server" id="Msg"
           text="Hello, ASP.NET 2.0" />
        <asp:button runat="server" id="Send" text="Send" 
                    onclick="Send_Click" />
        <hr />
        <b>Last message sent: </b>
        <asp:label runat="server" id="MsgSent" Font-Italic="True" /> 
        <hr />
    </form>
</body>
</html>
ПРИМЕЧАНИЕ

Как уже говорилось, вы можете открывать существующие Web-сайты при помощи протокола FTP, а затем создавать и редактировать там файлы. Вам понадобится доступ к FTP-серверу и разрешение на чтение и запись в конкретном FTP-каталоге. Каталог должен существовать заранее, поскольку Visual Studio 2005 не может создать новый Web-сайт по FTP.

Проектирование Web-форм

Заполнение страницы Web Forms также не составляет труда. Вы перетаскиваете управляющие элементы из окна инструментария на форму, передвигаете их и конфигурируете их свойства. Если нужно, вы можете переключиться в режим Source и вручную отредактировать разметку HTML так, как вам больше нравится. Приятным сюрпризом для многих разработчиков будет возможность перетаскивания элементов прямо в окно Source с исходным кодом, при этом вместо графического представления элемента вы увидите соответствующий HTML. Кроме того, вы можете редактировать свойства серверного элемента управления, как выбирая его в режиме проектирования Design, так и выделяя соответствующий HTML в режиме просмотра исходного кода Source.

Одной из первых вещей, обращающих на себя внимание в Visual Studio 2005, является сохранение форматирования кода HTML при переключении между режимами. Любые исправления в режиме про-ектирования затрагивают только измененные элементы. Средства автоматического форматирования, которые Visual Studio .NET 2003 задействовала при изменении представлений, теперь отключены.

В Visual Studio 2005 улучшен механизм верификации HTML по сравнению с более старыми инструментами. Этот механизм позволяет убедиться, что создаваемый HTML-код подходит для текущего целевого браузера. Этот браузер указан внизу окна редактирования, и его значение по умолчанию установлено в Microsoft Internet Explorer 6.0. Когда вы вводите недопустимый или неправильный тэг, IDE обнаруживает несовместимость и предупреждает о ней. Тем не менее, это средство все равно позволяет вводить неправильный код.

Количество целевых клиентских браузеров в ASP.NET 2.0 значительно расширено и варьируется от Internet Explorer 6.0 до HTML 3.2 (используемого в Internet Explorer 3.x и Netscape Navigator 3.x). К другим целевым клиентам относятся мобильные схемы (Compact HTML 1.0 и мобильный HTML 3.2), Netscape 4.0 и XHTML 1.0 Transitional schema. Последняя схема используется в таких браузерах, как Netscape 7.0 и Opera 7.0.

Добавление кода к Web-формам

Как подключить серверный код к различным HTML-элементам на странице .aspx? Чтобы выяснить это, поместите на форму кнопку и дважды ее щелкните. Visual Studio переключится в режим Server Code и создаст пустой обработчик для используемого по умолчанию события элемента. Для кнопки это событие Click:

void Send_Click(object sender, EventArgs e)
{
    .
    .
    .
}

Разметка HTML модифицируется автоматически — добавляется новый атрибут onclick:

<asp:button runat="server" id="Send" 
     text="Send" 
     onclick="Send_Click" />

Обратите внимание: в отличие от Visual Studio .NET 2003 новая версия автоматически не встраивает в страницу код регистрации обработчика события. Присоединение событий теперь всегда выполняется декларативно на странице .aspx. Вспомним, что в Visual Studio .NET 2003 двойной щелчок кнопки приводил к добавлению следующих строк в класс отделенного кода:

// VS.NET встраивает этот код в класс отделенного кода страницы,
// когда вы дважды щелкаете кнопку, чтобы добавить 
// обработчик события по умолчанию.
Send.Click += new EventHandler(this.Send_Click);

Теперь при первой компиляции страницы ASP.NET выполняет динамическое присоединение, и атрибут onclick преобразуется в код, приведенный выше. Заметьте: атрибут onclick применяется и при работе со страницей, использующей старую схему — отделенный код. Единственным отличием в этом случае будет определение обработчика события в классе отделенного кода, а не встраивание его непосредственно в страницу.

Теперь у нас есть пример страницы и некоторый код, с которым мы можем поиграть. Тестирование этой страницы сводится к нажатию клавиши F5. Visual Studio 2005 может пожаловаться на отсутствие файла web.config, необходимого для отладки кода. Если вы хотите запустить страницу, не выполняя отладку, щелкните Run. В противном случае можно позволить Visual Studio сгенерировать подходящий файл web.config. Если вы создали собственный web. config, убедитесь, что в нем есть следующая строка:

<compilation debug="true" />

Сделав это, можно запускать сеанс отладки.

Локальный Web-сервер

Встроенный Web-сервер — это небольшое приложение, и, конечно, он не может продублировать всю функциональность полноценного Web-сервера, такого как IIS. Он работает только с отдельными страницами и не поддерживает дополнительные возможности IIS, наподобие метаданных или способности работать в качестве почтового сервера по протоколу SMTP. Поэтому приложение, отсылающее письма по электронной почте, нужно тестировать с помощью IIS, поскольку локальный Web-сервер не может самостоятельно обработать почтовые сообщения. Однако если вы установите SMTP-сервис, то встроенный Web-сервер также сможет посылать электронную почту.

Еще один аспект работы со встроенным Web-сервером, который необходимо принимать во внимание, касается контекста безопасности. Работа приложения ASP.NET под управлением IIS 5.0 ограничена пространством обслуживающего рабочего процесса — отдельного исполняемого файла Win32, чье имя и возможности зависят от модели процессов, используемой в ASP.NET на этом сервере. Но вне зависимости от внутреннего представления и asp-net_wp.exe (рабочий процесс классической модели процессов в ASP.NET), и w3wp.exe (рабочий процесс, применяемый в модели процессов IIS 6.0) выполняются под управлением строго определенной учетной записи. В первом случае это учетная запись ASPNET, во втором — учетная запись NETWORK SERVICE.

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

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

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

Специальные папки в приложениях ASP.NET 2.0

В Visual Studio 2005 все файлы, найденные в подкаталогах приложения, неявно становятся частью сайта. Любой файл, скопированный в один из существующих каталогов, и любой вновь созданный каталог появляются в Solution Explorer. У одних папок в ASP.NET 2.0 есть специальное назначение, другие же просто названы определенным образом в соответствии с некоторым соглашением. В табл. 1-1 перечислены некоторые специальные папки, входящие в структуру приложения ASP.NET 2.0.

Папка Описание
BinСодержит все предварительно скомпилированныесборки, необходимые приложению.
CodeСодержит файлы с исходными классами (.vb или.cs), которые исполняющая среда ASP.NET динамически компилирует в сборки.
ResourcesСодержит файлы ресурсов (.jpg, .resx, .xsd), которые исполняющая среда ASP.NET динамически компилирует в ресурсные сборки.
ThemesСодержит определение тем, поддерживаемых приложением. Содержимое этой папки компилируется в динамическую сборку. (Темы ASP.NET будут рассмотрены подробнее в главе 4.)
Табл. 1-1.  Специальные папки в приложениях ASP.NET

Имена папок нечувствительны к регистру. Такие папки, как Images и Data, применяются часто, но в отличие от остальных не играют никакой роли в архитектуре исполняющей среды ASP.NET. Они просто названы в соответствии с соглашением и предназначены соответственно для хранения изображений и локальных файлов данных (например, баз данных Access, XML-файлов и т. п.).

Как и в ASP.NET 1.x, папка Bin — это место, где должны храниться пользовательские прекомпилированные сборки. Другой важный каталог в структуре приложения ASP.NET 2.0 — это каталог Code. Он предназначен для хранения повторно используемых компонентов, автоматически компилируемых и связываемых с кодом страницы. Visual Studio 2005 непрерывно следит за каталогом Code и при появлении в нем новых файлов с классами компилирует их. Компоненты подкаталога Code по умолчанию компилируются в одну общую сборку. Ссылка на эту сборку затем добавляется к проекту, и доступ к ней получают все страницы сайта. (Подробнее от этом — немного ниже.)

Модель смежного кода

Встроенный (inline) код нельзя назвать наилучшей практикой программирования, хотя в некоторых случаях он может быть гораздо практичней остальных методик. Такой код не приводит к уменьшению скорости выполнения страницы и не влияет на критические параметры сайта, вроде пропускной способности и масштабируемости. Если вы будете использовать встроенный код, с вашим приложением ничего плохого не случится. Единственные, кто могут пострадать от применения такого кода, — это сами программисты. Реальным страницам может потребоваться большой объем серверного кода, и добавление всего этого кода в тэг <script> файла .aspx чрезвычайно усложнит чтение, редактирование и сопровождение файла.

В ASP.NET 1.x в качестве альтернативы встроенному коду предлагались классы отделенного кода. Отделенный и встроенный код — два функционально эквивалентных способа присоединения кода к страницам с точки зрения исполняющей среды ASP.NET, но не с точки зрения Visual Studio .NET 2003.

Эволюция модели отделенного кода

Visual Studio .NET 2003 не поддерживает встроенный код. Если же вы все равно попытаетесь его использовать, у вас могут возникнуть сложности. Во-первых, вам не будет доступна функциональность IntelliSense и некоторые другие полезные возможности.

В реальных проектах, разрабатываемых в Visual Studio .NET 2003, вам просто придется играть по правилам и создавать страницы, использующие классы с отделенным кодом.

Концепция отделенного кода базируется на идее, что каждой

странице Web Forms соответствует отдельный файл с классом. Этот класс — динамически генерируемый класс страницы, создаваемый системой ASP.NET для каждого ресурса .aspx. Весь серверный код, который вы связываете с ресурсом .aspx, помещается в отделенный класс. В теории это выглядит красиво и элегантно, но в реализации Visual Studio .NET 2003 получается не слишком практично. Проект Visual Studio всегда компилируется в сборку, в которой все составляющие классы, включая и отделенные, собраны вместе. Как вы, возможно, уже узнали на собственном опыте, такой подход имеет по крайней мере три недостатка, перечисленных ниже.

ASP.NET 2.0 содержит новую улучшенную модель компиляции. В ней компиляция по требованию применяется в файлах классов, а также исключена необходимость компиляции Web-проектов в IDE Visual Studio .NET.

Компиляция по требованию для всех ресурсов

ASP.NET 1.x поддерживает динамическую компиляцию файлов нескольких типов: страниц ASP.NET (.aspx), Web-сервисов (.asmx), пользовательских элементов управления (.ascx), обработчиков HTTP (.ashx) и файлов global.asax. Перечисленные файлы автоматически компилируются по требованию при первом обращении к ним со стороны Web-приложения. Скомпилированная копия становится недействительной, как только в соответствующем исходном файле будут обнаружены изменения. Такая система позволяет програм-мистам быстро и с минимальными издержками разрабатывать приложения — вы просто нажимаете Save, и все готово.

В ASP.NET 2.0 возможность компиляции по требованию предусмотрена и для других типов файлов: обычных файлов с классами (.vb и .cs), ресурсных файлов (.resx), файлов обнаружения Web-сервисов (.wsdl) и файлов схем типизированных наборов данных (.xsd). Поскольку исполняющая среда ASP.NET гарантирует, что все изменения в указанных файлах отслеживаются незамедлительно, необходимость в явной компиляции отпала. Изменения в ASP.NET сделали возможным пересмотр всего механизма отделенного кода.

В то же время система компоновки ASP.NET 2.0 совместима со схемой отделенного кода в приложениях, созданных в более старых версиях ASP.NET.

ПРИМЕЧАНИЕ

То, что ASP.NET 2.0 компилирует файлы классов (.cs и .vb) по требованию, — это факт. То, что ASP.NET 1.x не делает то же самое, — вопрос спорный. В ASP.NET 1.x действительно существует возможность компиляции по требованию файлов классов, явно привязанных к страницам .aspx с помощью атрибута Src директивы @Page. К сожалению, эта кодовая модель не поддерживается в Visual Studio .NET 2002 и 2003 и поэтому часто остается невостребованной.

Смежный или отделенный код

Ничего плохого в применении модели отделенного кода нет. Она соответствует объектно-ориентированному подходу, способствует модульности кода и позволяет разделить код и разметку. Единственная проблема такой модели заключается в ее реализации в Visual Studio .NET 2003. Последняя версия Visual Studio содержит улучшенную модель взаимодействия страницы и класса. Новая кодовая модель, названная смежной (code-beside), похожа на модель отделенного кода, но в них использованы разные наборы ключевых слов, и ведут они себя по-разному. В следующем фрагменте показаны заголовки страниц ASP.NET 1.x с отделенным кодом, создаваемые как с помощью Visual Studio, так и без нее:

<%@ Page Language="C#" Inherits="Company.MyClass" 
         Codebehind="MyPage.aspx.cs" %>
<%@ Page Language="C#" Src="MyPage.aspx.cs" %>

Приведенный ниже пример демонстрирует связку «страница-класс», получаемую в ASP.NET 2.0 при использовании смежного кода. Обратите внимание на новое ключевое слово CompileWith:

<%@ Page Language="C#" CompileWith="MyPage.aspx.cs" 
         ClassName="Company.MyClass" %>

По умолчанию Visual Studio 2005 создает страницы со встроенным кодом. Для проектирования сайта с разделением кода следует указать соответствующий шаблон, выбрав пункт Add New Item в меню Website. При редактировании страницы, использующей разделение кода, Visual Studio сохраняет код в файле класса, указанном в атрибуте CompileWith. Для выполнения страниц или проекта нет необходимости выполнять их сборку. ASP.NET скомпилирует страницу, когда она впервые понадобится.

Частичные классы

Модели компиляции в ASP.NET 1.x и ASP.NET 2.0 значительно отличаются, поскольку имеют абсолютно разную основу. Страницы, применяющие разделение кода, могут пользоваться функциональностью, получившей название частичных (partial) классов. Во время выполнения страницы компилятор использует атрибут CompileWith директивы @Page для поиска файла, содержащего код. Затем он динамически объединяет страницу .aspx и этот код в один класс, унаследованный от базового класса Page. Полученный класс компилируется в сборку и выполняется.

После добавления Web-формы с разделением кода первая директива @Page на странице может выглядеть следующим образом:

<%@ page language="C#" compilewith="HelloBeside.aspx.cs" 
         classname="ASP.HelloBeside_aspx" %>

Во время выполнения страницы ASP.NET 2.0 динамически генерирует класс, соответствующий странице, а затем создает экземпляр этого класса. Атрибут CompileWith определяет файл с кодом для этой страницы, а атрибут ClassName содержит имя создаваемого класса. По умолчанию Visual Studio 2005 использует имя страницы как основу для имени класса.

По умолчанию код в файле со смежным кодом помещен в пространство имен ASP и содержит только определение класса. Это определение — неполное (частичное), в него входит только та часть полного класса, которая нужна странице во время выполнения. Говоря конкретно, частичный класс, определенный в кодовом файле, содержит обработчики событий и другой код, написанный вами. Исполняющая среда ASP.NET 2.0 анализирует файл разметки .aspx и комбинирует полученную информацию с содержимым частичного класса смежного кода. Полученный класс наследуется от класса Page, компилируется и используется для обслуживания запросов. В следующем примере приведена версия смежного кода приложения Hello, World, рассмотренного выше:

using System;
namespace ASP 
{
   public partial class HelloBeside_aspx
   {
      void Send_Click(object sender, EventArgs e)
      {
            MsgSent.Text = Msg.Text;
      }
   }
}

Более подробно мы будем обсуждать модель компиляции ASP.NET 2.0 в главе 11.

Совместное использование исходного кода компонентов

Модель смежного кода распространяет возможность использования компиляции по требованию и на классы, привязанные к Web-страницам. А как насчет других файлов с классами (например, вспомогательных компонентов и бизнес-объектов), которые ваше приложение может использовать как единолично, так и вместе с другими программами? Должны ли они заранее компилироваться и помещаться в папку Bin? Это не совсем так.

Подкаталог Code

Вы можете хранить вспомогательные классы и бизнес-объекты в подкаталоге Code. Как уже говорилось, Visual Studio 2005 следит за содержимым этой папки и компилирует все добавленные или исправленные классы. Ссылка на полученную сборку автоматически передается приложению и распространяется между всеми страницами, входящими в сайт.

В подкаталог Code следует помещать только компоненты. Не храните там страницы, пользовательские элементы управления и любые другие файлы, не содержащие код. Все файлы в папке Code динамически компилируются в одну сборку с именем code.dll. Область видимости этой сборки — приложение, а создается она в папке Temporary ASP.NET Files — за пределами дерева каталогов Web-сайта.

Пример создания совместно используемого класса

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

Во многих продуктах и службах, работающих через Web, следует применять надежные пароли. Определение «надежного пароля» зависит от службы, но в общем случае он должен быть не короче 8 символов и содержать по крайней мере по одному символу из следующих групп: символы в верхнем регистре, символы в нижнем регистре, цифры и специальные символы. Мы воспользуемся этим определением в нашем примере. Тестовая страница, которую мы разработаем, будет запрашивать требуемую длину пароля и предлагать вариант, построенный по указанным правилам. Создайте новый файл с именем StrongPassword.cs и поместите его во вновь созданный подкаталог Code. Вот структура этого класса:

public class StrongPassword
{
    public StrongPassword() 
    {...}
    public StrongPassword(string password) 
    {...}
    public bool Validate()
    {...}
    public bool Validate(string password) 
    {...}
    public string Generate()
    {...}
    public string Generate(int passwordLength)
    {...}
}

Класс содержит два основных метода: один — для проверки надежности указанного пароля, а другой — для генерации нового надежного пароля. Конечно, данное нами определение «надежности» пароля достаточно произвольно. После помещения в каталог Code этот класс скомпилируется по требованию и станет доступным всем страницам. А код тестовой страницы, предназначенный для генерации и проверки пароля, станет проще и читабельней:

void buttonGenerate_Click(Object sender, EventArgs e) {        
    StrongPassword pswd = new StrongPassword(); 
    // Используем минимально допустимую длину.
    labelPassword.Text = pswd.Generate();       
}
void buttonValidate_Click(Object sender, EventArgs e) {
    StrongPassword pswd = new StrongPassword(TestPassword.Text);    
    labelResult.Text = pswd.Validate().ToString();
}

Той же функциональности можно добиться и сделав код встроенным. Однако рациональное использование каталога Code улучшает читаемость и модульность, т. е., говоря другими словами, качество кода, который вы пишете.

Объектная модель страницы

В .NET Framework класс Page представляет .aspx-файл — Web-страницу — и реализует базовую функциональность всех страниц. Во время выполнения содержимое файла .aspx анализируется, и динамически создается класс (на C# или Visual Basic .NET, в зависимости от выбранного языка). Этот динамически созданный класс унаследован от базового класса Page. В отличие от ASP.NET 1.x в ASP.NET 2.0 базовый класс страницы не меняется при отделении кода. (В ASP.NET 1.x при использовании модели отделенного кода класс отделенного кода становится предком динамически генерируемого класса страницы.)

Класс Page — это встроенный обработчик HTTP, вызываемый для обслуживания запроса исполняющей средой ASP.NET посредством методов интерфейса IHttpHandler. Кроме того, этот класс представляет собой специальный тип элемента управления, поскольку он унаследован от TemplateControl. В ASP.NET 2.0 класс Page кроме того реализует интерфейс IPaginationContainer, который позволяет разбивать Web-страницу (и любой другой контейнерный элемент управления) на части с помощью нового управляющего элемента Pager. (Подробнее об этом ниже.)

public class Page : TemplateControl, IHttpHandler, IPaginationContainer

Поведением каждой страницы можно управлять с помощью атрибутов директивы @Page. Но чтобы наилучшим образом воспользоваться возможностями класса Page, необходимо изучить его свойства, методы и события и ясно представлять жизненный цикл страницы в исполняющей среде ASP.NET. В целом, при переходе от ASP.NET 1.x к ASP.NET 2.0 структура страницы не претерпела революционных изменений. Однако добавлено довольно много новых возможностей. Некоторые из них касаются представления страницы в виде объекта, другие — унаследованы от окружающей исполняющей среды.

Что нового в классе Page

В ASP.NET 2.0 к странице добавлена поддержка некоторых новых возможностей, таких как персонализация, эталонные страницы, темы и ведение статистики сайта. Вы можете контролировать, включать, отключать эти функции с помощью новых методов, свойств и директивных атрибутов. Начнем наше исследование с самого начала страницы, т. е. с директивы @Page. В этом разделе мы, в основном, сосредоточимся на изменениях и усовершенствованиях программного интерфейса класса Page. Все члены класса, определенные в ASP.NET 1.x, поддерживаются и в версии 2.0. Подробное обсуждение элементов, унаследованных от ASP.NET 1.x, можно найти в моей книге «Programming Microsoft ASP.NET» (Microsoft Press, 2003). Элементы инфраструктуры, такие как темы и статистика сайта, будут рассмотрены в главах 4 и 8 соответственно.

Директива @Page

В ASP.NET 2.0 добавлено несколько новых атрибутов к директиве @Page, позволяющих разработчику контролировать новые возможности, например упоминаемые ранее персонализацию и темы.

В табл. 1-2 перечислены новые атрибуты этой директивы.

Атрибут Описание
AsyncЕсли этот атрибут равен true, то генерируемый класс страницы порождается от IHttpAsyncHandler, а не от IHttpHandler, и страница получает некоторые встроенные асинхронные возможности.
CompileWithЗадает имя смежного файла, соответствующего этой странице.
EnablePersona-Указывает, нужно ли при генерации страницы использовать информацию из профиля пользователя.
MasterPageFile Задает путь к эталонному файлу, применяемому для генерации текущей страницы.
Personalization-Содержит имя допустимого провайдера, определенного в конфигурационном файле приложения.
ProvidTheme Определяет имя темы, используемой для данной страницы.
Табл. 1-2.  Новые атрибуты директивы @Page

Мы уже встречали атрибут CompileWith ранее в этой главе, а эталонные страницы будут подробно рассмотрены в главе 2. Персонализация и темы — предмет обсуждения главы 4. Персонализация касается вопроса автоматического использования информации из профиля. Темы предоставляют странице возможность менять свой внешний вид (скин) с сохранением всех ее функций.

ПРИМЕЧАНИЕ

Использование логической директивы Async (по умолчанию ее значение равно false) заставляет исполняющую среду ASP.NET генерировать код, обслуживающий запросы к странице асинхронно. В ASP.NET 1.x можно создавать асинхронные приложения, но нужно очень хорошо понимать применяемые концепции и писать довольно много кода. В среду ASP.NET 2.0 эта модель интегрирована, и ее можно включить с помощью директивы Async.

Код страницы выполняется асинхронно, пока исполняющая среда обрабатывает события жизненного цикла этой страницы. Их единственная точка взаимодействия на странице установлена между событиями PreRender и PreRenderComplete и служит для син-хронизации потоков, обрабатывающих запросы, и генерации вывода в браузер.

Свойства класса Page

Свойства объекта Page подразделяются на две группы: одна содержит встроенные объекты, вторая объединяет специфические для страницы свойства. К встроенным объектам относятся ссылки на такие глобальные объекты, как Cache, User и Trace, а также все классические встроенные объекты, формирующие контекст HTTP, — Session, Application, Request и аналогичные. Специфические свойства страницы — это все свойства, влияющие на состояние страницы или описывающие его, например IsPostBack, EnableViewState и SmartNavigation.

Новые свойства класса Page также можно отнести к одной из вышеупомянутых групп. В табл. 1-3 перечислены новые встроенные объекты ASP.NET 2.0.

Свойство Описание
ClientScript Экземпляр класса ClientScriptManager, представляющего отдельный объект, объединяющий все методы для работы с клиентскими сценариями.
Header Экземпляр класса HtmlHead, представляющего содержимое блока <head> страницы, если он помечен как runat=server.
MasterВозвращает эталонную страницу, определяющую общий внешний вид данной станицы.
PagerЭкземпляр управляющего элемента Pager (если он создан), выполняющий разбиение вывода текущей страницы на части.
SiteCountersЭкземпляр класса SiteCounters, представляющего встроенный сервис отслеживания обращений к страницам приложения. О сервисе статистики мы подробно поговорим в главе 8.
Табл. 1-3.  Новые встроенные объекты класса Page

Свойство ClientScript возвращает объект для управления методами, встраивающими в страницу код JavaScript. Этот объект действует как централизованная консоль по вызову всех методов, связанных с работой сценариев, таких как RegisterHiddenField и RegisterStartupScript. Обратите внимание: теперь все методы класса, работающие со сценариями, помечены как устаревшие и реализуются посредством вызова соответствующего метода объекта ClientScript. В следующем фрагменте кода приведен пример такого вызова:

[Obsolete("..."false)]
public void RegisterHiddenField(string fieldName, string field value) 
{
   this.ClientScript.RegisterHiddenField(fieldName, fieldValue);
}

Значение false в атрибуте [Obsolete] указывает, что применение устаревшего элемента не считается ошибкой.

В табл. 1-4 перечислены другие новые свойства класса Page.

Свойство Описание
EnablePersonalization -Позволяет получить или установить признак того, нужно ли использовать информацию из профиля для построения страницы.
EnableThemingПозволяет сконфигурировать страницу таким образом, чтобы тема игнорировалась. Это может быть полезным, если внешний вид страницы определен заранее, и вы не хотите, чтобы он изменился из-за применения темы.
IsAsyncПоказывает, обрабатывается ли страница асинхронно.
IsCrossPagePos Back t-Позволяет определить, загружена ли страница в результате возврата формы от другой страницы.
IsPagePersonalizedУказывает, содержит ли страница информацию профиля и используется ли эта информация в данный момент.
MasterPageFileПолучает или задает имя файла эталонной страницы.
MaximumWeightПолучает или устанавливает наибольший размер каждой страницы, используемый элементом управления Pager для разбиения вывода страницы .aspx на части. По умолчанию он равен 4000. (Подробнее об этом чуть позже.)
Personalization ModeЗадает режим персонализации, используя одно иззначений перечисления PersonalizationMode.
PreviousPage PageВозвращает объект, представляющий собой объект предыдущей страницы, участвующей в про-цессе возврата формы от другой страницы.
TitleПолучает или задает строку, содержащую заголовок страницы.
Табл. 1-4.   Другие новые свойства класса Page

Пара из этих свойств — IsCrossPagePostBack и PreviousPage — за-служивает еще нескольких слов. В ASP.NET 2.0 страницы больше не обязаны всегда возвращать формы для самих себя. Они могут автоматически отсылать содержимое своих уникальных HTML-форм другим страницам. Как страница-адресат может различить, выполнен ли возврат формы от нее самой или какой-то другой страницы? Это легко сделать с помощью свойств IsPostBack и IsCrossPagePostBack. В случае возврата формы от другой страницы страница-адресат имеет о странице-отправителе всю информацию и может получить значения исходных элементов управления, поскольку ссылка на страницу, отправившую форму, доступна в свойстве PreviousPage. В разделе «Программирование страницы» будет приведен пример применения этой функциональности.

Методы класса Page

Класс Page содержит несколько новых методов, большинство из которых просто унаследовано от базового класса Control. Все эти методы перечислены в табл. 1-5.

МетодОписание
EnsureID Унаследован от Control и не особенно полезен для страницы. Этот метод позволяет убедиться, что ID текущего объекта уникален.
Focus Унаследован от Control и не представляет ценности для страницы. Метод позволяет убедиться, что страница получила фокус ввода.
GetCallbackEventReferenceВозвращает прототип функции JavaScript, выполняемой на стороне клиента, отсылающей на сервер данные с помощью функции обратного вызова. Применяется для реализации удаленных сценариев.
GetValidatorsВозвращает набор верификаторов, входящих в определенную группу.
GetWebResour ceUrlВозвращает допустимый URL, указывающий на файл (например, на GIF-файл), который используется в странице в виде именованного ресурса.
RegisterRequires ControlState -Регистрирует указанный элемент, как требующий сохранения состояния. (Подробнее состояние элемента управления будет рассмотрено позже.)
SetFocusПередает фокус ввода указанному управляющему элементу на странице.
TestDeviceFilter Проверяет соответствие используемого браузера определенному типу.
Табл. 1-5.  Новые методы класса Page

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

События класса Page

Жизненный цикл страницы в исполняющей среде ASP.NET отмечен определенной последовательностью событий. Привязывая к событиям свой код, разработчики могут динамически модифицировать вывод страницы и состояние расположенных на ней элементов. В ASP.NET 1.x страница генерирует такие события, как Init, Load, PreRender и Unload, позволяющие выделить ключевые моменты жизненного цикла. В ASP.NET 2.0 добавлено довольно много новых событий, с помощью которых можно гораздо точнее отслеживать процесс обработки запроса. Новые события перечислены в табл. 1-6 в алфавитном порядке. Чуть позже мы обсудим порядок их срабатывания.

СобытиеОписание
InitCompleteВозникает после завершения инициализации страницы.
LoadCompleteВозникает в конце загрузочного этапа жизненного цикла страницы.
PreInitГенерируется перед началом инициализации страницы. Это первое событие в жизни страницы в ASP.NET 2.0.
PreLoadСрабатывает перед тем, как страница начинает загружать информацию о состоянии, сразу после инициализации.
PreRender CompleteВозникает после завершения фазы предрендеринга и создания всех дочерних элементов управления. После этого события сохраняется состояние отображения и данные персонализации и выполняется рендеринг HTML-страницы.
Табл. 1-6.  Новые события класса Page

Рассмотрим полный жизненный цикл страницы ASP.NET 2.0.

Жизненный цикл страницы

Страница ASP.NET начинает свой жизненный путь, когда исполняющая среда ASP.NET вызывает метод IHttpHandler::ProcessRequest для динамического класса, созданного в качестве оболочки исходного кода запрашиваемого ресурса .aspx. В этом методе заполняются встроенные элементы страницы, такие как контекст HTTP и объекты Request и Response. Затем метод строит дерево управляющих элементов, объявленных в коде .aspx, и выясняет, не выполняется ли страница в режиме возврата формы, обратного вызова или возврата формы для другой страницы. (О режиме обратного вызова я подробно расскажу позднее.) Первую возможность вступить в игру разработчики получают, когда происходит событие PreInit.

ПРЕДУПРЕЖДЕНИЕ

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

Программирование страницы

По сравнению с реализацией в ASP.NET 1.x класс Page в ASP.NET 2.0 предоставляет несколько новых возможностей, таких как возврат формы для другой страницы, разбиение содержимого страницы на части и персонализация. В этом разделе мы подробнее познакомимся с первыми двумя пунктами, отложив персонализацию до главы 4. Возврат формы для другой страницы (cross-page posting) — это функциональность, давно и настоятельно требуемая сообществом разработчиков ASP.NET. Разбиение страницы на части — результат плотной интеграции между ASP.NET и Mobile ASP.NET. Но начнем мы наш беглый обзор с другой долгожданной функциональности — возможности программирования тэга <head> Web-страницы.

Элемент управления HtmlHead

Управляющий элемент HtmlHead входит в пространство имен System.Web.UI.HtmlControls. Экземпляр этого элемента создается автоматически, если страница содержит тэг <head> с атрибутом runat=server. Обратите внимание: этот параметр задается по умолчанию, если вы добавляете новую страницу к Web-проекту в Visual Studio 2005, как продемонстрировано в следующем фрагменте:

<head runat="server">
    <title>Untitled Page</title>
</head>

Заголовок страницы можно получить с помощью нового свойства Header класса Page. Свойство возвращает null, если тэг <head> отсутствует, или не содержит атрибута runat.

Элемент управления реализует интерфейс IPageHeader, состоящий из трех свойств-наборов — Metadata, LinkedStylesheet, Stylesheet —и строкового свойства Title. Свойство Metadata — это словарь, содержащий все дочерние тэги <meta> заголовка:

Header.Metadata.Add("CODE-LANGUAGE", "C#"); 

Этот код приводит к генерации следующей разметки:

<meta name="CODE-LANGUAGE" content="C#" />

Чтобы создать другие виды метаданных, например Http-Equiv, можно прибегнуть к добавлению литеральных управляющих элементов к набору Controls заголовка. Обратите внимание на необходимость явного приведения объекта Header к типу Control, поскольку свойство Header объявлено с типом IPageHeader, у которого нет свойства Controls:

LiteralControl equiv;
equiv = new LiteralControl ("<meta http-equiv='refresh' content='3' />")
((Control) Header).Controls.Add(equiv);

Для добавления файла таблиц стилей можно использовать следующий код:

Header.LinkedStyleSheets.Add("MyStyles.css");

И, наконец, свойство Title элемента HtmlHead позволяет получить и установить заголовок страницы:

Header.Title = "This is the title";

Учтите, что это свойство возвращает правильный заголовок страницы только в том случае, если тэг <title> корректно размещен в пределах тэга <head>. Некоторые браузеры слишком снисходительны в этом вопросе и позволяют разработчикам определять этот тэг вне заголовка.

Возврат формы для другой страницы

Для реализации такого возврата формы нужно выполнить всего пару шагов. Во-первых, необходимо указать свойство PostBackUrl для тех кнопок и серверных элементов, которые могут вызвать этот возврат. Если свойство PostBackUrl установлено, исполняющая среда ASP.NET связывает соответствующий HTML-элемент с новой функцией JavaScript. Вместо старой знакомой __doPostback, она использует новую функцию WebForm_DoPostBackWithOptions:

<form runat="server">
   <asp:textbox runat="server" id="Data" />
   <asp:button runat="server" id="buttonPost"
            Text="Click" 
            PostBackUrl="~/target.aspx" />
</form>
Объявление кнопки визуализируется в следующую разметку:
<input type="submit" name="buttonPost" id="buttonPost" 
     value="Click"
     onclick="javascript:WebForm_DoPostBackWithOptions(
        new WebForm_PostBackOptions(&quot;buttonPost&quot;, 
                                    &quot;&quot;, 
                                    false, 
                                    &quot;&quot;, 
                                    &quot;target.aspx&quot;, 
                                    false, 
                                    false))" />

В результате, когда пользователь щелкает кнопку, текущая форма отсылает свое содержимое указанной странице-адресату. А что происходит с состоянием отображения? Если страница содержит элемент, выполняющий возврат формы для другой страницы, создается новое скрытое поле —_PREVIOUSPAGE. В нем находится информация о состоянии отображения, применяемом для обслуживания запроса. Эта информация используется вместо первоначального состояния отображения страницы-адресата.

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

<%@ page language="C#" %>
<script runat="server">
    void Page_Load(object sender, EventArgs e)
    {        
        if (PreviousPage == null)        
        {
            Response.Write("Invoke me only through cross-
              page posting.");
            Response.End();
            return;
        }    
        
        // Извлекаем данные из текстового поля.
        TextBox txt = (TextBox) PreviousPage.FindControl("Data");
        Response.Write("<b>You passed:</b> " + txt.Text);
    }
</script>
<html>
<head runat="server">
    <title>Target page</title>
</head>
<body>
</body>
</html>    

Разбиение страницы на части

Если вам приходилось работать с мобильными элементами управления ASP.NET, вам должно быть известно о разбиении вывода на части. Разбиение страницы на части — это возможность автоматического вывода содержимого формы по частям, в соответствии с характеристиками целевого мобильного устройства. Каждая из этих частей получается путем разбиения разметки целой формы на блоки примерно одинакового размера.

В ASP.NET 2.0 появился новый элемент управления страницами под названием Pager, который добавляет похожую функциональность всем серверным управляющим элементам, в том числе и мобильным. Этот элемент позволяет разбивать на части вывод всех контейнерных управляющих элементов, основываясь на их «весе» или числе дочерних элементов результирующей страницы. Pager также имеет свой собственный пользовательский интерфейс, позволяющий перемещаться по страницам.

Далее приведен исходный код страницы:

<%@ Page Language="C#" %> 

<html> 
<script runat="server"> 
    void Page_Load (Object sender, EventArgs e)
    {
        for (int i=0; i<50; i++) {
            TextBox txt = new TextBox ();
            txt.Text = i.ToString();
            panelSample.Controls.Add (txt);
            panelSample.Controls.Add (new LiteralControl("<br>"));
        }
    }
</script> 
<body> 
<form runat="server"> 
<h1>Pager in action</h1> 
<asp:contentpager runat="server" id="pagerPanel" 
    Mode="NextPreviousFirstLast"  
    ControlToPaginate="panelSample" 
    ItemsPerPage="9" /> 
<asp:panel runat="server" id="panelSample" borderwidth="1" /> 
</form> 
</body> 
</html>

Элемент ContentPager разбивает содержимое контейнера, основываясь на одном из двух алгоритмов — в зависимости от «веса» или количества элементов. Выбор алгоритма определяется значением свойства ItemsPerPage. Если это свойство задано, то используется алгоритм вывода на основе количества элементов, в противном случае используется весовой алгоритм. Оба алгоритма работают сходно, однако весовой алгоритм предоставляет более точный контроль за выводом элементов на каждой странице. В сущности, алгоритм, основанный на количестве элементов, пытается поместить на страницу ровно столько элементов, сколько задано в свойстве ItemsPerPage. Алгоритм на основе веса присваивает каждому контейнеру максимальный вес, который при разбивке на страницы не должен быть превышен. Например, максимальный вес класса Page равен 4000. Каждому элементу управления также присваивается вес по умолчанию (100). Как видите, поведение обоих алгоритмов по умолчанию практически одинаково, но вес каждого элемента может быть переопределен, что позволит изменить стандартную форму разбивки.

Объектная модель сценариев страницы

Отличная новость, касающаяся объектной модели сценариев в ASP.NET 2.0, состоит в том, что теперь они могут вызывать серверные события из клиентского кода, не отправляя данные страницы на сервер и не обновляя изображение. Такая разновидность удаленных сценариев реализована посредством механизма обратных вызовов, что дает разработчикам значительные преимущества. При использовании обратных вызовов в сценариях, результаты выполнения методов на серверной стороне передаются напрямую функции JavaScript, после чего она может обновить пользовательский интерфейс с помощью Dynamic HTML. Обращение к серверу происходит, но страница обновляется не полностью.

Сценарии с обратными вызовами — не единственная хорошая новость. Модель сценариев значительно улучшена. В результате, установка фокуса ввода на определенный элемент управления теперь сводится к вызову метода SetFocus.

Сценарии с обратными вызовами

Использование обратных вызовов в сценариях позволяет выполнять внеплановые обращения к серверу. Эти обращения — специальный вид возврата формы, так что полный цикл обмена данными все равно всегда присутствует, но, в отличие от классического возврата формы, обратные вызовы в сценариях не перерисовывают всю страницу и поддерживают у пользователя иллюзию, что все выполняется на стороне клиента. Обратные вызовы можно применять для обновления отдельных элементов страницы, например диаграмм или панелей, реализуя различные представления одних и тех же данных. Вы также можете загружать дополнительную информацию по требованию, автоматически заполнять одно или несколько полей и т. п. В частности, в ASP.NET 2.0 элемент управления TreeView интенсивно использует обратные вызовы для реализации разворачивания и сворачивания ветвей. А в элементе GridView (см. главу 7) обратные вызовы задействованы в функциях разбиения на страницы и сортировки без использования явных возвратов формы.

Обратный вызов в сценарии начинается с события на клиентской стороне (обычно щелчка мыши), которое запускает встроенную функцию JavaScript под названием WebForm_DoCallback. Если для срабатывания этой функции необходимо нажимать на кнопку, не используйте тэг <asp:button>. Этот тэг преобразуется в кнопку отправки, что в любом случае приведет к обновлению всей страницы. Используйте кнопку-ссылку или клиентскую кнопку, к примеру, тэг HTML 4.0 <button>. При вызове функции WebForm_DoCallback необходимо указать несколько аргументов, как показано ниже:

WebForm_DoCallback(
   pageID,         // ID страницы, выполняющей вызов
   argument,       // строковый аргумент для передачи 
                   // серверному коду   
   returnCallback, // код JavaScript, инициируемый
                   // по завершении обратного вызова
   context,        // данные, передаваемые вызову returnCallback
   errorCallback); //код JavaScript,вызываемый при появлении ошибок

Первый аргумент содержит ID страницы и является обязательным. Когда происходит возврат из серверного кода, инфраструктура ASP.NET 2.0 вызывает функцию, указанную как returnCallback, и передает ей возвращенное сервером значение (всегда строковое) и любую контекстную информацию. Функция returnCallback несет ответственность за обработку возвращенного значения и обновление пользовательского интерфейса с помощью Dynamic HTML.

Рассмотрим пример. Страница, поддерживающая внеплановые обращения к серверу, должна реализовывать интерфейс ICallbackEventHandler. Для этого необходимо указать директиву @Implements:

<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

Интерфейс ICallbackEventHandler содержит только один метод —RaiseCallbackEvent:

public virtual string RaiseCallbackEvent(string eventArgument)
{
    // eventArgument содержит переданный(е) параметр(ы).
    // TODO: Извлечь из параметра значения, переданные сервером,
    //       и запаковать все в возвращаемую строку.
}

Следующая страница демонстрирует пример применения обратных вызовов в сценариях от начала до конца. На ней показан раскрывающийся список с именами работников, взятыми из базы данных Northwind. По кнопке More Info запускается код JavaScript, передающий серверу ID выбранного в списке работника:

<%@ page language="C#" %>
<%@ import namespace="System.Data" %>
<%@ implements interface="System.Web.UI.ICallbackEventHandler" %>
<script language="javascript">
    function UpdateEmployeeViewHandler(result, context) { 
        // Результат представлен в виде строки значений,
        // разделенных запятыми.
        var obj = result.split(",");
        e_ID.innerHTML = obj[0]; 
        e_FName.innerHTML = obj[1]; 
        e_LName.innerHTML = obj[2]; 
        e_Title.innerHTML = obj[3]; 
        e_Country.innerHTML = obj[4]; 
        e_Notes.innerHTML = obj[5];
    }
</script>
<script runat="server">
    public virtual string RaiseCallbackEvent(string eventArgument) {
        // Получаем дополнительную информацию
        // об указанном работнике.
        int empID = Convert.ToInt32 (eventArgument);
        EmployeesManager empMan = new EmployeesManager();
        EmployeeInfo emp = empMan.GetEmployeeDetails(empID);
        // Упаковываем данные в строку.
        string[] buf = new string[6];
        buf[0] = emp.ID.ToString ();
        buf[1] = emp.FirstName; 
        buf[2] = emp.LastName; 
        buf[3] = emp.Title; 
        buf[4] = emp.Country; 
        buf[5] = emp.Notes;
        return String.Join(",", buf);
    }
    void Page_Load (Object sender, EventArgs e) {
        // Заполняем раскрывающийся список.
        EmployeesManager empMan = new EmployeesManager();
        DataTable dt = empMan.GetListOfNames();  
        cboEmployees.DataSource = dt;
        cboEmployees.DataTextField = "lastname";
        cboEmployees.DataValueField = "employeeid";
        cboEmployees.DataBind();
        // Подготавливаем вызов функции Javascript.
        string callbackRef = GetCallbackEventReference(this,
                "document.all['cboEmployees'].value",
                "UpdateEmployeeViewHandler", "null", "null");
        // Привязываем функцию обратного вызова
        // к клиентской кнопке.
        buttonTrigger.Attributes["onclick"] = 
                 String.Format("javascript:{0}", callbackRef);
    }
</script>
<html>
<body>
    <form runat="server">
        <asp:dropdownlist id="cboEmployees" runat="server" />
        <button runat="server" id="buttonTrigger">More Info
          </button><br>
        <table>
        <tr><td><b>ID</b></td><td><span id="e_ID" /></td></tr>
        <tr><td><b>Name</b></td><td><span id="e_FName" /></td></tr>
        <tr><td><b>Last Name</b></td><td><span id="e_LName" />
          </td></tr>
        <tr><td><b>Title</b></td><td><span id="e_Title" /></td>
          </tr>
        <tr><td><b>Country</b></td><td><span id="e_Country" />
          </td></tr>
        <tr><td><b>Notes</b></td><td><i><span id="e_Notes" /></i>
          </td></tr>
        </table>
    </form>
</body>
</html>

Страница отправляет вызов на сторону сервера, где начинается обычный процесс ее инициализации. Генерируются события Init и Load, а свойство IsCallback устанавливается в true. Вызов RaiseCallbackEvent происходит после окончания фазы загрузки. После этого запрос завершается, не переходя в фазу рендеринга. Специальный системный компонент — диспетчер обратных вызовов, — создаваемый на клиентской стороне, управляет процессом взаимодействия между страницей и сервером. Диспетчер обратных вызовов — это библиотека сценариев, передаваемая клиенту ASP.NET. Он отвечает за создание запросов к серверу и генерирует соответствующее событие на серверной стороне. Он также разбирает получаемый ответ и передает данные в указанную функцию JavaScript, вызываемую после завершения обратного вызова.

ПРИМЕЧАНИЕ

Нужно ли вам самостоятельно писать вызов WebForm_DoCallback? Следует ли понимать детали его реализации? Не обязательно. Метод GetCallbackEventReference класса Page возвращает строку со сценарием, инициирующим обратный вызов. Вам нужно предварить эту строку кодом javascript: и присоединить ее к атрибуту onclick клиентской кнопки. В качестве альтернативы можно создать для этой строки оболочку в виде функции JavaScript и поместить ее на страницу. Процесс генерации клиентского сценария для выполнения обратного вызова становится немного сложнее, если необходимо передавать параметры. В этом случае легче использовать WebForm_DoCallback напрямую. Однако если не выполнять вызов GetCallbackEventReference, генерируется ошибка периода выполнения. Чтобы наверняка добавить все необходимые ссылки, при инициализации нужно выполнить фальшивый вызов метода:

GetCallbackEventReference(this, "arg", "callback", "null", "null");

Установка фокуса

Возможность установки фокуса ввода на определенный элемент управления при показе страницы — это полезная функция, которой очень не хватало в ASP.NET 1.x. В ASP.NET 2.0 к классу Page специально добавлен метод SetFocus. Следующий код показывает, как установить фокус ввода на элемент управления TextBox с названием txtLastName:

void Page_Load(object sender, EventArgs e) {
    if (!IsPostBack)
        SetFocus("txtLastName");
}

Метод SetFocus кэширует ID элемента и заставляет класс Page генерировать дополнительный код сценариев при рендеринге страницы. В следующем примере показан альтернативный подход к установке фокуса:

<form runat="server" defaultfocus="txtLastName">
    .
    .
    .
</form>

Установив свойство формы DefaultFocus, вы указываете, какой управляющий элемент по умолчанию получает фокус ввода. Этот вариант эквивалентен вызову SetFocus. Разница между ними в том, что если один из элементов потребует установки фокуса посредством SetFocus, фокус по умолчанию игнорируется.

Обзор серверных элементов управления

В ASP.NET 1.x существует два различных, но похоже выглядящих семейства управляющих элементов — стандартные элементы ASP.NET и мобильные элементы. Основная цель ASP.NET 2.0 — позволить разработчикам создавать Web-приложения для различных устройств, не задумываясь о семантике конкретного устройства. ASP.NET 2.0 определяет общую архитектуру Web-элементов и адаптеров, а также унифицирует функциональность, присущую версиям Mobile ASP.NET и ASP.NET 1.x.

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

Адаптивный рендеринг мобильных управляющих элементов ASP.NET распространяется и на другие элементы ASP.NET, стирая различия между мобильными и Web-приложениями, по крайней мере, на уровне API. Однако следует заметить, что мобильные и Web-приложения все же остаются довольно разными с точки зрения требуемой семантики и принципов применения.

Новые возможности элементов управления

Управляющие элементы ASP.NET 2.0 сохраняют 100%-ю обратную совместимость с элементами ASP.NET 1.x, обеспечивая такую же или лучшую производительность. Кроме того, они отражают новую функциональность, предоставляемую платформой, такую как персонализация, использование тем, модель связывания с данными и состояние управляющих элементов. Во всех элементах применяется одинаковый префикс <asp:>, тогда как в мобильных элементах ASP.NET 1.x по умолчанию используется префикс <mobile:>.

Адаптивный рендеринг

Адаптивный рендеринг — это процесс создания различной разметки и форматирования для разных устройств. В первую очередь адаптивный рендеринг касается элементов управления, но он также распространяется и на контейнерные элементы, такие как формы и страницы. Хотя такой гибкий механизм рендеринга уменьшает количество кода, необходимого для создания приложений для различных видов устройств, он концептуально отличается от довольно привлекательной парадигмы «написано раз, работает везде».

Возможность однократного создания приложения основывается на идее наименьшего общего знаменателя, применяемого при генерации разметки. Это не относится к ASP.NET 2.0, где управляющие элементы всегда стараются выполнить визуализацию наилучшим способом, возможным для этого устройства. Адаптивный рендеринг лучше описывать с использованием другого слогана: «спроектировано раз, работает везде». Функциональность проектируется однократно, и может быть визуализирована практически на любом устройстве, но физическая адаптация кода может потребовать некоторого дополнительного кодирования. Этот дополнительный код приспосабливает вывод управляющего элемента к типу устройства, и, таким образом, при преобразовании не происходит потери функциональности.

Адаптеры — это компоненты, переопределяющие этапы жизненного цикла элементов управления, что позволяет выполнять действия, специфичные для каждого устройства. ASP.NET 2.0 ставит определенный адаптер в соответствие элементу управления при обслуживании каждого запроса. Разумеется, выбор адаптера зависит от текущего устройства. Элемент управления хранит ссылку на соответствующий адаптер в защищенном свойстве Adapter. У каждого элемента есть связанный с ним адаптер, если только речь не идет о составном управляющем элементе, чей рендеринг осуществляется дочерними элементами. Пользовательские элементы управления могут и не иметь адаптеров, поставленных им в соответствие, в этом случае ASP.NET 2.0 ищет адаптер, проходя по дереву наследования.

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

<asp:label runat="server" 
           text="This book is the best in its genre."
           IsWml:text=”Great book” />

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

Состояние элемента управления

Некоторым элементам ASP.NET необходимо, чтобы между запросами можно было сохранять некое состояние. Примерами информации о состоянии может служить текущая страница многостраничного элемента или порядок сортировки данных. В ASP.NET 1.x существует только один контейнер, в котором можно хранить эти данные, — состояние отображения (view state). Однако состояние отображения предназначено, в основном, для хранения установок уровня приложения, и, что самое главное, его можно отключить.

И что тогда станет с информацией элементов? В ASP.NET 2.0 вводится понятие состояния элемента управления (control state), отделенного от состояния отображения для того, чтобы подчеркнуть его важную роль в инфраструктуре управляющих элементов.

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

// Этот код является частью реализации элемента управления.
protected override void OnInit(EventArgs e) 
{
Page.RegisterRequiresControlState(this);
   base.OnInit(e);
}

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

protected override object SaveControlState() 
protected override void LoadControlState(object state)

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

ПРИМЕЧАНИЕ

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

Новые базовые элементы управления

Хотя ASP.NET 2.0 и поддерживает 100-процентную обратную совместимость с ASP.NET 1.x, лишь немногие компоненты не претерпели значительных изменений. Новые и исправленные элементы управления можно сгруппировать в 6 основных категорий: контейнеры, кнопки, текстовые поля, изображения, списки и элементы для работы с данными. В главе 7 подробно описаны новые элементы, работающие с данными и представлениями.

Давайте познакомимся с некоторыми новыми элементами управления. А начнем мы с уже существующего — элемента Panel, который получил в ASP.NET 2.0 новую интересную возможность.

Элемент управления Panel

Элемент Panel группирует другие элементы внутри тэга <div>. Он позволяет добавлять и удалять управляющие элементы и поддерживает информацию о стилях. В ASP.NET 2.0 панели могут содержать горизонтальные и вертикальные полосы прокрутки, реализованные с помощью CSS-стиля overflow. Приведем пример, демонстрирующий панель с вертикальной прокруткой:

<asp:panel runat="server" scrollbars="Vertical" height="105px" 
           style="border:solid 1px;">
           0<br />1<br />2<br />3<br />4<br />5<br />6
</asp:panel>

Элемент управления MultiView

Элемент MultiView задает группу представлений, из которых только одно может быть выбрано активным и показано клиенту. Для активного представления используется объект View.

<asp:MultiView runat="server" id="Tables">
   <asp:View runat="server" id="Employees">
        .
        .
        .
   </asp:View>
   <asp:View runat="server" id="Products">
        .
        .
        .
   </asp:View>
   <asp:View runat="server" id="Customers">
        .
        .
        .
   </asp:View>
</asp:MultiView>

Вы можете изменить активное представление с помощью событий возврата формы, когда пользователь щелкает кнопку или ссылки, принадлежащие текущему представлению. Для выбора нового варианта можно либо установить значение свойства ActiveViewIndex, либо передать объект представления методу SetActiveView.

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

void Page_Load(object sender, EventArgs e)
{
   // Views — это раскрывающийся список.
   Tables.ActiveViewIndex = Views.SelectedIndex;
}

Элемент управления Wizard

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

<asp:wizard runat="server" id="BookWizard"
    style="border:solid 1px" width="300" height="100"
    onfinishbuttonclick="Finished">
<WizardSteps>
    <asp:WizardStep steptype="Start">
         <h3>Thanks for choosing this book.
         Please, proceed with payment!</h3>
    </asp:WizardStep>
    <asp:WizardStep steptype="Step">
         <h3>Enter your credit card number:</h3>
         <asp:textbox runat="server" id="CreditCard" text="" />
    </asp:WizardStep>
    <asp:WizardStep steptype="Finish">
        <h3>You’re all set. Click and your credit card
        will be charged. Thank you!</h3>
    </asp:WizardStep>
    <asp:WizardStep steptype="Complete">
        <asp:label runat="server" id="FinalMsg" />    
    </asp:WizardStep>
</WizardSteps>
</asp:wizard>

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

В следующем коде приведен последний шаг мастера, завершающий всю операцию:

void Finished(object sender, EventArgs e)
{
    // Выполняем операцию.
        .
        .
        .
    // Выводим ответное сообщение.
    string msg = "Credit card <b>[{0}]</b>
      has been successfully charged.";
    FinalMsg.Text = String.Format(msg, CreditCard.Text);
}

Более подробно этот элемент управления будет рассмотрен в главе 8.

Элемент управления BulletedList

Мне очень не хватало элемента BulletedList в ASP.NET 1.x, поэтому я создал его самостоятельно. К моему удивлению, это было совсем не сложно. Но все равно я чрезвычайно рад, что этот управляющий элемент появился в ASP.NET 2.0. Он представляет собой программный интерфейс, построенный вокруг HTML-тэгов <ul> и <ol> и дает некоторые дополнительные возможности, например стили маркеров, связывание с данными и поддержку нестандартных изображений. В следующем примере в качестве маркера применяется нестандартный объект:

<asp:bulletedlist runat="server" bulletstyle="Square">
     <asp:listitem>One</asp:listitem>
     <asp:listitem>Two</asp:listitem>
     <asp:listitem>Three</asp:listitem>
</asp:bulletedlist>

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

Элемент управления DynamicImage

Класс DynamicImage — это нечто большее, чем просто оболочка для тэга <img>. Его функции не ограничиваются простым показом изображений. Этот элемент управления способен адаптировать изображение к возможностям указанного браузера. С помощью нескольких свойств можно задавать правила поведения класса DynamicImage при генерации изображений для браузеров с ограниченными графическими возможностями. Вот пример применения этого управляющего элемента:

<asp:dynamicimage runat="server"
    ImageFile="image.gif">
</asp:dynamicimage>

Интересно, что исходное изображение может быть задано различными способами, в том числе массивом байтов из внешнего источника, например базы данных, файла или сервиса генерации изображений. Байты изображения нужно передавать с помощью свойства ImageBytes, а не ImageFile, используемого для работы с файлами. Как вы узнаете из главы 8, ASP.NET 2.0 поставляется со специальным HTTP-обработчиком, который способен генерировать динамические изображения с помощью объектов GDI+. Если вы хотите показать изображение, полученное таким образом, необходимо в свойстве ImageGeneratorUrl указать URL этого сервиса. Если нужно передавать параметры, используйте управляющий элемент <asp:parameter>. Для генераторов изображений используется расширение .asix:

<asp:dynamicimage runat="server"
    ImageType="gif"”
    ImageGeneratorUrlImageFile="textimage.asix">
    <parameters>
        <asp:parameter Name="Text" DefaultValue="ASP.NET 2.0" />
    </parameters>
</asp:dynamicimage>

В главе 8 мы обсудим элемент DynamicImage подробнее.

Элемент управления FileUpload

В ASP.NET 1.x загрузка файла на сервер возможна с помощью серверного элемента HtmlInputFile. Он представляет собой простую оболочку для HTML-тэга <input type=file>. Новый управляющий элемент FileUpload ASP.NET 2.0 практически идентичен ему по своим функциям, но имеет более абстрактный интерфейс. Оба элемента управления выводят текстовое поле и кнопку поиска, позволяющую выбрать файл на компьютере клиента и загрузить его на Web-сервер.

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

<asp:fileupload runat="server" id="uploader" />

Элемент выполняет свою работу во время возврата формы. К загруженному файлу можно обратиться по имени через свойство FileName или работать с ним, как с потоком, воспользовавшись свойством FileContent. Для получения более подробной информации о присланном файле можно обратиться к объекту, возвращаемому свойством PostedFile. И, наконец, метод SaveAs позволяет скопировать присланный файл в другой файл на стороне сервера. Учтите, что каталог, в который происходит копирование, должен существовать, в противном случае будет сгенерировано исключение:

void UploadButton_Click(object sender, EventArgs e)
{
    // Указываем каталог на сервере, в котором
    // надо сохранить загруженный файл.
    string savePath = @"c:\temp\uploads\";
    if (FileUpload1.HasFile)
    {
       string fileName = FileUpload1.FileName;
       savePath += fileName;

       FileUpload1.SaveAs(savePath);

       UploadStatusLabel.Text = "File saved as: <i>" + savePath +
         "</i>";
     }
     else
     {
        // Уведомляем пользователя, что файл не был загружен.
        UploadStatusLabel.Text =
          "You did not specify a file to upload.";
     }
 }

Заключение

В этой главе мы рассмотрели три сущности, составляющие основу Web-приложений, написанных на ASP.NET: среду разработки, объект страницы и элементы управления. Обновленный и более мощный дизайнер форм ASP.NET 2.0 делает разработку Web-приложений проще и приятней. Дизайнер ASP.NET из Visual Studio 2005 решает все вопросы, касающиеся инструментов Web-разработки, и предоставляет высококачественную IDE, более продуктивную и простую в использовании.

Класс Page — это основа всех Web-форм, динамически создаваемых из ресурсов .aspx. Он значительно усовершенствован и теперь поддерживает такую функциональность, как персонализация, темы, и более мощную объектную модель сценариев, о чем лучше всего свидетельствует появление возвратов форм для других страниц и обратных вызовов в сценариях.

На страницах появляются новые базовые элементы управления, такие как Web-мастера, элемент MultiView и маркированные списки. Вероятно, наиболее значительное нововведение ASP.NET 2.0 — это унифицированная модель, объединяющая элементы управления для настольных и мобильных компьютеров. В результате в мире ASP.NET дебютировали такие новшества, как разбиение страницы на части и сохранение состояния элемента управления. Кроме того, в мобильных устройствах теперь можно использовать семейство более мощных управляющих элементов. Адаптивный рендеринг упрощает проектирование Web-приложений, выполняя оптимизацию для разных типов устройств посредством создания небольшого дополнительного приложения в случаях, когда простой настройки вывода недостаточно.

В следующей главе мы приступим к исследованию мира программирования ASP.NET 2.0. А начнем мы с наиболее востребованной новой функциональности ASP.NET 2.0 — эталонных страниц.


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