Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » .NET - ASP.NET »

Обсудить на форуме Обсудить на форуме

Введение в ASP.NET 2.0

Гайдар Магдануров
Знакомство с ASP.NET 2.0

Введение

Каждый раз, разрабатывая проект и создавая Web-приложение, пользуются различными средствами для создания архитектуры приложения, редактирования кода и публикации результатов своего труда на Web-сервере. При этом для конечного пользователя Web-приложение любой сложности остается набором HTML-страниц, каждая из которых имеет свой уникальный URL. По большом счету, пользователю нет дела до того на какой платформе или с использованием какой технологии создано приложение. У пользователя есть цель, которую он хочет достичь и универсальное средство, практически любой используемый им Web-браузер. В этом заключено огромное преимущество приложений для Internet по сравнению с приложениями для настольных систем – существование общепринятого «языка общения», HTML кода. Для того, чтобы развернуть Web-приложение достаточно установить его на сервер, после чего приложение может быть доступно любому клиенту с установленным Web-браузером. К сожалению, здесь тоже существует очевидная проблема в обработке HTML кода браузерами разных производителей.
    Задача разработчика заключается в том, чтобы создать приложение, генерирующее HTML код, оптимальный для большинства браузеров, которыми пользуется конечный пользователь. Каждая технология, используемая для создания Web-приложения, позволяет генерировать HTML код, поэтому, в конечном итоге, выбор технологии, на основе которой будет создано Web-приложение, зависит лишь от удобства и скорости разработки и простоты развертывания и поддержки конечного продукта.
    Преимущество технологии ASP.NET перед остальными в высокой степени абстракции, построенной над стандартным HTML кодом: использование объектно-ориентированной парадигмы, поддержку нескольких языков программирования, наличие универсального основания, содержащего тысячи уже готовых для использования в проектах решений – Microsoft .NET Framework.
При этом для разработки приложения может быть использована любая среда разработки или даже текстовый редактор, позволяющий создавать, редактировать и сохранять текстовые файлы. Если же разработчик желает воспользоваться всей мощью Microsoft .NET Framework и ASP.NET и, при этом, затратить как можно меньше усилий, то ему нужно воспользоваться подходящей для его задач средой разработки. Одним из наиболее эффективных средств создания Web-приложений ASP.NET является Microsoft Visual Studio. Поддержка ASP.NET 2.0 включена в версию Visual Studio 2005.
    В данной статье кратко рассказывается о большинстве новых возможностей ASP.NET 2.0, новой версии среды ASP.NET. Далее в тексте считается, что читатель знаком с технологией ASP.NET 1.0 или ASP.NET 1.1. Если рассматриваемая тема выходит за рамки статьи, то непосредственно в тексте располагается гиперссылка на статью, содержащую подробную информацию. Также, в конце статьи приводится список литературы в порядке изложения информации в данной статье.

 

Использование нескольких языков программирования

Microsoft .NET Framework и Visual Studio 2005 поддерживает несколько языков программирования, таких как Visual Basic, Visual C#, Visual C++, Visual J#. Поскольку эти языки используют единую среду выполнения CLR (Common Language Runtime) и соответствуют общим стандартам CLS (Common Language Specification), то сборка, созданная с применением одного из .NET языков, может быть использована в проекте, разрабатываемом на другом языке программирования, также, как если бы эта сборка и приложение были написаны на одном и том же языке.
    С выходом Microsoft .NET Framework 2.0 стало возможно использовать в одном и том же проекте разные языки программирования. То, что Web-приложение ASP.NET может быть написано на нескольких языках программирования, очень удобно, если уже есть проверенные решения на одном из языков, а проект пишется с использованием другого языка, либо, если в команде имеются разработчики, использующие различные языки программирования. О том, как использовать разные языки в одном проекте можно прочитать в этой статье.

 


Технология разделения кода

Основа всего в Web-приложении – это страница. Пользователь, пользуясь браузером, перемещается между страницами, периодически возвращаясь к уже просмотренным ранее страницам, вводя какие-то данные в HTML формы и получая некоторый результат. В ASP.NET страница чаще всего представляет собой Web-форму, содержащую различные элементы управления, реагирующую на события, создаваемые пользователем.
    ASP.NET 1.x позволяет разделять код логики от кода представления, то есть помещать код программной логики страницы в файл .cs или .vb, отдельно от кода собственно страницы, размещаемом в .aspx файле. Эта технология называется Code-Behind. Таким образом, дизайн страницы может быть изменен не затрагивая кода страницы, что позволяет разделить ответственность за внешний вид и работу страницы между дизайнером и программистом. Для этого в .aspx файле можно задать параметры директивы Page.

<%@ Page Language="c#" Src="User.aspx.cs" %>

Но для поддержки редактирования с помощью Microsoft Visual Studio .NET в ASP.NET странице необходимо указать класс, соответствующей данной странице и файл, в котором находится код этого класса. Для этого директива Page преобразуется с использованием ключевых слов Codebenind и Inherits.

<%@ Page Language="c#" Codebehind="TheProject.User" Inherits="User.aspx.cs" %>

В ASP.NET 2.0 используется иной механизм разделения кода. В директиве Page при этом необходимо использовать другие ключевые слова: CodeFile и Inherits.

<%@ Page Language="c#" CodeFile="TheProject.User" Inherits="User.aspx.cs" %>

