Главная » Silverlight » Веб-служба REST и другие простые службы

0

В настоящее время простые веб-службы получают все большее распространение. Это объясняется тем, что они проще, чем протокол SOAP и стандарты WS-*. Конечно, простые веб-службы никогда не заменят веб-службы SOAP, потому что они не предо­ставляют многие средства распределенной обработки, такие как транзакции, марш­рутизация и т.п. Однако их чистая структура делает их идеальным инструментом для создания служб, совместимых с наиболее широким диапазоном клиентских устройств. Многие популярные сайты (Amazon, eBay, Google) предоставляют интерфейсы на основе как REST, так и SOAP.

Сравнение служб SOAP и REST

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

Полнофункциональная веб-служба SOAP размещает данные в специфичной структуре XML — документе SOAP. Документ SOAP может быть довольно длинным. Это означает, что создать сообщение SOAP на платформе, не содер­жащей встроенных средств SOAP, очень сложно. На платформе Silverlight нет встроенных средств SOAP. Чтобы не соз­давать документ XML вручную, в приложение Silverlight можно добавить ссылку на службу SOAP. Службы SOAP обла­дают существенными преимуществами. В них используются строго типизированные данные. Службу SOAP легко рас­ширять благодаря заголовкам SOAP (отдельным частям данных, которые можно передавать вместе с сообщением, но не в теле сообщения). Заголовки SOAP — ключевой инструмент расширения веб-служб на основе стандартов SOAP. В других веб-службах, в которых не применяется стандарт SOAP, используются более простые способы передачи ин­формации. Входные значения можно добавлять в адрес URL (они отслеживаются как параметры строки запроса) или предоставлять как пары "имя-значение" в теле сообщения. В любом случае накладные расходы небольшие, однако проверка типов отсутствует. В ответе простой веб-службы используется строка данных или код XML.

О простых веб-службах, возвращающих документ HTML, часто пишут как об использовании XML посредством про­токола HTTP. Часто их называют также службами REST, однако REST — это, скорее, концепция, а не конкретный стан­дарт. Основная идея REST (Representational State Transfer — передача презентационных состояний) состоит в том, что каждый URL представляет собой уникальный объект, а не вызов метода. Большинство веб-служб, позиционируемых как службы REST, не придерживаются этой идеи. Фактически они являются простыми службами, основанными не на стандартах SOAP.

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

В предыдущем разделе использовалась страница HTML с таблицей, содержащей информацию о населении Земли в разные периоды истории. Таблицу можно преобра­зовать в простую веб-службу. Для этого нужно создать код, принимающий год и воз­вращающий количество человек. Запрошенный год можно предоставить в аргументе строки запроса GET" или в теле запроса POST. Выбранная стратегия определяет класс, используемый в клиентской программе, — простой класс WebClient или более сложный класс WebRequest. Для обычных запросов GET класса WebClient достаточно, однако только более сложный класс WebRequest позволяет коду Silverlight передать значение.

Простую веб-службу можно создать на основе формы ASP.NET, однако для упроще­ния рекомендуется избегать полной модели форм. В конце концов, пользователю не нужна вся страница с элементами <html>, <head> и <body>. Вместо этого лучше создать обработчик HTTP.

Для создания обработчика HTTP откройте в Visual Studio окно проводника решений, щелкните правой кнопкой мыши на сайте ASP.NET и выберите в контекстном меню ко­манду Add New Item (Добавить новый элемент). Выберите шаблон Generic Handler, за­дайте имя и щелкните на кнопке Add. По умолчанию обработчик HTTP получает расши­рение . ashx. В данном примере обработчик называется PopulationService. ashx.

Каждый обработчик HTTP фактически является классом, реализующим интерфейс IHttpHandler. Обработчику нужно предоставить метод ProcessRequest О и процеду­ру чтения свойства IsReusable. Свойство IsReusable определяет, можно ли повторно использовать экземпляр обработчика HTTP для создания более одного запроса. Если в полях класса не хранится информация о состояниях, можно, не опасаясь ошибок, воз­вратить значение true.

public bool IsReusable

{

get { return true; }

}

Все необходимые операции выполняются в методе ProcessRequest (). Он получает объект HttpContext, посредством которого обращается к текущим параметрам запро­са и создает ответ. В данном примере метод ProcessRequest О проверяет передавае­мое именованное значение year. Затем код проверяет, есть ли в строке буквы, и по­лучает возвращаемое значение с помощью пользовательского метода GetPopulation (). Результат записывается на страницу как текст.

public void ProcessRequest (HttpContext context)

