Основы ASP.NET 2.0

         

Блоки отображения


Любой код, внедренный с помощью <% и %>, обрабатывается во время события Render как часть страницы. В теле блока <% %> допустимо объявлять переменные (тогда они будут локальными для того метода, в котором данный блок будет реализован), но нельзя объявлять методы или типы.

Такой стиль программирования был характерен для asp. Чаще всего в блоках отображения выводится HTML-код с помощью Response.Write.

<%= someExpr %> является сокращением <% Response.Write (someExpr) %>:

<html> <head> </head> <body> 1 Строка HTML<br /> <% Response.Write ("1 Строка ASP.NET <br />"); %> 2 Строка HTML<br /> <% Response.Write ("2 Строка ASP.NET<br />"); %> 3 Строка HTML<br /> <% ="3 Строка ASP.NET<br />"; %> </body> </html>

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

Объект любого класса создается с помощью синтаксиса "тег объекта":

<object id="items" class="System.Collections.ArrayList" runat="server"/>

Это эквивалентно описанию в классе страницы поля:

System.Collections.ArrayList items;

Еще один способ применяется для связывания с источниками данных и будет рассмотрен в лекции 7



Директива Page


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

Наиболее важные атрибуты директивы перечислены в таблице.

AutoEventWireupАвтоматическая обработка событий страницы
BufferУправляет буферизацией страницы. По умолчанию буферизуется
ClassNameПозволяет назначать имя класса, сгенерированного данной страницей
CodeFileНазвание файла с отделенным кодом для данной страницы
CultureУстанавливает набор региональных параметров, т.е. язык, формат валюты, даты, чисел
DebugЕсли true, на страницу выводится отладочная информация
TraceВывод трассировочной информации
EnableViewStateСохранение состояния страницы. По умолчанию она сохраняется
EnableThemingПозволяет включить или выключить поддержку тем оформления. По умолчанию включено
InheritsКласс, от которого наследуется класс данной страницы в технологии отделенного кода
IsAsyncПоказывает, обрабатывается ли страница асинхронно
LanguageЯзык, используемый во внедренном коде
WarningLevelНаибольший допустимый уровень предупреждений компилятора
CompilerOptionsОпции компилятора



Директивы


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

Синтаксис объявления директив такой:

<%@ [Directive] [Attribute=Value] %>

Можно объявить несколько директив одновременно:

<%@ [Directive] [Attribute=Value] [Attribute=Value] %>

В ASP .NET 2.0 существует 11 директив.

ДирективаАтрибутыОписание
@AssemblyName SrcИмпортирует на страницу или в элемент управления сборку с заданным именем
@Controlтакие же, как у PageПрименяется для задания свойств при создании собственных пользовательских элементов управления
@ImplementsInterfaceУказывает, что класс данной страницы реализует данный интерфейс
@ImportNamespaceИмпортирует пространство имен
@Masterтакие же, как у PageПрименяется на страницах шаблона дизайна (Master page). Новая в ASP .NET 2.0
@MasterTypeTypeName VirtualPathДает строго типизированную ссылку на класс, содержащийся в шаблоне дизайна. Позволяет обращаться к свойствам этого класса
@OutputCacheDuration Location VaryByCustom VaryByHeader VaryByParam VaryByControlУправляет кэшированием страницы или элемента управления. Подробнее описана в лекции 15
@Pageсм. нижеАтрибуты, относящиеся к данной странице. Употребляется только в файлах с расширением aspx
@PreviousPageTypeTypeName VirtualPathСтраница, с которой были отправлены данные, введенные пользователем. Новая в ASP .NET 2.0. Раньше страницы отправляли пост только самим себе
@ReferencePage ControlСтраница или элемент управления, который нужно компилировать вместе с данной
@RegisterAssembly Namespace Src TagName TagPrefixСоздает псевдонимы для пространств имен и пользовательских элементов управления

Пока что подробно рассмотрим два из них — Page и Import.





Как работает ASP .NET


Когда мы инсталлируем .NET, в соответствующих директориях C:\WINDOWS\Microsoft.NET\Framework\ помещается также файл aspnet_isapi.dll. Это — ISAPI-расширение, и предназначено оно для получения запросов, адресованных ASP .NET-приложениям (*.aspx *.asmx и т.д.), а также для создания рабочих процессов aspnet_wp.exe, обрабатывающих запросы. Интернет-сервер — IIS или встроенный в WebMatrix и в Visual Studio Cassini — используют это расширение, когда им надо обработать обращение к страницам с расширением aspx.