В этом случае код класса программной логики страницы будет размещен в файле указанном в атрибуте CodeFile. Надо отметить, что Visual Studio 2005 использует разделяемые классы (partial classes).

public partial class Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
    
     }
}

Поэтому разработчик может поместить код класса в нескольких файлах, но подобное рассредоточение кода делает приложение весьма громоздким и трудным в поддержке и разработке.
    Используемая в Visual Studio 2003 модель Code-Behind обладает несколькими весьма существенными недостатками. Прежде всего, используя Visual Studio разработчику необходимо компилировать проект перед публикацией, поскольку ASP.NET компилирует страницы, только если указан атрибут Src, не используемый Visual Studio. При этом, поскольку среда ASP.NET обнаруживает изменение даты создания сборки, после каждой замены старой сборки в каталоге bin происходит перезапуск домена приложения, что выливается во временную «заторможенность» в работе приложения.
    Visual Studio 2005 использует новые ключевые слова, поддерживаемые средой выполнения ASP.NET 2.0, а среда выполнения, в свою очередь, использует новую технику компиляции страниц. Это позволяет решить проблему замены сборки на более новую.
Несмотря на это, Visual Studio 2005 по-прежнему позволяет отказаться от разделения кода и поместить код программной логики в самом файле страницы, и использовать теги <script runat="server"></script>. Более того, по умолчанию Visual Studio создает именно страницы без разделения кода.

 

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

Сравним действия, которые совершает ASP.NET 2.0 и ASP.NET 1.0, когда пользователь запрашивает файл с расширением .aspx. В ASP.NET 1.x среда выполнения анализирует директиву Page страницы, осуществляет поиск соответствующего класса в сборке приложения, затем на основании кода страницы создается класс, производный от класса программной логики страницы. В случае если сборка отсутствует, то осуществляется поиск файла программной логики, указанного в атрибуте Src директивы Page. Если файл найден, то происходит компиляция сборки, если нет, то ASP.NET выбрасывает исключение.
    В ASP.NET 2.0 среда выполнения также анализирует директивы Page, осуществляет поиск сборки соответствующей классу логики страницы, после чего создается класс страницы. В отличие от ASP.NET 1.x, родительским классом для класса страницы является System.Web.UI.Page, поскольку создаваемый динамический класс является собственно классом страницы (используются разделяемые классы для класса страницы и класса программной логики), а не потомком класса программной логики. Поэтому, если в ASP.NET 1.x класс Web-формы мог называться также как и сама Web-форма.

<form id="frmDefault" runat="server"></form>

…

public class frmDefault : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
}

В ASP.NET 2.0 это недопустимо, поскольку элемент управления System.Web.UI.Form является элементом класса.
    Основным преимуществом ASP.NET является то, что в случае отсутствия сборки, необходимой для выполнения страницы, происходит компиляция только файла программной логики страницы, без перекомпиляции всей сборки. Поскольку существует динамическая компиляция, то необходимо обеспечить возможность создавать код, общий для всех страниц приложения. Для этой цели в ASP.NET 2.0 существуют специальные директории, являющиеся дочерними директориями корневой директории приложения, одна из которых App_Code, служит для хранения файлов, содержащих общий код для всех страниц. При выполнении динамической компиляции, код из директории App_Code компилируется и становится доступным для всех страниц Web-приложения. При этом Visual Studio 2005 поддерживает код, находящийся в директории App_Code, поэтому работает подсветка синтаксиса и IntelliSense.
    Исследовать генерируемые средой выполнения ASP.NET 2.0 файлы, и подробно разобраться в процессе компиляции можно изучив содержимое директории: %WINDIT%\Microsoft.NET\Framework\версия\Temporary ASP.NET Files\имя_приложения, куда ASP.NET 2.0 помещает динамически созданные сборки. Либо, вызвав ошибку на ASP.NET странице в режиме отладки выбрать ссылку Show Complete Compilation Source.

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

 

Изменения в структуре проекта Visual Studio

В версии Visual Studio 2005 больше нет файлов .csproj или .vbproj, которые раньше создавались для каждого из типов проектов ASP.NET. Вместо файлов проекта Visual Studio использует структуру директорий, таким образом, для того чтобы включить в проект существующий файл достаточно просто скопировать его в директорию проекта. Следует отметить, что если файл или директория удаляется из дерева файлов проекта в окне Solution Explorer, то файл или директория физически удаляются из файловой системы.

 

Страница ASP.NET 2.0

Директива @Page

Для внесения новых возможностей в ASP.NET 2.0 было необходимо внести изменения и дополнения в класс страницы Page. Поскольку для установке свойств страницы в design-time используются атрибуты директивы Page, то здесь будут рассмотрены новые атрибуты, появившиеся для реализации механизмов персонализации, шаблонов дизайна, оформления и асинхронной работы станиц. Подробнее о назначении новых атрибутов можно узнать в части статьи, посвященной новым свойствам и методам класса Page.

Async

Указывает на то, какой из интерфейсов IHttpHandler или IHttpAsyncHandler реализует класс страницы. После установки этого атрибута в true, генерируемый динамически класс страницы будет реализовать от IHttpAsyncHandler, в противном случае класс будет реализовать IHttpHandler. Если класс страницы реализует IHttpAsyncHandler, то код страницы может выполнятся асинхронно до наступления нового события в жизненном цикле страницы PreRender, ко времени наступления которого происходит синхронизация и подготовка HTML-кода для отправки браузеру клиента.

