Лекция 2. Анатомия ASP.NET. ASP.NET в действии. (документация, исходники)Источник: aspnetmania
Ум сугубо математический будет правильно работать, только если ему заранее известны все определения и начала ВведениеASP.NET - один из компонентов .NET Framework. Перечислим кратко основные черты этой технологии:
ADO.NET - набор классов, предназначенных для доступа к базам данных Microsoft SQL Server, к источникам данных OLEDB и к файлам XML. Разные части вашего проекта могут быть написаны на разных языках, это называется interoperability . Мы попробуем написать проект, где одна из страниц будет на Visual Basic, а другая на С#. Компютерные языки бывают компилируемыми и интерпретируемыми. В процессе компиляции программы, написанной на компилируемом языке, создается выполняемый файл(В Windows - exe). Он выполняется быстро, но не может исполняться на другой платформе. Машина, на которой она выполняется, должна иметь похожую конфигурацию. Например, если программа использует dll, то эта библиотека должна быть установлена и на целевой машине. Интерпретируемые программы компилируются в момент выполнения, поэтому они работают медленнее, но не зависят от конкретной машины. В .NET Framework применяется двухэтапная компиляция, то есть первый этап - это компиляция в MSIL, а вторая - компиляция «Just-in-time» компилятором во время исполнения. JIT-компилятор оптимизирует код для той машины, на которой он исполняется. В ASP.NET страница компилируется в MSIL при первом обращении клиента к странице. Вместе с ней компилируются классы, которые она использует. Если вы используете Visual Studio 2005, можно не ожидать первого запроса, а принудительно скомпилировать все страницы вашего проекта. Это позволит выявить синтаксические и другие ошибки. MSIL - это ассемблер, не зависящий от машины. Он может выполняться на любой машине, где установлена CLR. Проект Mono пытается перенести CLR на другие платформы, позволяя взаимодействовать серверам, работающим на разных платформах. Вы можете ознакомиться с проектом на сайте http://mono-project.com На странице http://go-mono.com/archive/xsp-0.10.html находится XSP - сервер ASP.NET, который может служить расширением сервера Apache - основного сервера *nix - систем. Как работает 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, которая загружается в процесс веб-сервера. Последующие запросы к странице также обрабатывает dll, если исходный код страницы не меняется. Все эти файлы можно найти в директории «Temporary ASP.NET Files» текущей версии .NET. Если мы работаем в среде разработки Visual Studio 2005 или VWD, для каждого проекта создается своя поддиректория. Типы страниц и папок проектаВ проект можно добавлять новые файлы через диалог New File. Если снять отметку с флажка "Place code in separate file", Visual Studio создаст один файл, в котором будет и страница, и код для ее обработки(в стиле WebMatrix). Все файлы помещаются в директорию проекта. И наоборот, все файлы, которые будут помещены в директорию проекта, станут его частью. Для веб-сайтов не существует специального файла .csproj, в котором перечислялись бы его составные части, как это было в предыдущих версиях Visual Studio. Структура решения(solution) описывается в текстовом файле .sln. В решение могут входить несколько веб-сайтов и библиотек. В ASP.NET 2.0 имеются специальные поддиректории проекта для разных типов файлов. Например, в папке App_Code хранятся общедоступные классы, текстовые файлы и некоторые другие(DataSet, диаграмма классов). Файлы с расширениями .cs или .vb, попавшие туда, автоматически компилируются, когда запрашивается любая страница проекта. В App_Data содержатся источники данных, используемых в проекте - базы данных Access и Microsoft SQL, XML-файлы. К этой директории нельзя получить доступ извне, а только из самого приложения. В папке Themes хранятся темы проекта(лекция 13). Применение тем позволяет настроить единообразный внешний вид сайта и централизованно им управлять. В App_GlobalResources находятся ресурсы, например таблицы строк, которые можно создавать на разных языках. Язык ресурсов выбирается автоматически в зависимости от настроек браузера пользователя. В папке App_WebReferences находятся ссылки на используемые веб-сервисы. Можно создавать собственные поддиректории проекта, например, для хранения картинок. Проект на 2 языкахПроект 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> ДирективыНа каждой странице aspx обычно задаются директивы, с помощью которых Вы можете контролировать поведение страницы. Можно считать их языком, с которым вы общаетесь с компилятором, указывая ему, как обрабатывать данную страницу. Директивы обычно помещают в начале файла. Мы уже встречались с директивой Page в первой лекции. Синтаскис объявления директив такой: <%@ [Directive] [Attribute=Value] %> Можно объявить несколько директив одновременно: <%@ [Directive] [Attribute=Value] [Attribute=Value] %> В ASP.NET 2.0 существует 11 директив.
Пока что подробно рассмотрим 2 из них - Page и Import. Директива PageДиректива Page позволяет установить свойства страницы, которые будут использованы во время компиляции. Эта директива используется чаще остальных, поэтому ее необходимо рассмотреть более подробно. Наиболее важные атрибуты директивы перечислены в таблице:
Пространства имен библиотеки классовБиблиотека классов 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. Программа просмотра классовКак же узнать, какие классы имеются в библиотеке классов .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. Исследуя свойство IsPostBack, можно узнать, что оно имеет булевское значение, и предназначено только для чтения. Проверка соответствия стандартамСуществуют разные стандарты HTML и XHTML. Более поздние стандарты предъявляют более строгие требования, например, XHTML 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 также находится выпадающий список, в котором можно выбрать стандарт или версию браузер, для которого предназначена данная страница. Страница автоматически проверяется на соответствие этому стандарту. Свойства страницыСтраница - это основа всего в 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"]); События страницыРабота среды 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" %> Во время трассировки не выводится событие Unload, потому что оно происходит, когда весь код уже выведен. Во время обработки этого события нужно освободить ресурсы, например соединения с базами данных или открытые файлы. Полный список событий страницы, которые можно переопределить в классе страницы:
Для всех событий определены обработчики - виртуальные функции 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. Поэтому будем называть их переменными страницы. Здесь можно переопределить виртуальные методы класса страницы. В блоке также можно объявлять классы, но они будут внутренними по отношению к классу страницы. Блоки отображенияЛюбой код, внедренный с помощью <% и %>, обрабатывается во время события 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 лекции. ЗаключениеТехнология ASP.NET построена на объектно-ориентированном событийно-управляемом подходе к созданию web-страницы. Классы, используемые для генерации web-страниц, являются частью библиотеки .NET Frameworks. Для многих из них существуют аналоги в Windows Forms, что сближает программирование настольных приложений с программированием web-приложений. |