Этот модуль разбирает (parse) содержимое страниц aspx вместе с файлом отделенного кода и генерирует класс на языке страницы с объектом Page. Страница aspx отличается от обычной HTML-страницы наличием серверных элементов управления, которые описываются специальными тегами. Для понимания работы ASP .NET важно отметить, что каждому тегу элемента управления соответствует свой член класса страницы. Например,

<asp:Label ID="Label1" runat="server"></asp:Label>

преобразуется в

@__ctrl = new global::System.Web.UI.WebControls.Label();

Основная задача объекта Page — посылка HTML-кода в выходной поток. Этот класс компилируется в библиотеку DLL, которая загружается в процесс web-сервера. Последующие запросы к странице также обрабатывает DLL, если исходный код страницы не меняется. Все эти файлы можно найти в директории "Temporary ASP.NET Files" текущей версии .NET. Если мы работаем в среде разработки Visual Studio 2005 или VWD, для каждого проекта создается своя поддиректория.



Проект на двух языках


Проект web-сайта состоит из страниц aspx и классов, которые используются на страницах (и, конечно, разнообразных ресурсов). Файлы с классами, к которым можно обратиться из разных страниц, помещают в специальную папку App_Code. При компиляции они помещаются в одну сборку — библиотеку DLL в формате portable executable. Совершенно неважно, на каком языке написан класс, если это язык .NET.

Готовые скомпилированные сборки сторонних производителей тоже можно использовать в проекте. Их помещают в папку Bin. При этом их необходимо импортировать в проект:

<%@ Import Namespace="MyCustomNamespace" %>

Создайте новый проект. Добавьте в него файл, выбрав тип файла Class и язык Visual Basic. Среда сама предложит поместить его в папку Code. Назовем его CustomClass. У него будет очень простой код. Всего одна функция, которая добавляет слово Hello к имени, переданному в качестве параметра:

Imports Microsoft.VisualBasic

Public Class CustomClass

Public Function GetMessage(ByVal name As String) As String Return "Hello, " & name End Function End Class

Добавьте в проект страницу CodeFolder_cs.aspx. Эта страница написана на C#, но она создает класс, написанный на VB .NET:

<%@ page language="C#" %>

<script runat="server">

void Button1_Click(object sender, EventArgs e) { CustomClass c = new CustomClass(); Label1.Text = c.GetMessage(TextBox1.Text); } </script>

<html> <head> <title>ASP.NET Inline Pages</title> </head> <body> <form id="Form1" runat="server"> <h1>Welcome to ASP.NET 2.0!</h1> <b>Enter Your Name:</b> <asp:TextBox ID="TextBox1" Runat="server"/> <asp:Button ID="Button1" Text="Click Me" OnClick="Button1_Click" Runat="server"/> <br /> <br /> <asp:Label ID="Label1" Text="Hello" Runat="server" /> </form> </body> </html>


На странице определена форма, напоминающая форму Windows-приложения. На ней имеется кнопка, нажатие на которую обрабатывается в функции Button1_Click. В ней создается класс и вызывается его функция GetMessage с параметром, который берется из элемента редактирования. Возвращаемое значение записывается в элемент Label1. В более простом варианте это выглядит так:

Label1.Text = "Hello "+TextBox1.Text;

Класс может быть написан на C#, а использоваться из страницы на Visual Basic:

using System; public class CustomClass2 { public String GetMessage(String input) { return "Hello from C# " + input; } } Код страницы CodeFolder_vb.aspx: <script runat="server">

Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Dim c As New CustomClass2 Label1.Text = c.GetMessage(TextBox1.Text) End Sub </script>

Однако поместить в директории App_Code можно только на одном языке. Если там будут находиться файлы на разных языках, проект не будет компилироваться. Для того чтобы использовать два языка, необходимо создать поддиректорию, добавить ее в файл web.config и поместить в нее файлы на другом языке.

Регистрация в файле web.config:

<configuration> <system.web> ... <compilation> <codeSubDirectories> <add directoryName="VBCode"/> </codeSubDirectories> <codeSubDirectories> <add directoryName="CSCode"/> </codeSubDirectories> </compilation> ... </system.web> </configuration>


Программа просмотра классов


Как же узнать, какие классы имеются в библиотеке классов .NET? Для этого предназначен Object Browser (Visual Studio 2005) и Class Browser WebMatrix. Чтобы открыть Object Browser в Visual Studio 2005 или VWD Express, выберите пункт меню View —> Object Browser. Если вы используете WebMatrix, то Class Browser находится в той же папке меню Windows, что и WebMatrix — All Programs —> ASP.NET WebMatrix. В формате ASP .NET Class Browser включен в состав Framework SDK.