AsyncTimeOut

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

Culture

Устанавливает набор региональных параметров (Culture), используемый для страницы.

EnableTheming

Позволяет включить или выключить поддержку тем оформления. По умолчанию включено.

MasterPageFile

Указывает путь к шаблону, который будет использован для создания кода этой страницы.

StyleSheetTheme

Позволяет установить идентификатор темы оформления, которая будет использоваться для изменения установленной темы оформления (в атрибуте Theme или в файле web.confg). Таким образом можно установить общую тему оформления для всего сайта, а с помощью атрибута StyleSheetTheme вносить некоторые изменения в общее оформление страницы и/или некоторых элементов управления, содержащихся на странице.

Theme

Указывает название темы оформления, которая будет использована для оформления кода данной страницы.

UICulture

Устанавливает набор региональных параметров (Culture), используемый для пользовательского интерфейса страницы.

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

Жизненный цикл страницы ASP.NET начинается с получения и обработки Web-сервером IIS запроса к данной странице и передачи этого запроса среде выполнения ASP.NET. В момент получения запроса, среда выполнения загружает класс вызываемой страницы, устанавливает свойства класса страницы, выстраивает дерево элементов, заполняет свойства  Request и Response и вызывает метод IHttpHandler.ProcessRequest. После этого среда выполнения проверяет каким образом была вызвана эта страницы и если страница вызвана путем передачи данных с другой страницы, о чем будет рассказано далее, то среда выполнения устанавливает свойство PreviousPage.
    Стоит отметить также, что помимо рассмотренных ниже этапов выполнения страницы существуют еще и этапы уровня приложения, не специфичные для страницы. Подробно об этапах выполнения приложения написано в этой статье.

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

Во время прохождения этапов жизненного цикла возникают события, подписавшись на которые, разработчик может выполнять свой собственный код. Стоит упомянуть атрибут AutoEventWireup, директивы @Page: если этот атрибут установлен в true (значение по умолчанию), то методы класса страницы, названные Page_НазваниеСобытия, автоматически становятся обработчиками соответствующих событий жизненного цикла станицы.
    Для того, чтобы проследить жизненный цикл страницы и последовательность возникновения событий, можно установить атрибут
Trace директивы @Page в true, а атрибут TraceMode в "SortByTime". Тогда в разделе Trace Information можно найти список произошедших событий (колонка Message). Например:

Trace Information

Category Message From First(s) From Last(s)
aspx.page Begin PreInit    
aspx.page End PreInit 0.0364973314167865 0.036497
aspx.page Begin Init 0.0379050459346291 0.001408
aspx.page End Init 0.047693704143491 0.009789
aspx.page Begin InitComplete 0.0477864508468221 0.000093
aspx.page End InitComplete 0.0481875670270608 0.000401
aspx.page Begin PreLoad 0.0489879732516718 0.000800
aspx.page End PreLoad 0.0494462283607275 0.000458
aspx.page Begin Load 0.0494924892194238 0.000046
aspx.page End Load 0.0553441897381414 0.005852
aspx.page Begin LoadComplete 0.0554711043059809 0.000127
aspx.page End LoadComplete 0.055942153615399 0.000471
aspx.page Begin PreRender 0.0561455634022874 0.000203
aspx.page End PreRender 0.0618604874695332 0.005715
aspx.page Begin PreRenderComplete 0.06269871008062 0.000838
aspx.page End PreRenderComplete 0.0633259746265858 0.000627
aspx.page Begin SaveState 0.080360541216174 0.017035
aspx.page End SaveState 0.213795377788888 0.133435
aspx.page Begin SaveStateComplete 0.213911298043872 0.000116
aspx.page End SaveStateComplete 0.214385763389788 0.000474
aspx.page Begin Render 0.214440078745078 0.000054
aspx.page End Render 0.315044337228923 0.100604


    Из всех событий жизненного цикла страницы, разработчик может подписаться только на пять, помимо событий дочерних элементов управления. Эти события:
PreInit, Init, Load, PreRender, Unload. Рассмотрим варианты использования этих событий.

Событие Использование
PreInit

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

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

Init На этом этапе разработчик может считывать или инициализировать свойства элементов управления.
Load На этом этапе разработчик может считывать или изменять свойства элементов управления.
PreRender Последняя возможность внести изменения во внешний вид страницы.
Unload Освобождение занятых ресурсов (закрытие открытых соединений с базой данных, завершение работы с файлами и т.п.)

Важно, что на этом этапе уже создано HTML представление страницы и попытка внести какие-либо изменения (например, вызвав метод Response.Write()), приведет к исключению.

Новые свойства и методы объекта Page

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

ClientScript

Содержит ссылку на экземпляр объекта ClientScriptManager, который позволяет работать с клиентскими скриптами (регистрировать блоки клиентского кода, создавать скрытые поля и т.п.)

EnableTheming

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

GetValidators

Метод, возвращающий коллекцию валидаторов данной страницы.

Header

Ссылка на объект HtmlHead, позволяющий контролировать содержимое раздела <head> HTML страницы, при условии, что для элемента head установлен атрибут runat="server".

IsAsync

Свойство, указывающее на способ обработки страницы – синхронный или асинхронный.

IsCrossPagePostBack

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

Master

Ссылка на экземпляр объекта шаблона страницы.

MasterPageFile