{

// Получение года

string year = context.Request.Form["year"];

// Удаление запятых и пробелов year = year.Replace(",", ""); year = year.Trim();

II Проверка года bool isBc = false; if (year.EndsWith("ВС", StringComparison.OrdinallgnoreCase))

{

isBc = true;

year = year.Remove(year.IndexOf("BC", StringComparison.OrdinallgnoreCase)) ;

year = year.Trim();

}

/ / Получение количества человек

int yearNumber = Int32.Parse(year) ;

int population = GetPopulation(yearNumber, isBc);

//Запись ответа

context.Response.ContentType = "text/plain"; context.Response.Write(population);

На стороне клиента необходимо использовать класс WebRequest пространства имен System.Net. Чтобы класс WebRequest был доступен, нужно добавить в проект ссылку на сборку System.Net.dll, которая по умолчанию не включена.

Для класса WebRequest необходимо, чтобы все операции выполнялись асинхронно. Сравните: класс WebClient выполняет одну асинхронную операцию (загружает ответ), а класс WebRequest — две (создает поток запроса и загружает ответ).

Чтобы применить класс WebRequest, нужно создать объект WebRequest и пра­вильную строку URL и вызвать метод BeginGetRequestStream (). При вызове метода BeginGetRequestStreamO ему нужно предоставить метод обратного вызова, который запишет запрос в поток запроса. В данном примере эту операцию выполняет метод CreateRequest () .

private string searchYear;

private void cmdGetData_Click (object sender,

RoutedEventArgs e)

{

Uri address = new Uri("http://localhost:" + HtmlPage.Document.DocumentUri.Port + "/ASPWebSite/PopulationService.ashx");

WebRequest request = WebRequest.Create (address) ;

request.Method = "POST";

request.ContentType = "application/x-www-form-urlencoded";

// Сохранение года

searchYear = txtYear.Text;

// Асинхронная подготовка запроса

request.BeginGetRequestStream(CreateRequest, request);

}

Перед вызовом метода BeginGetRequestStreamO код копирует год из текстово­го поля в закрытое поле searchYear. Это необходимо, чтобы метод обратного вызова CreateRequest () имел доступ к исходному году, даже если пользователь отредактирует текстовое поле перед выполнением метода CreateRequest (). Кроме того, это позволяет избежать проблем с потоками. Метод CreateRequest О выполняется в фоновом потоке (не в главном потоке приложения), поэтому он не может обращаться непосредственно к элементам страницы. Как показано в главе 16, проблем с потоками можно избежать с помощью метода Dispatcher .Beginlnvoke О , однако копирование позволяет решить эту проблему проще.

Обычно надстройка Silverlight вызывает метод CreateRequest () через долю секунды после запуска метода BeginGetRequestStreamO . В этот момент нужно записать значе­ние в запрос. Часто веб-службы используют для передаваемых значений тот же стан­дарт, что и формы HTML. Это означает, что каждый параметр передается как пара "имя- значение". Элементы пары отделены друг от друга знаком равенства (=). Пары отделены друг от друга знаками амперсанда (&), например FirstName=Matthew&LastName=MacDona Id. Для записи данных используется объект StreamWriter.

private void CreateRequest(IAsyncResult asyncResult)

{

WebRequest request = (WebRequest)asyncResult.AsyncState;

// Запись года в пару "имя-значение" (например, уеаг=1985)

Stream requestStream =

request.EndGetRequestStream(asyncResult); StreamWriter writer = new StreamWriter(requestStream); writer.Write("year=" + searchYear);

// Очистка потока (обязательная операция) writer.Close() ; requestStream.Close() ;

// Асинхронное чтение запроса

request.BeginGetResponse(ReadResponse, request)

}

После создания запроса нужно закрыть объект StreamWriter (дабы убедиться в том, что все данные записаны) и только после этого закрыть поток запроса. Затем нужно вызвать метод BeginGetResponse (), чтобы предоставить метод обратного вызова, кото­рый обработает поток ответа, когда он будет доступен. В данном примере эту операцию выполняет метод ReadResponse ().

Для чтения ответа используется объект StreamReader. Необходим также код обра­ботки исключений, возникающих, например, если служба не может быть найдена. Если в ответе используется код XML, необходимо обработать его.

private void ReadResponse(IAsyncResult asyncResult) {

string result;

WebRequest request = (WebRequest)asyncResult.AsyncState;

// Получение потока ответа WebResponse response = request.EndGetResponse(asyncResult) ; Stream responseStream = response.GetResponseStream();

try

{                                                                       I

// Чтение возвращенного текста

StreamReader reader = new StreamReader(responseStream); string population = reader.ReadToEndO ; result = population + " тысяч человек";

}

catch (Exception err) {

result = "Ошибка при вызове службы.";

}

finally

(

response.Close ();

)

Как и BeginGetRequestStreamO , метод обратного вызова BeginGetResponse () вы­полняется в фоновом потоке. Следовательно, для взаимодействия с элементами стра­ницы нужно использовать метод Dispatcher .Beginlnvoke (), маршаллизующий вызовы в главный поток приложения.

// Обновление интерфейса приложения Dispatcher.Beginlnvoke (

delegate () {

lblResult.Text = result; )).;

}

Забавный факт: при вызове простой веб-службы в Silverlight нужно выполнить боль­ше операций, чем при вызове веб-службы на основе SOAP. Это объясняется тем, что в Silverlight не генерируется код простой службы. Простые службы легче вызывать, но они хуже документированы. Из-за отсутствия низкоуровневой документации, в инстру­менты разработки, такие как Visual Studio, не удается добавить средства генерации кода для простых веб-служб.

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии