Поделиться через


Общие сведения о веб-службах ASP.NET AJAX

Скотт Кейт

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

Вызов веб-служб с помощью ASP.NET AJAX

Дэн Валин (Dan Wahlin)

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

Хотя элемент управления UPDATEPanel ASP.NET AJAX предоставляет простой способ включения любой страницы ASP.NET, иногда может возникнуть время, когда необходимо динамически обращаться к данным на сервере без использования UpdatePanel. В этой статье вы узнаете, как это сделать, создавая и потребляя веб-службы на ASP.NET страницах AJAX.

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

Конфигурация веб-служб

При создании нового проекта веб-сайта в Visual Studio 2008 файл web.config имеет ряд новых дополнений, которые могут быть незнакомы пользователям предыдущих версий Visual Studio. Некоторые из этих изменений сопоставляют префикс asp с ASP.NET элементами управления AJAX, чтобы они могли использоваться на страницах, а другие определяют необходимые httpHandlers и HttpModules. В списке 1 показаны изменения, внесенные <httpHandlers> в элемент в web.config, который влияет на вызовы веб-службы. По умолчанию HttpHandler, используемый для обработки вызовов ASMX, удаляется и заменяется классом ScriptHandlerFactory, расположенным в сборке System.Web.Extensions.dll. System.Web.Extensions.dll содержит все основные функции, используемые ASP.NET AJAX.

Описание 1. настройка обработчика веб-службы ASP.NET AJAX

<httpHandlers>
     <remove verb="*" path="*.asmx"/>
     <add verb="*" path="*.asmx" validate="false"
          type="System.Web.Script.Services.ScriptHandlerFactory,
          System.Web.Extensions, Version=1.0.61025.0, Culture=neutral,
          PublicKeyToken=31bf3856ad364e35"/>
</httpHandlers>

Эта замена HttpHandler выполняется для разрешения вызовов нотации объектов JavaScript (JSON) из ASP.NET страниц AJAX в веб-службы .NET с помощью прокси-сервера веб-службы JavaScript. ASP.NET AJAX отправляет сообщения JSON в веб-службы в отличие от стандартных вызовов протокола SOAP, которые обычно связаны с веб-службами. Это приводит к уменьшению числа сообщений запросов и ответов в целом. Кроме того, он позволяет более эффективно обрабатывать данные на стороне клиента, так как библиотека JavaScript ASP.NET AJAX оптимизирована для работы с объектами JSON. В списке 2 и листинге 3 показаны примеры сообщений запроса и ответа веб-службы, сериализованных в формат JSON. Сообщение запроса, показанное в списке 2, передает параметр страны со значением "Бельгия", а ответное сообщение в списке 3 передает массив объектов Customer и их связанных свойств.

Перечисление 2. Сериализованное в JSON сообщение запроса веб-службы

{"country":"Belgium"}

> [! ПРИМЕЧАНИЕ] Имя операции определяется как часть URL-адреса веб-службы; Кроме того, сообщения запросов не всегда отправляются через JSON. Веб-службы могут использовать атрибут ScriptMethod с параметром UseHttpGet, равным true, что приводит к передаче параметров строки запроса.

Описание 3. Сообщение ответа веб-службы сериализовано в JSON

[{"__type":"Model.Customer","Country":"Belgium","CompanyName":"Maison
     Dewey","CustomerID":"MAISD","ContactName":"Catherine
     Dewey"},{"__type":"Model.Customer","Country":"Belgium","CompanyName":"Suprêmes
     délices","CustomerID":"SUPRD","ContactName":"Pascale
     Cartrain"}]

В следующем разделе вы узнаете, как создавать веб-службы, способные обрабатывать сообщения запроса JSON и отвечать на них как с простыми, так и сложными типами.

Создание веб-служб с поддержкой AJAX

Платформа AJAX ASP.NET предоставляет несколько различных способов вызова веб-служб. Вы можете использовать элемент управления AutoCompleteExtender (доступный в наборе средств AJAX ASP.NET) или JavaScript. Однако перед вызовом службы необходимо включить ajax-enable его, чтобы его можно было вызвать с помощью кода клиентского скрипта.

Независимо от того, вы не знакомы с ASP.NET веб-службами, вы найдете простое создание и включение AJAX служб. Платформа .NET поддерживает создание веб-служб ASP.NET с момента его первоначального выпуска в 2002 году, а расширения AJAX ASP.NET предоставляют дополнительные функциональные возможности AJAX, которые создаются на основе набора функций платформы .NET Framework по умолчанию. Visual Studio .NET 2008 Beta 2 имеет встроенную поддержку создания файлов веб-службы ASMX и автоматически получает связанный код рядом с классами System.Web.Services.WebService. При добавлении методов в класс необходимо применить атрибут WebMethod для их вызова потребителями веб-службы.

В описании 4 показан пример применения атрибута WebMethod к методу GetCustomersByCountry().

Перечисление 4. Использование атрибута WebMethod в веб-службе

[WebMethod]
public Customer[] GetCustomersByCountry(string country)
{
     return Biz.BAL.GetCustomersByCountry(country);
}

Метод GetCustomersByCountry() принимает параметр страны и возвращает массив объектов Customer. Значение страны, передаваемое в метод, пересылается в класс бизнес-слоя, который, в свою очередь, вызывает класс слоя данных для получения данных из базы данных, заполняет свойства объекта Customer данными и возвращает массив.

Использование атрибута ScriptService

При добавлении атрибута WebMethod метод GetCustomersByCountry() вызывается клиентами, отправляющими стандартные сообщения SOAP в веб-службу, он не позволяет выполнять вызовы JSON из ASP.NET приложений AJAX из поля. Чтобы разрешить вызовы JSON, необходимо применить атрибут расширения AJAX ScriptService ASP.NET к классу веб-службы. Это позволяет веб-службе отправлять сообщения ответа, отформатированные с помощью JSON, и позволяет клиентскому скрипту вызывать службу, отправляя сообщения JSON.

В описании 5 показан пример применения атрибута ScriptService к классу веб-службы с именем CustomersService.

Описание 5. Использование атрибута ScriptService для AJAX-enable a Web Service

[System.Web.Script.Services.ScriptService]
[WebService(Namespace = "http://xmlforasp.net")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class CustomersService : System.Web.Services.WebService
{
     [WebMethod]
     public Customer[] GetCustomersByCountry(string country)
     {
          return Biz.BAL.GetCustomersByCountry(country);
     }
}

Атрибут ScriptService выступает в качестве маркера, указывающего, что его можно вызвать из кода скрипта AJAX. Он фактически не обрабатывает какие-либо задачи сериализации или десериализации JSON, которые происходят за кулисами. ScriptHandlerFactory (настроенный в web.config) и другие связанные классы выполняют большую часть обработки JSON.

Использование атрибута ScriptMethod

Атрибут ScriptService является единственным атрибутом ASP.NET AJAX, который должен быть определен в веб-службе .NET, чтобы он использовался ASP.NET страницами AJAX. Однако другой атрибут с именем ScriptMethod также можно применять непосредственно к веб-методам в службе. ScriptMethod определяет три свойства, включая UseHttpGetResponseFormat и XmlSerializeString. Изменение значений этих свойств может быть полезно в случаях, когда тип запроса, принятый веб-методом, необходимо изменить на GET, если веб-метод должен возвращать необработанные XML-данные в виде XmlDocument или объекте или XmlElement когда данные, возвращаемые из службы, всегда должны быть сериализованы как XML вместо JSON.

Свойство UseHttpGet можно использовать, если веб-метод должен принимать запросы GET, а не запросы POST. Запросы отправляются с помощью URL-адреса с входными параметрами веб-метода, преобразованными в параметры QueryString. Свойство UseHttpGet по умолчанию имеет значение false и должно быть задано true только в том случае, если операции, как известно, являются безопасными и когда конфиденциальные данные не передаются в веб-службу. В списке 6 показан пример использования атрибута ScriptMethod со свойством UseHttpGet.

Описание 6. Использование атрибута ScriptMethod со свойством UseHttpGet.

[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public string HttpGetEcho(string input)
{
     return input;
}

Ниже показаны примеры заголовков, отправленных при вызове веб-метода HttpGetEcho, показанного в списке 6:

GET /CustomerViewer/DemoService.asmx/HttpGetEcho?input=%22Input Value%22 HTTP/1.1

Помимо разрешения веб-методов принимать HTTP-запросы GET, атрибут ScriptMethod также можно использовать, если xml-ответы необходимо возвращать из службы, а не JSON. Например, веб-служба может получить RSS-канал из удаленного сайта и вернуть его в виде объекта XmlDocument или XmlElement. Обработка XML-данных может происходить на клиенте.

В списке 7 показан пример использования свойства ResponseFormat для указания того, что XML-данные должны быть возвращены из веб-метода.

Описание 7. Использование атрибута ScriptMethod со свойством ResponseFormat.

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public XmlElement GetRssFeed(string url)
{
     XmlDocument doc = new XmlDocument();
     doc.Load(url);
     return doc.DocumentElement;
}

Свойство ResponseFormat также можно использовать вместе со свойством XmlSerializeString. Свойство XmlSerializeString имеет значение false по умолчанию, что означает, что все типы возвращаемых значений, кроме строк, возвращаемых из веб-метода, сериализуются в формате XML, если ResponseFormat для свойства задано значение ResponseFormat.Xml. Если XmlSerializeString задано значение true, все типы, возвращаемые из веб-метода, сериализуются в формате XML, включая типы строк. Если свойство ResponseFormat имеет значение свойства ResponseFormat.Json XmlSerializeString, игнорируется.

В описании 8 показан пример использования свойства XmlSerializeString для принудительной сериализации строк в формате XML.

Описание 8. Использование атрибута ScriptMethod со свойством XmlSerializeString

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml,XmlSerializeString=true)]
public string GetXmlString(string input)
{
     return input;
}

Значение, возвращаемое из вызова веб-метода GetXmlString, показанного в списке 8, отображается следующим образом:

<?xml version="1.0"?>
     <string>Test</string>

Хотя формат JSON по умолчанию сводит к минимуму общий размер сообщений запроса и ответа и становится более легко потребляемым клиентами AJAX ASP.NET клиентами AJAX в нескольких браузерах, свойства ResponseFormat и XmlSerializeString можно использовать, когда клиентские приложения, такие как Internet Explorer 5 или выше, ожидают, что xml-данные будут возвращены из веб-метода.

Работа со сложными типами

В списке 5 показан пример возврата сложного типа с именем Customer из веб-службы. Класс Customer определяет несколько различных простых типов внутри себя как свойства, такие как FirstName и LastName. Сложные типы, используемые в качестве входного параметра или возвращаемого типа в веб-методе с поддержкой AJAX, автоматически сериализуются в JSON перед отправкой на стороне клиента. Однако вложенные сложные типы (определенные внутри другого типа) по умолчанию недоступны клиенту в качестве автономных объектов.

В случаях, когда вложенный сложный тип, используемый веб-службой, также должен использоваться на клиентской странице, атрибут ASP.NET AJAX GenerateScriptType можно добавить в веб-службу. Например, класс CustomerDetails, показанный в списке 9, содержит свойства Address и Gender, представляющие вложенные сложные типы.

Описание 9. Класс CustomerDetails, показанный здесь, содержит два вложенных сложных типа.

public class CustomerDetails : Customer
{
     public CustomerDetails()
     {
     }
     Address _Address;
     Gender _Gender = Gender.Unknown;
     public Address Address
     {
          get { return _Address; }
          set { _Address = value; }
     }
     public Gender Gender
     {
          get { return _Gender; }
          set { _Gender = value; }
     }
}

Объекты Address и Gender, определенные в классе CustomerDetails, показанном в листинге 9, не будут автоматически доступны для использования на стороне клиента через JavaScript, так как они являются вложенными типами (Адрес является классом и полом является перечислением). В ситуациях, когда вложенный тип, используемый в веб-службе, должен быть доступен на стороне клиента, атрибут GenerateScriptType, упомянутый выше, можно использовать (см. описание 10). Этот атрибут можно добавить несколько раз в случаях, когда из службы возвращаются различные вложенные сложные типы. Его можно применять непосредственно к классу веб-службы или выше определенных веб-методов.

Описание 10. Использование атрибута GenerateScriptService для определения вложенных типов, которые должны быть доступны клиенту.

[System.Web.Script.Services.ScriptService]
[System.Web.Script.Services.GenerateScriptType(typeof(Address))]
[System.Web.Script.Services.GenerateScriptType(typeof(Gender))]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class NestedComplexTypeService : System.Web.Services.WebService
{
     //Web Methods
}

Применив GenerateScriptType атрибут к веб-службе, типы Address и Gender будут автоматически доступны для использования клиентским ASP.NET кодом JavaScript AJAX. Пример JavaScript, который автоматически создается и отправляется клиенту путем добавления атрибута GenerateScriptType в веб-службе, показан в списке 11. Далее в статье вы узнаете, как использовать вложенные сложные типы.

Описание 11. Вложенные сложные типы, доступные на странице ASP.NET AJAX.

if (typeof(Model.Address) === 'undefined')
{
     Model.Address=gtc("Model.Address");
     Model.Address.registerClass('Model.Address');
}
Model.Gender = function() { throw Error.invalidOperation(); }
Model.Gender.prototype = {Unknown: 0,Male: 1,Female: 2}
Model.Gender.registerEnum('Model.Gender', true);

Теперь, когда вы узнали, как создавать веб-службы и сделать их доступными для ASP.NET страниц AJAX, давайте рассмотрим, как создавать и использовать прокси JavaScript, чтобы получить или отправить данные в веб-службы.

Создание прокси-серверов JavaScript

Вызов стандартной веб-службы (.NET или другой платформы) обычно включает создание прокси-объекта, который защищает вас от сложностей отправки сообщений запроса и ответа SOAP. При ASP.NET вызовах веб-службы AJAX прокси-серверы JavaScript можно создавать и использовать для легкого вызова служб, не беспокоясь о сериализации и десериализации сообщений JSON. Прокси-серверы JavaScript можно создавать автоматически с помощью элемента управления ASP.NET AJAX ScriptManager.

Создание прокси-сервера JavaScript, который может вызывать веб-службы, выполняется с помощью свойства Служб ScriptManager. Это свойство позволяет определить одну или несколько служб, которые страница AJAX ASP.NET может вызывать асинхронно для отправки или получения данных, не требуя операций обратной передачи. Вы определяете службу с помощью элемента управления ASP.NET AJAX ServiceReference и назначения URL-адреса веб-службы свойству элемента управления Path . В описании 12 показан пример ссылки на службу с именем CustomersService.asmx.

<asp:ScriptManager ID="ScriptManager1" runat="server">
     <Services>
          <asp:ServiceReference Path="~/CustomersService.asmx" />
     </Services>
</asp:ScriptManager>

Перечисление 12. Определение веб-службы, используемой на странице ASP.NET AJAX.

Добавление ссылки на CustomersService.asmx через элемент управления ScriptManager приводит к динамическому созданию и ссылке на прокси-сервер JavaScript на страницу. Прокси-сервер внедряется с помощью <тега скрипта> и динамически загружается путем вызова файла CustomersService.asmx и добавления /js в конец файла. В следующем примере показано, как прокси-сервер JavaScript внедрен на страницу при отключении отладки в web.config:

<script src="CustomersService.asmx/js" type="text/javascript"></script>

> [! ПРИМЕЧАНИЕ. Если вы хотите увидеть фактический код прокси-сервера JavaScript, созданный, можно ввести URL-адрес нужной веб-службы .NET в поле адреса Internet Explorer и добавить /js в конец его.

Если отладка включена в web.config, то в страницу будет внедрена отладочная версия прокси-сервера JavaScript, как показано ниже:

<script src="CustomersService.asmx/jsdebug" type="text/javascript"></script>

Прокси-сервер JavaScript, созданный ScriptManager, также можно внедрить непосредственно на страницу, а не ссылаться с помощью <атрибута тега скрипта> . Это можно сделать, установив для элемента управления InlineScript свойство InlineScript элемента управления ServiceReference значение true (значение по умолчанию равно false). Это может быть полезно, если прокси-сервер не используется на нескольких страницах и когда вы хотите уменьшить количество сетевых вызовов, сделанных на сервере. Если для InlineScript задано значение true, скрипт прокси-сервера не будет кэширован браузером, поэтому значение по умолчанию false рекомендуется в случаях, когда прокси-сервер используется несколькими страницами в приложении AJAX ASP.NET. Ниже показан пример использования свойства InlineScript:

<asp:ServiceReference InlineScript="true" Path="~/CustomersService.asmx"/>

Использование прокси JavaScript

Когда веб-служба ссылается на страницу ASP.NET AJAX с помощью элемента управления ScriptManager, вызов можно сделать в веб-службе, а возвращаемые данные можно обрабатывать с помощью функций обратного вызова. Веб-служба вызывается путем ссылки на его пространство имен (если существует), имя класса и имя веб-метода. Все параметры, передаваемые веб-службе, можно определить вместе с функцией обратного вызова, обрабатывающей возвращаемые данные.

Пример использования прокси-сервера JavaScript для вызова веб-метода с именем GetCustomersByCountry() показан в описании 13. Функция GetCustomersByCountry() вызывается, когда конечный пользователь нажимает кнопку на странице.

Перечисление 13. Вызов веб-службы с прокси-сервером JavaScript.

function GetCustomerByCountry()
{
     var country = $get("txtCountry").value;
     InterfaceTraining.CustomersService.GetCustomersByCountry(country, OnWSRequestComplete);
}
function OnWSRequestComplete(results)
{
     if (results != null)
     {
          CreateCustomersTable(results);
          GetMap(results);
     }
}

Этот вызов ссылается на пространство имен InterfaceTraining, класс CustomersService и веб-метод GetCustomersByCountry, определенный в службе. Он передает значение страны, полученное из текстового поля, а также функцию обратного вызова с именем OnWSRequestComplete, которая должна вызываться при возврате асинхронного вызова веб-службы. OnWSRequestComplete обрабатывает массив объектов Customer, возвращаемых из службы, и преобразует их в таблицу, отображаемую на странице. Выходные данные, созданные из вызова, отображаются на рис. 1.

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

Рис. 1. Привязка данных, полученных путем асинхронного вызова AJAX к веб-службе. (Щелкните, чтобы просмотреть изображение полного размера)

Прокси-серверы JavaScript также могут выполнять одностороннее вызовы к веб-службам в случаях, когда веб-метод должен вызываться, но прокси-сервер не должен ждать ответа. Например, может потребоваться вызвать веб-службу, чтобы запустить процесс, например рабочий поток, но не ожидать возвращаемого значения из службы. В случаях, когда односторонний вызов должен быть выполнен в службу, функция обратного вызова, показанная в листинге 13, может быть просто опущена. Так как функция обратного вызова не определена, прокси-объект не будет ожидать возврата данных веб-службой.

Обработка ошибок

Асинхронные обратные вызовы к веб-службам могут столкнуться с различными типами ошибок, таких как сеть, недоступность веб-службы или возвращаемое исключение. К счастью, прокси-объекты JavaScript, созданные ScriptManager, позволяют определять несколько обратных вызовов для обработки ошибок и сбоев в дополнение к обратному вызову успешного выполнения, показанном ранее. Функцию обратного вызова ошибки можно определить сразу после стандартной функции обратного вызова в вызове веб-метода, как показано в описании 14.

Описание 14. Определение функции обратного вызова ошибки и отображение ошибок.

function GetCustomersByCountry() 
{
     var country = $get("txtCountry").value;
     InterfaceTraining.CustomersService.GetCustomersByCountry(country, 
          OnWSRequestComplete, OnWSRequestFailed);
}
function OnWSRequestFailed(error)
{
     alert("Stack Trace: " + error.get_stackTrace() + "/r/n" +
          "Error: " + error.get_message() + "/r/n" +
          "Status Code: " + error.get_statusCode() + "/r/n" +
          "Exception Type: " + error.get_exceptionType() + "/r/n" +
          "Timed Out: " + error.get_timedOut());
}

Все ошибки, возникающие при вызове веб-службы, активируют функцию обратного вызова OnWSRequestFailed(), которая принимает объект, представляющий ошибку в качестве параметра. Объект ошибки предоставляет несколько различных функций, чтобы определить причину ошибки, а также время ожидания вызова. В описании 14 показан пример использования различных функций ошибок и рис. 2 показан пример выходных данных, создаваемых функциями.

Выходные данные, созданные вызовом функций ошибок AJAX ASP.NET.

Рис. 2. Выходные данные, созданные путем вызова функций ошибки AJAX ASP.NET. (Щелкните, чтобы просмотреть изображение полного размера)

Обработка XML-данных, возвращаемых из веб-службы

Ранее вы узнали, как веб-метод может возвращать необработанные XML-данные с помощью атрибута ScriptMethod вместе со свойством ResponseFormat. Если параметр ResponseFormat имеет значение ResponseFormat.Xml, данные, возвращаемые из веб-службы, сериализуются как XML, а не JSON. Это может быть полезно, если xml-данные должны передаваться непосредственно клиенту для обработки с помощью JavaScript или XSLT. В настоящее время Internet Explorer 5 или более поздней версии предоставляет лучшую клиентская объектная модель для анализа и фильтрации XML-данных из-за встроенной поддержки MSXML.

Получение XML-данных из веб-службы не отличается от получения других типов данных. Начните с вызова прокси-сервера JavaScript для вызова соответствующей функции и определения функции обратного вызова. После возврата вызова можно обработать данные в функции обратного вызова.

В списке 15 показан пример вызова веб-метода GetRssFeed(), возвращающего объект XmlElement. GetRssFeed() принимает один параметр, представляющий URL-адрес для получения RSS-канала.

Описание 15. Работа с XML-данными, возвращаемыми из веб-службы.

function GetRss()
{
     InterfaceTraining.DemoService.GetRssFeed(
          "https://blogs.interfacett.com/dan-wahlins-blog/rss.xml",
          OnWSRequestComplete);
}
function OnWSRequestComplete(result)
{
     if (document.all) //Filter for IE DOM since other browsers are limited
     {
          var items = result.selectNodes("//item");
          for (var i=0;i<items.length;i++)
          {
               var title = items[i].selectSingleNode("title").text;
               var href = items[i].selectSingleNode("link").text;
               $get("divOutput").innerHTML +=
               "<a href='" + href + "'>" + title + "</a><br/>";
          }
     }
     else
     {
          $get("divOutput").innerHTML = "RSS only available in IE5+";
     }
}

Этот пример передает URL-адрес в RSS-канал и обрабатывает возвращенные XML-данные в функции OnWSRequestComplete(). В OnWSRequestComplete() сначала проверяет, доступен ли браузер Internet Explorer, чтобы узнать, доступен ли средство синтаксического анализа MSXML. Если это так, инструкция XPath используется для поиска всех <тегов элементов> в RSS-канале. Затем каждый элемент выполняет итерации, а связанные <теги заголовков> и <ссылок> находятся и обрабатываются для отображения данных каждого элемента. На рисунке 3 показан пример выходных данных, созданных при выполнении вызова ASP.NET AJAX через прокси-сервер JavaScript для веб-метода GetRssFeed().

Обработка сложных типов

Сложные типы, принятые или возвращенные веб-службой, автоматически предоставляются через прокси-сервер JavaScript. Однако вложенные сложные типы не доступны напрямую на стороне клиента, если атрибут GenerateScriptType не применяется к службе, как описано ранее. Почему вы хотите использовать вложенный сложный тип на стороне клиента?

Чтобы ответить на этот вопрос, предположим, что страница AJAX ASP.NET отображает данные клиента и позволяет конечным пользователям обновлять адрес клиента. Если веб-служба указывает, что тип адреса (сложный тип, определенный в классе CustomerDetails), можно отправить клиенту, процесс обновления можно разделить на отдельные функции для улучшения использования кода.

Выходные данные, создаваемые при вызове веб-службы, которая возвращает данные RSS.

Рис. 3. Выходные данные, создаваемые при вызове веб-службы, возвращающей RSS-данные. (Щелкните, чтобы просмотреть изображение полного размера)

В списке 16 показан пример клиентского кода, который вызывает объект Address, определенный в пространстве имен модели, заполняет его обновленными данными и назначает его свойству Address объекта CustomerDetails. Затем объект CustomerDetails передается в веб-службу для обработки.

Описание 16. Использование вложенных сложных типов

function UpdateAddress()
{
     var cust = new Model.CustomerDetails();
     cust.CustomerID = $get("hidCustomerID").value;
     cust.Address = CreateAddress();
     InterfaceTraining.DemoService.UpdateAddress(cust,OnWSUpdateComplete);
}
function CreateAddress()
{
     var addr = new Model.Address();
     addr.Street = $get("txtStreet").value;
     addr.City = $get("txtCity").value;
     addr.State = $get("txtState").value;
     return addr;
}
function OnWSUpdateComplete(result)
{
     alert("Update " + ((result)?"succeeded":"failed")+ "!");
}

Создание и использование методов страницы

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

ASP.NET AJAX предоставляет другой механизм для создания вызовов веб-службы без создания автономных asmx-файлов. Это делается с помощью метода, называемого "методами страницы". Методы страницы являются статическими (общими в VB.NET) методами, внедренными непосредственно в файл страницы или кода рядом с атрибутом WebMethod, примененным к ним. Применяя атрибут WebMethod, его можно вызывать с помощью специального объекта JavaScript с именем PageMethods, который динамически создается во время выполнения. Объект PageMethods выступает в качестве прокси-сервера, который защищает вас от процесса сериализации и десериализации JSON. Обратите внимание, что для использования объекта PageMethods необходимо задать для свойства EnablePageMethods свойства ScriptManager значение true.

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
</asp:ScriptManager>

В описании 17 показан пример определения двух методов страницы в классе ASP.NET кода рядом с ним. Эти методы извлекают данные из класса бизнес-слоя, расположенного в папке App_Code веб-сайта.

Описание 17. Определение методов страницы.

[WebMethod]
public static Customer[] GetCustomersByCountry(string country)
{
     return Biz.BAL.GetCustomersByCountry(country);
}
[WebMethod]
public static Customer[] GetCustomersByID(string id)
{
     return Biz.BAL.GetCustomersByID(id);
}

Когда ScriptManager обнаруживает наличие веб-методов на странице, она создает динамическую ссылку на объект PageMethods, упомянутый ранее. Вызов веб-метода выполняется путем ссылки на класс PageMethods, за которым следует имя метода и все необходимые данные параметров, которые должны быть переданы. В списке 18 показаны примеры вызова двух методов страниц, показанных ранее.

Описание 18. Вызов методов страницы с объектом JavaScript PageMethods.

function GetCustomerByCountry() 
{
     var country = $get("txtCountry").value;
     PageMethods.GetCustomersByCountry(country, OnWSRequestComplete);
}
function GetCustomerByID() 
{
     var custID = $get("txtCustomerID").value;
     PageMethods.GetCustomersByID(custID, OnWSRequestComplete);
}
function OnWSRequestComplete(results) 
{
     var searchResults = $get("searchResults");
     searchResults.control.set_data(results);
     if (results != null) GetMap(results[0].Country,results);
}

Использование объекта PageMethods очень похоже на использование прокси-объекта JavaScript. Сначала необходимо указать все данные параметров, которые должны передаваться методу страницы, а затем определять функцию обратного вызова, которая должна вызываться при возврате асинхронного вызова. Можно также указать обратный вызов сбоя (см. описание 14 примера обработки сбоев).

AutoCompleteExtender и набор средств AJAX ASP.NET

Набор средств AJAX (доступный из https://github.com/DevExpress/AjaxControlToolkit) ASP.NET предоставляет несколько элементов управления, которые можно использовать для доступа к веб-службам. В частности, набор средств содержит полезный элемент управления AutoCompleteExtender , который можно использовать для вызова веб-служб и отображения данных на страницах без написания кода JavaScript вообще.

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

Использование autoCompleteExtender на странице AJAX ASP.NET требует, чтобы сборка AjaxControlToolkit.dll была добавлена в папку корзины веб-сайта. После добавления сборки набора средств вы хотите ссылаться на нее в web.config, чтобы элементы управления, содержащиеся в нем, были доступны всем страницам в приложении. Это можно сделать, добавив следующий тег в тег элементов управления> web.config<:

<add namespace="AjaxControlToolkit" assembly="AjaxControlToolkit" tagPrefix="ajaxToolkit"/>

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

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" 
     TagPrefix="ajaxToolkit" %>

Использование элемента управления AutoCompleteExtender.

Рис. 4. Использование элемента управления AutoCompleteExtender. (Щелкните, чтобы просмотреть изображение полного размера)

После настройки веб-сайта для использования набора средств AJAX ASP.NET можно добавить элемент управления AutoCompleteExtender на страницу так же, как и обычный элемент управления ASP.NET сервера. В описании 19 показан пример использования элемента управления для вызова веб-службы.

Описание 19. Использование элемента управления autoCompleteExtender набора средств AJAX ASP.NET.

<ajaxToolkit:AutoCompleteExtender ID="extTxtCustomerID" runat="server"
     MinimumPrefixLength="1" ServiceMethod="GetCustomerIDs"
     ServicePath="~/CustomersService.asmx"
     TargetControlID="txtCustomerID" />

AutoCompleteExtender имеет несколько различных свойств, включая стандартные идентификаторы и свойства runat, найденные на элементах управления сервера. Помимо этого, вы можете определить, сколько символов типы конечных пользователей перед запросом веб-службы запрашиваются для данных. Свойство MinimumPrefixLength, показанное в листинге 19, приводит к тому, что служба вызывается при каждом вводе символа в текстовое поле. Необходимо тщательно задать это значение, так как каждый раз, когда пользователь вводит символ, веб-служба будет вызываться для поиска значений, соответствующих символам в текстовом поле. Веб-служба для вызова, а также целевого веб-метода определяется с помощью свойств ServicePath и ServiceMethod соответственно. Наконец, свойство TargetControlID определяет текстовое поле для перехвата элемента управления AutoCompleteExtender.

Вызываемая веб-служба должна применять атрибут ScriptService, как описано ранее, и целевой веб-метод должен принимать два параметра с именем префикса и счетчика. Параметр prefixText представляет символы, типизированные конечным пользователем, и параметр счетчика представляет количество возвращаемых элементов (значение по умолчанию — 10). В списке 20 показан пример веб-метода GetCustomerIDs, вызываемого элементом управления AutoCompleteExtender ранее в списке 19. Веб-метод вызывает метод бизнес-слоя, который в свою очередь вызывает метод слоя данных, который обрабатывает фильтрацию данных и возвращает результаты сопоставления. Код метода слоя данных показан в описании 21.

Описание 20. Фильтрация данных, отправляемых из элемента управления AutoCompleteExtender.

[WebMethod]
public string[] GetCustomerIDs(string prefixText, int count) 
{
     return Biz.BAL.GetCustomerIDs(prefixText, count);
}

Описание 21. Фильтрация результатов на основе входных данных конечных пользователей.

public static string[] GetCustomerIDs(string prefixText, int count)
{
     //Customer IDs cached in _CustomerIDs field to improve performance
     if (_CustomerIDs == null)
     {
          List<string> ids = new List<string>();
          //SQL text used for simplicity...recommend using sprocs
          string sql = "SELECT CustomerID FROM Customers";
          DbConnection conn = GetDBConnection();
          conn.Open();
          DbCommand cmd = conn.CreateCommand();
          cmd.CommandText = sql;
          DbDataReader reader = cmd.ExecuteReader();
          while (reader.Read())
          {
               ids.Add(reader["CustomerID"].ToString());
          }
          reader.Close();
          conn.Close();
          _CustomerIDs = ids.ToArray();
     }
     int index = Array.BinarySearch(_CustomerIDs, prefixText, new CaseInsensitiveComparer());
     //~ is bitwise complement (reverse each bit)
     if (index < 0) index = ~index;
     int matchingCount;
     for (matchingCount = 0; matchingCount < count && index + matchingCount < _CustomerIDs.Length; matchingCount++)
     {
          if (!_CustomerIDs[index + matchingCount].StartsWith(prefixText, StringComparison.CurrentCultureIgnoreCase))
          {
               break;
          }
     }
     String[] returnValue = new string[matchingCount];
     if (matchingCount > 0)
     {
          Array.Copy(_CustomerIDs, index, returnValue, 0, matchingCount);
     }
     return returnValue;
}

Заключение

ASP.NET AJAX обеспечивает отличную поддержку для вызова веб-служб без написания большого количества пользовательского кода JavaScript для обработки сообщений запроса и ответа. В этой статье вы узнали, как разрешить веб-службам .NET включить .NET, чтобы они могли обрабатывать сообщения JSON и как определять прокси JavaScript с помощью элемента управления ScriptManager. Вы также узнали, как прокси JavaScript можно использовать для вызова веб-служб, обработки простых и сложных типов и устранения сбоев. Наконец, вы узнали, как можно использовать методы страниц, чтобы упростить процесс создания и выполнения вызовов веб-службы и как элемент управления AutoCompleteExtender может помочь конечным пользователям по мере их ввода. Хотя UpdatePanel, доступный в ASP.NET AJAX, безусловно, будет элементом управления для многих программистов AJAX из-за простоты, зная, как вызывать веб-службы через прокси JavaScript может быть полезным во многих приложениях.

Биография

Дэн Wahlin (Microsoft Most Ценной профессионал для ASP.NET и ВЕБ-служб XML) является инструктором по разработке .NET и консультантом по архитектуре в Interface Technical Training (http://www.interfacett.com). Дэн основал XML-сайт для ASP.NET разработчиков (www.XMLforASP.NET), находится в Бюро спикера INETA и выступает на нескольких конференциях. Дэн совместно созданная профессиональная ДНК Windows (Wrox), ASP.NET: советы, руководства и код (Sams), ASP.NET 1.1 Insider Solutions, professional ASP.NET 2.0 AJAX (Wrox), ASP.NET 2.0 MVP Hacks и автор XML для ASP.NET разработчиков (Sams). Когда он не пишет код, статьи или книги, Дэн любит писать и записывать музыку и играть в гольф и баскетбол со своей женой и детьми.

Скотт Кейт работает с технологиями Microsoft Web с 1997 года и является президентом myKB.com (www.myKB.com), где он специализируется на написании ASP.NET основанных на приложениях, ориентированных на решения базы знаний. Скотт можно связаться по электронной почте по scott.cate@myKB.com электронной почте или в своем блоге по ScottCate.com