Свойство, содержащее имя файла шаблона страницы.

• MaxPageStateFieldLength

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

PageAdapter

Свойство возвращает объект PageAdapter, управляющий генерацией HTML представления страницы. Конкретный PageAdapter устанавливается средой выполнения в зависимости от параметров Requets. Если выбран PageAdapter, то события жизненного цикла страницы замещаются событиями PaeAdapter.

PreviousPage

Ссылка на экземпляр объекта страницы, с которой было осуществлено отправление формы.

SetFocus

Метод, позволяющий установить выделение на какой-либо из видимых на странице элементов управления.

StyleSheetTheme, Theme

Смотрите выше описание новых атрибутов директивы @Page.

TestDeviceFilter

Метод, проверяющий является ли текущий браузер браузером указанного в качестве аргумента типа.

Title

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

 

Использование новых объектов страницы ASP.NET 2.0

Объект ClientScriptManager

ClientScriptManager предоставляющий методы для работы с кодом сценариев, которые будут использоваться в клиентской части Web-приложения. Теперь все методы, которые в ASP.NET 1.x использовались для регистрации клиентских скриптов или скрытых полей принадлежат классу ClientScriptManager. Например, иногда бывает необходимо регистрировать клиентский сценарий динамически, в зависимости от каких-либо параметров. Например, при перезагрузке страницы форума нужно указать пользователю, что ему пришло новое личное сообщение. Это можно сделать как показано в нижеследующем примере.

protected void Page_Load(object sender, EventArgs e)
{
  if (CheckMail())
  {
      string startupScript = "<script>" + 
                "if(confirm('Вам пришло новое сообщение. Прочесть?'))" +
                "window.navigate('/ReadMail.aspx');" + 
                "</script>";
      ClientScript.RegisterStartupScript(this.GetType(), "MailAlertScript", startupScript);
  }
}

Объект HtmlHead

Для каждой страницы ASP.NET, в HTML коде которой присутствует тег <head runat="server"></head> автоматически создается экземпляр объекта HtmlHead, позволяющий управлять заголовком страницы, добавлять теги META и ссылки на каскадные таблицы стилей.
    Раньше разработчику страницы ASP.NET 1.0 приходилось добавлять специальное свойство или переменную в класс страницы или придумывать какой-либо обходной путь для того, чтобы получить возможность управлять заголовком и метаданными страницы. Например, так как это показано в следующем примере.

<head>
<title><%=Page.Title%></title>
<%=Page.MetaData%>
<%=Page.Css%>
</head>

С появлением объекта HtmlHead подобные ухищрения уходят в прошлое.

Page.Header.Title = "HtmlHead Test Page";
Page.Header.Metadata.Add("Author", "Gaidar Magdanurov");
Page.Header.Metadata.Add("E-Mail", "gaidar@vbstreets.ru");

Помимо этого, как и любой элемент, способный содержать вложенные элементы, HtmlHead позволяет добавлять произвольные элементы.

((Control)Page.Header).Controls.Add(new LiteralControl
      ("<meta http-equiv=\"Content-Type\" content=\"text/html; 
       charset=windows-1251\">"));

 

Управление страницей

Установка выделения на элемент управления

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

<form id="frmMain" runat="server" defaultfocus="txtFirstName">
<asp:TextBox ID="txtFirstName" runat="server"></asp:TextBox>
<asp:TextBox ID="txtSecondName" runat="server"></asp:TextBox>
<asp:TextBox ID="txtLastName" runat="server"></asp:TextBox>
</form>

Выделением можно управлять программно, вызывая метод SetFocus, в качестве параметра передавая уникальный идентификатор этого элемента:

protected void Page_Load(object sender, EventArgs e)
{
  if(isPostBack)
  {
      SetFocus("txtLastName");
  }
  else
  {
      SetFocus("txtFirstText");
  }
}


Обновление данных без перезагрузки страницы

В ASP.NET 2.0 стало возможным обновлять данные на странице без отправки страницы на сервер и ее полного обновления. Это стало возможно благодаря появлению клиентских сценариев с обратным вызовом (callback scripts или клиентские коллбэки). После того, как некоторое событие вызывает запрос к серверу, обновленные данные передаются непосредственно в клиентский сценарий в качестве аргументов функции.
    Подобный способ обновления данных на странице удобно и выгодно применять, когда для обновления всей информации требуется много ресурсов и достаточно длительное время, при этом эти часть данных обновляется часто, а остальные данные статичны. Тогда время на обновления данных, например, одного пользовательского элемента, учитывая время запроса к серверу, обработки и получения ответа, будет существенно ниже, чем время обновления всей страницы.
    Допустим, существует страница, на которой находится выпадающий список. Когда пользователь выбирает некоторое значение из списка, в некоторый элемент управления загружается значение, логически связанное с выбранным из списка значением. При этом задача такова, что нельзя хранить все данные на стороне клиента (возможно данных слишком много и страница будет долго передаваться по сети, либо данные генерируются на сервере не только в зависимости от выбранного пользователем элемента выпадающего списка). В ASP.NET 1.x для решения этой задачи необходимо привязать к событию изменения значения в выпадающем списке серверный метод. При этом список должен вызывать отправку страницы на сервер при каждом изменении значения (AutoPostBack="True").

protected void ddStatic_SelectedIndexChanged(object sender, EventArgs e)
{
// На основании значения ddStatic.Items[ddStatic.SelectedIndex].Value
// метод устанавливает свойства дригих элементов управления
}