Все имеющиеся пространства имен показаны как узлы древовидной структуры. Нас интересует System.Web. Раскройте этот узел. Внутри оказались другие пространства имен. Раскройте System.Web.UI. Там находится большое количество классов, интерфейсов, делегатов, перечислений. Их можно узнать по иконкам. Например, иконка делегата похожа на чемодан.

— класс

— интерфейс

— событие

— перечисление

— метод

— свойство

Выберите класс Page. В окошке справа появится список его методов, полей и событий. Если выбрать метод, в третьем окне под вторым появится его описание. Внутри класса находятся еще две папки — классов-прародителей (Base Classes) и классов-потомков. Все их тоже можно просмотреть. Object Browser показывает и классы текущего проекта. Если классы закомментированы тегами генерации документации XML, то эта информация тоже видна, например Summary, Parameters, Values, Returns.


увеличить изображение
Рис. 2.8. 

Исследуя свойство IsPostBack, можно узнать, что оно имеет булевское значение и предназначено только для чтения.



Пространства имен библиотеки классов


Библиотека классов FCL содержит тысячи классов. Для удобства использования они объединены в пространства имен. Чтобы обращаться к классам, объявленным в пространстве имен, без указания полного пути, его нужно импортировать в проект. Если вы хотите работать с файлами формата XML, вам нужно импортировать пространство имен System.XML. В страницах отделенного кода на C#, как всегда, используется директива using.

using System. XML;

На странице aspx — директива Import

<%@ Import Namespace= "System.XML " %>

Для каждого пространства имен требуется отдельная директива Import.

Visual Studio .NET и VWD по умолчанию включают в страницу на C# наиболее часто используемые пространства имен. На страницу aspx импортировать эти пространства имен не требуется.

using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;

Например, в пространстве имен System.Web.UI находится класс Page, без которого не может существовать ни одна страница ASP .NET, в System.Web — HttpRequest и HttpResponse.



Проверка соответствия стандартам


Существуют разные стандарты HTML и xHTML. Более поздние стандарты предъявляют более строгие требования, например, хHTML 1.1 не разрешает пользоваться <br> и другими простыми тегами без закрывающей косой черты <br/>. В то же время старые стандарты не поддерживают новые теги.

В заголовке HTTP-запроса указывается стандарт документа, Visual Studio 2005 во всех страницах указывает следующий стандарт:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Этот стандарт требует наличия атрибута xmlns в теге <html> — ссылки на сайт с описанием стандарта.

<html xmlns="http://www.w3.org/1999/xhtml">

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



События страницы


Работа среды ASP .NET со страницей начинается с получения и обработки web-сервером IIS-запроса к данной странице и передачи этого запроса среде выполнения ASP .NET. Среда выполнения анализирует, нужно ли компилировать страницу или можно выдать в качестве ответа страницу из кэша.

Затем начинается жизненный цикл страницы. Он начинается с этапа PreInit. После получения запроса среда выполнения загружает класс вызываемой страницы, устанавливает свойства класса страницы, выстраивает дерево элементов, заполняет свойства Request, Response и UICulture и вызывает метод IHttpHandler.ProcessRequest. После этого среда выполнения проверяет, каким образом была вызвана эта страница, и если страница вызвана путем передачи данных с другой страницы, о чем будет рассказано далее, то среда выполнения устанавливает свойство PreviousPage.

На этом этапе устанавливается также свойство IsPostback объекта Page, которое позволяет узнать, в первый ли раз загружается форма или она должна формироваться как результат обработки данных, введенных пользователем.

В обработчиках событий страницы можно проверить это свойство:

