AJAX для ASP.NET и шаблоны на стороне клиента

ОГЛАВЛЕНИЕ

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

В сущности, настоящими приложениями AJAX являются те, которые используют для обхода обозревателя объект XMLHttpRequest и устанавливают прямую связь с веб-сервером и любыми размещенными конечными точками HTTP. Такие приложения способны асинхронно получать необходимые данные и независимо от этого обновлять нужные блоки интерфейса пользователя. Используя этот ключевой принцип, было разработано несколько сред AJAX, содержащих разные дозы «синтаксического сахара», большие или меньшие функциональные возможности, а также более или менее обширные наборы элементов управления для пользовательского интерфейса. Одна из таких сред — это AJAX для ASP.NET.

Спроектировать и собрать настоящее приложение AJAX непросто, тем более в отсутствие надлежащих средств программирования. По сравнению с другими платформами, AJAX для ASP.NET отличается хорошими возможностями доступа к коду на сервере. С точки зрения разработчика подключиться к поддерживающему сценарии веб-серверу или к службе Windows Communication Foundation (WCF) с помощью AJAX для ASP.NET — пустяковое дело. Нужно просто сослаться на URL-адрес, и платформа сама создаст класс прокси на языке JavaScript. Это просто и эффективно. Класс прокси скрывает все детали связей объекта XMLHttpRequest, сериализацию и десериализацию, форматы данных и пакетирование в HTTP. Нужно всего лишь вызвать метод асинхронно и получить обычный объект передачи данных (то есть DTO) с его собственным набором свойств.

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

Что же можно сделать для улучшения модели пользовательского интерфейса в настоящих веб-приложениях AJAX для ASP.NET? В прошлом месяце я познакомил вас с концепцией одностраничного интерфейса (Single-Page Interface, SPI) и с парой простых шаблонов проектирования, полезных при построении страниц SPI. Сегодня мы обсудим шаблоны на стороне клиента и привязку данных.

Типичная функция AJAX

Классической иллюстрацией возможностей подхода, предлагаемого AJAX, является приложение, которое выводит котировки акций в реальном времени. Веб-узлы, реализующие такую же функциональность без применения AJAX, используют тег метаобновления или решения, основанные на таких подключаемых модулях, как Flash, Silverlight™ или управляющие элементы ActiveX®. Обычно список величин котировок привязан на стороне сервера к управляющему элементу «сетка», который обновляется вместе с остальной страницей при каждой следующей обратной передаче или по запросу страницы. Такие страницы легко улучшаются внедрением частичной визуализации. Это можно сделать следующим образом: разметка, показанная на рис. 1, помещает управляющий элемент «сетка» в элемент UpdatePanel, который периодически обновляется с помощью управляющего элемента Timer.

Рис. 1 Пользовательский интерфейс страницы вывода котировок акций в реальном времени

<asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional">
  <ContentTemplate>
   <div style="margin:10px;">
    <asp:Label runat="server" ID="Label2" />
    <asp:GridView ID="GridView1" runat="server" SkinID="ClassicGrid"
     AutoGenerateColumns="false" 
     OnRowDataBound="GridView1_RowDataBound">
     <Columns>
      <asp:BoundField DataField="Symbol" HeaderText="SYMBOL" />
      <asp:BoundField DataField="Quote" HeaderText="LAST" >
       <ItemStyle HorizontalAlign="Right" />
      </asp:BoundField>
      <asp:BoundField DataField="Change" HeaderText="CHANGE" >
       <ItemStyle HorizontalAlign="Right" />
      </asp:BoundField>
     </Columns>
    </asp:GridView>
    <small><asp:Label runat="server" ID="Label1" /></small>
   </div> 
  </ContentTemplate>
  <Triggers>
   <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" /> 
  </Triggers> 
</asp:UpdatePanel>

<asp:Timer runat="server" id="Timer1" Enabled="true" 
  Interval="600000" OnTick="Timer1_Tick" />

Управляющий элемент «сетка» привязан к коллекции объектов, обладающих как минимум тремя свойствами: биржевой код, котировка и ее изменение. Содержимое сетки обновляется каждые 10 минут. Управляющий элемент «таймер» платформы AJAX для ASP.NET активирует таймер на стороне клиента, а когда время ожидания заканчивается, вызывает обратную передачу. Поскольку сетка обернута элементом UpdatePanel, котировки в ней обновляются независимо от остальной страницы. На стороне сервера при каждом сигнале таймера исполняется следующий код:

protected void Timer1_Tick(object sender, EventArgs e)
{
   Label2.Text = "<b>Last update: </b>" + DateTime.Now.ToLocalTime();
   GridView1.DataSource = picker.Update();
   GridView1.DataBind();
}

Объект «загрузчик» — это экземпляр пользовательского вспомогательного класса StockPicker. В этом классе находится экземпляр служебного класса, который получает данные котировок. Вот конструктор класса StockPicker:

public StockPicker(string stocks)
{
  string provider = ConfigurationManager.AppSettings["StockProvider"];
  _service = GetFactory(serviceProvider, stocks);

   if (_service == null)
    return;

   _desc = _service.GetServiceDescription();

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

interface IQuoteService
{
   StockInfoCollection GetQuotes();
   string GetServiceDescription();
}

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

public class StockInfo
{
   public string Symbol { get; set; }
   public string Quote { get; set; } 
   public string Change { get; set; }
   public string Day { get; set; }
   public string Time { get; set; } 
}

На рис. 2 показан пример страницы AJAX для ASP.NET, основанной на этом интерфейсе API, в действии.

 

Рис. 2 Страница обновляемых котировок с использованием частичной визуализации