В ASP.NET 2.0, как уже было сказано выше, существует возможность не обновлять всю страницу целиком. В данном случае разумно обновить только необходимые данные, поскольку обновлять всю страницу только для того, чтобы установить одно значение слишком расточительно.
    Для реализации механизма обновления данных без перезагрузки страницы необходимо создать клиентскую функцию обратного вызова, принимающую переданные с сервера параметры, серверную функцию, принимающую параметры от клиента и возвращающую клиенту значения на основании полученных параметров и связать эти две функции. Мало того, механизм обратного вызова в ASP.NET 2.0 позволяет возвращать результат асинхронно. Для этого в интерфейсе ICallbackEventHandler определены два метода: RaiseCallbackEvent, для получения параметров на сервере и GetCallbackResult для возвращения результата клиенту. Для реализации функциональности предыдущего примера в ASPX файле помещается следующий код.

<script>
function UpdateText(result, context) 
{ 
    dSpan.innerText = result;
}
</script>

<asp:DropDownList ID="ddDynamic" runat="server">

</asp:DropDownList><br />
<span id="dSpan" style="font-weight: bold;"></span>

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

public partial class ScriptCallback_aspx : 
  System.Web.UI.Page, System.Web.UI.ICallbackEventHandler { }

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

public virtual void PrepareCallbackEvent(string Аргументы)
public virtual string RenderCallbackResult()


private string EventArgument = "";


public void PrepareCallbackEvent(string eventArgument)
{
    EventArgument = eventArgument;
}

public string RenderCallbackResult()
{
    return EventArgument; // значение типа string
}

Последним шагом к поставленной цели является связывание серверной и клиентских функций.

protected void Page_Load(object sender, EventArgs e)
{
  // создаем ссылку на функцию обратного вызова
  string callbackFunction = Page.ClientScript.GetCallbackEventReference
  (
    this,
    "document.all['ddDynamic'].value",
    "UpdateText",
    "null"
  );

  // Привязываем сценарий к событию изменения значения выпадающего
  // списка
  ddDynamic.Attributes["onchange"] = String.Format("javascript:{0}", 
  callbackFunction);
}

Метод GetCallbackEventReference объекта ClientScriptManager принимает в качестве параметров ссылку на объект страницы, строку, указывающую на значение, которое необходимо передавать на сервер при обратном вызове, имя метода на стороне клиента и принимающего ответ сервера. Подробное описание можно получить в документации MSDN или с помощью инструмента Visual Studio - Object Browser.
    Используя эту технологию можно создавать сложные методы обновления данных страницы и позволяющие получить значительный выигрыш в производительности, для этого достаточно разобраться в том, какой код генерирует среда выполнения ASP.NET, реализуя эту функциональность.
 

// Список, вызывающий перезагрузку страницы
<select name="ddStatic"
onchange="javascript:setTimeout('__doPostBack(\'ddStatic\',\'\')', 0)"
id="ddStatic">
</select> 
// Список вызывающий метод с обратным вызовом
<select name="ddDynamic" id="ddDynamic"
onchange="javascript:WebForm_DoCallback
('__Page',document.all['ddDynamic'].value,UpdateText,null,null,false)">

Стандартная функция doPostBack весьма проста и служит для сохранения данных о событии в скрытые поля формы.

var theForm = document.forms['frmCallBack'];
function __doPostBack(eventTarget, eventArgument) {
  if (theForm.onsubmit == null || theForm.onsubmit()) {
    theForm.__EVENTTARGET.value = eventTarget;
    theForm.__EVENTARGUMENT.value = eventArgument;
    theForm.submit();
  }
}

При использовании функций с обратным вызовом механизм значительно сложнее. Код функции WebForm_DoCallback гораздо больше, чем doPostBack, поскольку эта функция определяет тип объектной модели браузера, после чего загружает необходимый для передачи данных с модуль. Например, для браузера поддерживающего DOM это будет Microsoft.XMLHTTP.
    Посмотреть код различных клиентских функций, используемых средой ASP.NET 2.0 можно сохранив страницу, поддерживающую функции с обратным вызовом на жесткий диск и открыв в текстовом редакторе файл WebResource.axd, ссылка на который имеется в HTML странице.
    Более подробное описание возможностей и области применения клиентских функций обратного вызова описано в статье Дино Эспозито.

Отправка данных формы другой странице ASP.NET

Существенное ограничением серверных форм в ASP.NET 1.0 – отсутствие возможности непосредственно передавать данные, введенные в форме, другой странице. Чтобы отправить значения элементов форму другой странице необходимо использовать простою HTML форму и в атрибуте action указать путь к странице, которая должна получить данные. При этом теряются преимущества использования серверных форм.
    В ASP.NET 2.0 тег элемента управления может иметь дополнительный атрибут PostBackUrl, позволяющий указать какой странице система должна передать Web-форму, если отправление данных на сервер инициировано этим элементом управления.

<form id="frmTest" runat="server">
<asp:textbox id="txtFirstName" runat="server" /><br />
<asp:textbox id="txtLastName" runat="server" /><br />
<asp:button id="btnSend" Text="Post Data" PostBackUrl="crosspost.aspx"
runat="server" />
</form>