if (!Page.IsPostBack) { // обрабатывать }

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


Программист может инициализировать их свойства.
Загрузка. Во время события Load устанавливаются свойства элементов управления на основании информации о состоянии, если страница создается в результате отправки данных формы.
Если на странице существуют валидаторы (классы проверки данных, см. лекцию 5), то для них вызывается метод Validate(). Затем вызываются обработчики событий (при условии, что страница генерируется в ответ на действия пользователя).
В методе Render генерируется сам HTML-код выводимой страницы. При этом страница вызывает соответствующие методы дочерних элементов, а те в свою очередь — методы своих дочерних элементов. В методе Render код выводится в Response.OutputStream. Сама страница тоже считается элементом управления — класс Page является наследником класса Control. Если на странице есть блоки отображения, они становятся частью функции отрисовки (rendering).
Наконец, страница выгружается из памяти сервера и происходит событие Unload.
Во время жизненного цикла страницы происходят различные события. Можно включить трассировку страницы, чтобы посмотреть порядок их возникновения:
<%@ Page Language="C#" Trace ="true" TraceMode="SortByTime" %>

увеличить изображение
Рис. 2.9. 
Во время трассировки не выводится событие Unload, потому что оно происходит, когда весь код уже выведен. Во время обработки этого события нужно освободить ресурсы, например, соединения с базами данных или открытые файлы.
Полный список событий страницы, которые можно переопределить в классе страницы:


PreInitInitInitCompletePreLoadLoadLoadCompletePreRenderPreRenderCompleteUnload
Для всех событий определены обработчики — виртуальные функции OnInit, OnLoad. Когда AutoEventWireup равно true, в классе автоматически объявляются функции-обработчики событий с префиксом Page — Page_Load, Page_Init и так далее. Одно из самых популярных событий — это Page_Load. Генерируя новую страницу, Visual Studio создает обработчик этого события. Здесь можно изменить внешний вид элементов и задать новые. Можно установить AutoEventWireup в false. В таком случае надо писать перегруженные версии виртуальных функций:
protected override void OnInit(EventArgs e) { }
Так можно добиться ускорения работы страницы.

Способы внедрения кода ASP .NET в страницу


Есть три способа внедрить код на программном языке в страницу aspx.

Блок <script runat="server"> </script> называется блоком объявления кода. Тег <script> похож на тот, которым вводятся скрипты JavaScript, но с большим отличием — скрипт выполняется на сервере. Поэтому необходимо задавать атрибут runat="server". Атрибут language у него может принимать значения С#, VB, J#. В страницах с отделенным кодом можно писать и на C++. По умолчанию принимается значение языка Visual Basic, поэтому не надо забывать указывать язык, когда пишете на С#. Но нет необходимости это делать, если язык определен в директиве Page. Можно писать на разных языках в одном приложении, но нельзя смешивать разные языки на одной странице.

Внутри блока можно объявлять переменные, константы и функции. На самом деле в C# нет глобальных переменных, так что это будут члены класса страницы. Но они выглядят глобальными, потому что класс не описан программистом, его генерирует ASP .NET. Поэтому будем называть их переменными страницы.

Здесь можно переопределить виртуальные методы класса страницы. В блоке также можно объявлять классы, но они будут внутренними по отношению к классу страницы.



Свойства страницы


Страница — это основа всего в web-приложении.

Класс System.Web.UI.Page инкапсулирует функциональность, необходимую для создания и обработки страниц ASP .NET.

Каждая страница ASP .NET — это объект класса, который автоматически генерируется ядром ASP .NET. Класс наследуется от ассоциированного со страницей класса, если мы используем отделенный код, или прямо наследуется от System.Web.UI.Page, если код на C# встроен в страницу. Среда также создает конструктор по умолчанию.

Чтобы убедиться в этом, можем создать страницу "PageType.aspx":

<%@ Page Language="C#" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Тип страницы</title> </head> <body> <div> <% Response.Output.Write("Тип данной страницы {0}",this.GetType()); %> </div> <div> <% Response.Output.Write("Базовый тип данной страницы {0}",this.GetType().BaseType); %> </div> </body> </html>

Вот результат:

Тип данной страницы — ASP.pagetype_aspx

Базовый тип данной страницы — System.Web.UI.Page

Такая же страница, созданная по технологии разделения кода,

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PageType.aspx.cs" Inherits="PageType" %>

пишет результат:

Тип данной страницы — ASP.pagetype_aspx

Базовый тип данной страницы — PageType

То, что PageType — наследник System.Web.UI.Page, прописано в файле отделенного кода:


public partial class PageType : System.Web.UI.Page
К текущему объекту страницы можно обращаться как к переменной Page. Page — это контейнер элементов управления данной страницы, поэтому содержит в себе коллекцию Controls. Если в теге <head> присутствует атрибут runat = "server", то в Page содержится и поле Header, через которое можно управлять заголовком страницы — например, поменять название страницы в заголовке браузера, назначить файл каскадных таблиц стилей:
<script runat="server"> protected void Page_Init(object sender, EventArgs e) { HtmlLink myHtmlLink = new HtmlLink(); myHtmlLink.Href = "printable.css"; myHtmlLink.Attributes.Add("rel", "stylesheet"); myHtmlLink.Attributes.Add("type", "text/css");
Page.Header.Controls.Add(myHtmlLink); Page.Header.Title = "Новый заголовок"; } protected void Page_Load(object sender, System.EventArgs e) { Style bodyStyle = new Style();
bodyStyle.ForeColor = System.Drawing.Color.Blue; bodyStyle.BackColor = System.Drawing.Color.Beige;
Page.Header.StyleSheet.CreateStyleRule(bodyStyle, null, "p");
} </script>
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Hello ASP.NET</title> </head> <body> <p>Учитесь программировать на ASP.NET</p> </body> </html>
В этом примере мы поменяли текст заголовка. Запустите эту страницу. В получившемся HTML-коде внутри тега <title> стоит уже не "Untitled Page", а "Новый заголовок", который был установлен через Page.Header.Title.


Был создан стиль для тега <p>, что отразилось таким образом:
<style type="text/css"> p { color:Blue;background-color:Beige; } </style>
Внешняя страница CSS была импортирована из файла:
<link href="printable.css" rel="stylesheet" type="text/css" /> <style type="text/css">
Если атрибут AutoEventWireup, который присутствует в заголовке страниц, генерируемых VS, установлен, то методы с префиксом Page_ автоматически назначаются обработчиками событий страницы.
У страницы есть два важных свойства — Response и Request. Свойство Response имеет тип HttpResponse. Response страницы можно воспринимать как выходной поток. Весь HTML-код генерируемой страницы в принципе может быть выведен через запись в этот поток. Это был обычный способ работы разработчиков asp. Но в ASP .NET есть более удобные средства вывода данных с помощью серверных элементов управления. Response лучше использовать для записи Cookies, для задания различных параметров заголовка — управлять кэшированием, свойством Expires.
Вот пример из MSDN:
HttpCookie MyCookie = new HttpCookie("LastVisit"); DateTime now = DateTime.Now;
MyCookie.Value = now.ToString(); MyCookie.Expires = now.AddHours(1);
Response.Cookies.Add(MyCookie);
Можно поменять кодовую страницу:
<head runat="server"> <%Response.Charset = "windows-1251"; %> <title>Русская кодировка</title> </head>
Функция Response.Redirect перенаправляет браузер на другую страницу:
Response.Redirect("NavigationTarget.aspx?name=" + System.Web.HttpUtility.UrlEncode(Name.Text);
Здесь формируется командная строка с параметрами QueryString, которые целевая страница может прочитать.
Аналогично, свойство Request — это запрос, переданный на сервер для вывода нужной страницы. Он имеет тип HttpRequest. В нем хранится все о клиенте, включая настройки его браузера, файлы-cookie и данные, введенные им в форму:
NameLabel.Text = Server.HtmlEncode(Request.QueryString["Name"]);

Типы страниц и папок проекта


В проект можно добавлять новые файлы через диалог New File.


увеличить изображение
Рис. 2.1. 

Если снять отметку с флажка "Place code in separate file", Visual Studio создаст один файл, в котором будет и страница, и код для ее обработки (в стиле WebMatrix).

Все файлы помещаются в директорию проекта. И наоборот, все файлы, которые будут помещены в директорию проекта, станут его частью. Для web-сайтов не существует специального файла .csproj, в котором перечислялись бы его составные части, как это было в предыдущих версиях Visual Studio. Структура решения (solution) описывается в текстовом файле .sln. В решение могут входить несколько web-сайтов и библиотек.

В ASP.NET 2.0 имеются специальные поддиректории проекта для разных типов файлов. Например, в папке App_Code хранятся общедоступные классы, текстовые файлы и некоторые другие (DataSet, диаграмма классов). Файлы с расширениями .cs или .vb, попавшие туда, автоматически компилируются, когда запрашивается любая страница проекта. В App_Data содержатся источники данных, используемых в проекте, — базы данных Access и Microsoft SQL, XML-файлы. К этой директории нельзя получить доступ извне, а только из самого приложения. В папке Themes хранятся темы проекта (лекция 13). Применение тем позволяет настроить единообразный внешний вид сайта и централизованно им управлять. В App_GlobalResources находятся ресурсы, например, таблицы строк, которые можно создавать на разных языках. Язык ресурсов выбирается автоматически в зависимости от настроек браузера пользователя. В папке App_WebReferences находятся ссылки на используемые web-сервисы.

Можно создавать собственные поддиректории проекта, например, для хранения картинок.



NET Frameworks. Для многих из


Технология ASP .NET построена на объектно-ориентированном событийно-управляемом подходе к созданию web-страницы. Классы, используемые для генерации web-страниц, являются частью библиотеки . NET Frameworks. Для многих из них существуют аналоги в Windows Forms, что сближает программирование настольных приложений с программированием web-приложений.