После щелчка по кнопке, браузер пользователя будет переадресован на страницу crosspost.aspx, при этом вся информация об элементах управления формы, с которой произошло отправление данных, будет также передано.
    Чтобы реализовать эту возможность, среда ASP.NET 2.0 осуществляет проверку ASPX страниц на предмет наличия элементов управления с заданным атрибутом PostBackUrl и, при наличии таковых, создает на странице дополнительное скрытое поле __PREVIOUSPAGE, которое и содержит информацию о состоянии элементов формы. Эта информация доступна странице-получателю через свойство PreviousPage.
 

void Page_Load(object sender, EventArgs e)
{ 
if (PreviousPage != null) 
{
// Получаем объекты отправленной формы 
TextBox txtFirstName =
(TextBox)PreviousPage.FindControl("txtFirstName");
TextBox txtLastName =
(TextBox)PreviousPage.FindControl("txtLastName");

// Используем данные
txtInfo.Text = "Добрый день, " + txtFirstName.Text + "!";
}
}

На уровне HTML кода, отправка данных другой форме выглядит следующим образом.

<form method="post" action="GetValues.aspx" id="frmTest">

<input type="submit" name="btnSend" value="Post Data"
onclick="javascript:WebForm_DoPostBackWithOptions(
new WebForm_PostBackOptions(&quot;btnSend&quot;, &quot;&quot;, false,
&quot;&quot;, &quot;CrossPage.aspx&quot;, false, false))" id="btnSend" />
</form>

Из чего можно заключить, что данные формы не направляются из браузера непосредственно странице CrossPage.aspx, а предварительно направляются все той же странице GetValues.aspx, которая содержит форму frmTest. Это необходимо для поддержки серверной проверки (validation) введенных данных с использованием элементов управления RequiredFieldValidation, RangeValidation и других. Ознакомиться с методом WebForm_DoPostBackWithOptions можно в файле WebResource.axd, упомянутом в предыдущем параграфе этой статьи.

 

Шаблоны дизайна страниц

Что, прежде всего, отличает один Web-сайт от другого? Для простого пользователя сети Интернет основное отличие заключается в разнообразном дизайне странице. Прежде чем встретится с функциональными возможностями Web-приложения, посетитель сайта оценивает, нравится ли ему внешний вид страниц. Поэтому дизайн страниц является едва ли менее важным, чем общая функциональность.
    Задача разработчика писать код, а задача художника-дизайнера заниматься внешним оформлением и версткой HTML кода страниц. При этом в большинстве случаев необходимо обеспечить возможность параллельной работы над кодом приложения и HTML шаблоном. С этим весьма успешно справлялась технология разделения кода программной логики и HTML кода страницы Code-Behind. Но, при этом, при работе над каждой страницей, разработчику приходится, так или иначе, сталкиваться с разметкой страницы.
Стоит заметить, что большинство современных Web-сайтов имеют сходный внешний вид всех страниц и каждая страница имеет общие элементы дизайна. В ASP.NET 1.x общие элементы дизайна страниц заключали в пользовательские элементы управления и включались в каждую страницу, либо, наоборот, страницы преобразовывали в элементы управления, используя одну страницу в качестве основы в которую загружали элементы управления в зависимости от строки URL.
    Подход в ASP.NET 2.0 близок ко второму из названных подходов, но заключает в себе существенные преимущества. Разработчику больше нет нужды преобразовывать страницы в пользовательские элементы управления, что существенно упрощает разработку и отладку. А также существенно упрощает работу дизайнера, поскольку его задача сводится лишь во включении нескольких ASP.NET элементов в код страницы-шаблона. Для более подробного сравнения технологии шаблонов ASP.NET 2.0 с существующими ранее техниками использования шаблонов рекомендуется обратится к статье Фрица Оньена.

Создание шаблона дизайна

Шаблон дизайна страниц (Master pages) представляет собой обычную ASP.NET страницу, обладающую несколькими дополнительными атрибутами и свойствами и содержащую один или несколько специальных элементов управления ContentPlaceHolder. Для того чтобы преобразовать обычную страницу в шаблон, достаточно заменить директиву Page на директиву Master.
После этого необходимо вставить в разметку страницы серверные элементы управления ContentPlaceHolder, в те части страницы, где будет размещаться информация, не относящаяся к общему дизайну.

<%@ Master Language="C#" CodeFile="MainMaster.master.cs"
Inherits="MainMaster_master" %>

<html>
<head runat="server">
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Моя домашняя страница</title>
</head>
<body>
<table width="100%">
  <tr>
    <span id="PageTitle" runat="server"></span>
  </tr>
  <tr>
    <table width="100%">
      <tr>
       <td>
          <asp:contentplaceholder id="PageMenu" 
          runat="server"></asp:contentplaceholder>
       </td>
       <td>
     <form runat="server">
       <asp:contentplaceholder id="PageContent" 
       runat="server"></asp:contentplaceholder>
     </form>
    </td>
  </tr>
</table>
</tr>
<tr>
<p align="right">Время: <span id="PageTime" runat="server"></span></p>
</tr>
</table>
</body>
</html>

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

<asp:contentplaceholder id="PageMenu" runat="server">
<ul>
<li><a href="Default.aspx">Главная страница</a></li>
<li><a href="Contents.aspx">Оглавление</a></li>
</ul>
</asp:contentplaceholder>

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

protected void Page_Load(object sender, EventArgs e)
{
    PageTime.InnerText = DateTime.Now.ToShortDateString();
}

public string Title
{
  get
  {
    return PageTitle.InnerText;
  }
  set
  {
    PageTitle.InnerText = value;
  }
}

Создание страницы

Использование шаблонов дизайна налагает свои требования на страницы. Поскольку шаблон содержит элементы управления ContentPlaceHolder, то страница должна содержать элементы управления Content, содержащие код разметки и другие элементы управления, которые будут отображать на результирующей странице. На странице не должно быть каких-либо серверных элементов управления или кода разметки вне элементов управления Content.

<%@ Page Language="C#" CodeFile="Default.aspx.cs" Inherits="Default_aspx"
MasterPageFile="MainMaster.master"%>

<asp:content runat="server" id="MyMenu" contentplaceholderID="PageMenu">
<ul>
<li><a href="Page1.aspx">Страница 1</a></li>
<li><a href="Page2.aspx">Страница 2</a></li>
<li><a href="Page3.aspx">Страница 3</a></li>
</ul>
</asp:content>

<asp:content runat="server" ID="MyContent" contentplaceholderID="PageContent">
<asp:TextBox id="txtName" runat="server"></asp:TextBox>&nbsp;
<asp:Button id="btnShow" runat="server" Text="Показать"
OnClick="btnShow_Click" /><br />
<asp:PlaceHolder ID="PlaceHolder" runat="server"></asp:PlaceHolder>
</asp:content>


Также как и в случае с шаблоном, код логики страницы создается обычным образом. Единственное отличие в том, что страница не имеет собственных объектов вроде HeadControl, поэтому нужно использовать ссылку на страницу шаблона через свойство Master.

protected void Page_Load(object sender, EventArgs e)
{
  if (!Page.IsPostBack) Master.Page.Header.Title = "Домашняя страница";
}
protected void btnShow_Click(object sender, EventArgs e)
{
  PlaceHolder.Controls.Add(
     new LiteralControl("<script> alert('Добрый день, " 
     + txtName.Text + 
     "'); </script>"));
   Master.Page.Header.Title = "Добрый день, " + txtName.Text;
}


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

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>
<pages master="MainMaster.master" />
</system.web>
</configuration>

Кроме того, ASP.NET позволяет устанавливать тему оформления программным образом. Как было сказано выше, загрузка и связывание с шаблоном оформления происходит во время подготовки страницы к инициализации. Поэтому, если необходимо сменить шаблон оформления страницы, необходимо делать это в обработчике события PreInit.

protected void Page_PreInit(object sender, EventArgs e)
{
   Page.MasterPageFile = "AnotherMaster.master";
}

Обработка шаблонов средой ASP.NET

Во время первого обращения к какой-либо странице, ASP.NET осуществляет поиск и компиляцию сборок для всех шаблонов в директории. Эта операция занимает некоторое время, зависящее от количества страниц шаблонов в директории, но выполняется только один раз. Поэтому, если в директории присутствуют не использующиеся шаблоны, это не приводит к потерям производительности в процессе работы приложения, единственное неудобство – дополнительное время, а компиляцию ненужных сборок для неиспользуемых страниц.
    При обращении к aspx файлу страницы с заданным шаблоном оформления процесс компиляции почти ничем не отличается от обычного процесса компиляции страницы, за исключением того, что создается класс шаблона MasterPage ссылка на который доступна в свойстве Page.Master.
    Затем страница проходит все те шаги, которые описаны выше в этой статье, в результате чего генерируется HTML код, который отправляется клиенту. В полученном браузером HTML коде уже нельзя определить, какая часть кода задана в шаблоне оформления, а какая часть кода определена на самой странице, поскольку элементы управления ContentPlaceHolder и Content не имеют каких-либо HTML соответствий и не порождают дополнительных тегов, кроме своего содержимого.

<html>
<head id="ctl00_Head1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Домашняя страница</title>
</head>
<body>
<table width="100%">
<tr>
<span id="ctl00_PageTitle"></span>
</tr>
<tr>
<table width="100%">
<tr>
<td>
<ul>
<li><a href="Page1.aspx">Страница 1</a></li>
<li><a href="Page2.aspx">Страница 2</a></li>
<li><a href="Page3.aspx">Страница 3</a></li>
</ul>
</td>
<td>
<form method="post" action="default.aspx" id="__aspnetForm">
<div>
<input type="hidden" name="__VIEWSTATE" value="" />
</div>
<input name="ctl00$PageContent$txtName" type="text" id="ctl00_PageContent_txtName" />
&nbsp;
<input type="submit" name="ctl00$PageContent$btnShow" value="Показать" 
id="ctl00_PageContent_btnShow" /><br />
</form>
</td>
</tr>
</table>
</tr>
<tr>
<p align="right">Время: <span id="ctl00_PageTime">20.03.2005</span></p>
</tr>
</table>
</body>
</html>

Поскольку шаблон является подмножеством страницы, то допустимо создавать вложенные шаблоны, указывая для шаблона в директиве Master путь к другому шаблону с помощью атрибута MasterPageFile. Для этого необходимо в основном шаблоне определить элементы управления ContentPlaceHolder, а в «дочерних» шаблонах на ряду с ContentPlaceHolder элементами определить элементы управления Content для замещения содержимого элементов ContentPlaceHolder базового шаблона.

Использование разных шаблонов для разных браузеров

Любому Web-разработчику хорошо известно, что разные браузеры (например, Microsoft Internet Explorer, Netscape Navigator, Mozilla FireFox и др.) по разному обрабатывают HTML код и, что особенно важно, обладают несколько разными программируемыми моделями, что усложняет создание клиентских сценариев.
    Для разрешения этой проблемы существует два основных метода, которые используются и в ASP.NET 1.x и в классическом ASP. Первый заключается в том, что браузеру клиента отправляется клиентский код, который, основываясь на типе и версии браузера, выполняет некоторые действия. Второй состоит в перенаправлении браузера пользователя на те страницы, которые специально оптимизированы под конкретный браузер. ASP.NET упрощает создание подобных страниц, поскольку среда выполнения генерирует HTML код для стандартных серверных элементов управления основываясь на информации о браузере клиента. При использовании шаблонов оформления, можно создать несколько шаблонов, для каждого браузера и в директиве Page страницы указать, какой шаблон использовать.

<%@ Page ie:MasterPageFile="ieMainTemplate.master" 
opera:MasterPageFile="operaMainTemplate.master " 
mozilla:MasterPageFile="mozillaMainTemplate.master " %>

Список браузеров и используемые средой ASP.NET свойства браузеров можно найти в директории %WINDIT%\Microsoft.NET\Framework\версия\CONFIG\Browsers.
 

 

Упрощенная локализация Web-приложений

Определение региональных настроек пользователя

Для локализации приложений в ASP.NET 1.x разработчику часто приходилось писать код для определения региональных настроек пользователя. Этот код часто помещался в global.asax и его задачей стояла установка языка пользователя в качестве языка текущего процесса, путем создания объекта CultureInfo и присвоения его свойствам CurrentCulture и CurrentUICulture объекта CurrentThread:

void Application_BeginRequest (Object sender, EventArgs e)
{
  if (Request.UserLanguages.Length > 0) 
  {
    CultureInfo UserCulture = CultureInfo.CreateSpecificCulture(
      Request.UserLanguages[0]);
    Thread.CurrentThread.CurrentCulture = UserCulture;
    Thread.CurrentThread.CurrentUICulture = UserCulture;
  }
}

В ASP.NET 2.0 существует возможность переложить определение региональных настроек пользователя на среду выполнения. Достаточно установить атрибуты Culture="auto" и UICulture="auto" директивы @Page, чтобы для страницы региональные настройки пользователя определялись автоматически. В случае. если необходимо достичь этого эффекта на всех страницах сайта, достаточно в файл web.config добавить следующую строку:

<globalization culture="auto" uiCulture="auto" />

Выражения для локализации

ASP.NET 2.0 позволяет генерировать сборки с локальными ресурсами для каждой страницы и связывать элементы управления с данными, хранимыми в этих ресурсах с помощью выражений, размещаемых непосредственно в коде представления в ASPX файле. Для этого используется атрибут meta:resourcekey, значение которого анализируется во время выполнения страницы.

<asp:LinkButton id="lnkSelectLanguage" PostBackUrl="SelectLanguage.aspx" runat="server"
  meta:resourcekey="SelectLanguageResource">Select Language</asp:LinkButton>

Либо может быть использовано новое выражение <%$ resources: [applicationkey], resourcekey%>:

<asp:ImageButton id="btnSelectLanguage" Runat="server" 
ImageUrl="~/Images/SelectLanguage.jpg" 
AlternateText='<%$ Resources: SelectLanguage %>' PostBackUrl="SelectLanguage.aspx" />

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

<asp:Localize id="localText" runat="server" meta:resourcekey="TheText">Text</asp:Localize>

или

<asp:Localize id="localText" runat="server" text='<%$ resources: TextResources, TheText %>'>
Text</asp:Localize>

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

 

Заключение

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

 

Благодарности

Данная статья была написана еще на Beta 1 для книги GotDotNet Community Book - проект по написанию книги активными участниками сообщества GotDotNet. К сожалению проект оказался нежизнеспособен и книга не была написана. Разумеется, что информация по Beta 1 была неактуальна к моменту публикации. Поэтому я хочу поблагодарить Виктора Шатохина, указавшего на фрагменты статьи, ставшие неактуальными и, таким образом, заставившего переписать статью. Спасибо!
 

 

Дополнительная литература

  1. Common Language Runtime Overview

  2. Домашняя страница Common Language Runtime

  3. What is the Common Language Specification?

  4. ASP.NET Code-Behind Model Overview

  5. ASP.NET Web Page Code Model

  6. ASP.NET Compilation Overview

  7. Прекомпиляция сайта в ASP.NET 2.0

  8. Partial Types

  9. Новинки языка C# 2.0

  10. IHttpAsyncHandler Interface

  11. IHttpHandler Interface

  12. Директива @ Page

  13. ASP.NET Application Life Cycle Overview

  14. ASP.NET Page Life Cycle Overview

  15. ClientScriptManager Class

  16. HtmlHead Class

  17. Script Callbacks in ASP.NET

  18. Implications of Script Callbacks in ASP.NET

  19. Custom Script Callbacks in ASP.NET

  20. Master Your Site Design with Visual Inheritance and Page Templates

  21. ASP.NET 2.0 Localization Features: A Fresh Approach to Localizing Web Applications


Может пригодится:


Автор: gaidar
Прочитано: 15749
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (2)

Прислал: prived
prived

Прислал: Timur
mne ponravilos

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру