Работа с SOAP сервисом из Windows Phone 8.1 приложения

OSzone.net » Microsoft » Разработка приложений » Windows Phone » Работа с SOAP сервисом из Windows Phone 8.1 приложения
Автор: Алексей Соснин
Иcточник: msdn.microsoft.com
Опубликована: 16.01.2015

С выходом Windows Phone 8.1 появилась новая возможность в разработке приложений магазина Windows / Windows phone с общей кодовой базой. Это так называемые универсальные приложения, базирующиеся на более общем API и возможности повторного использования разметки XAML в Visual Studio 2013 сразу из коробки.

Если приложение магазина Windows использует WCF для работы с SOAP сервисами, то попытка портирования на Windows phone может завершиться неудачей. Как оказалось, пространство имен System.ServiceModel отныне недоступно. Соответственно требуется замена, отвечающая следующим требованиям:

SOAP запрос представляет собой особым образом сформированный XML документ. Все что необходимо сделать это сериализовать данные запроса в XML, поместить их в элемент Body и отправить в теле HTTP POST запроса. Структура ответа аналогична, результат получается из элемента Body.

*

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

public async Task<TResponse> CallAsync<TRequest, TResponse>(string action, TRequest request)
{
IHttpContent httpContent = GetHttpContent(action, request);
var response = await Client.PostAsync(EndpointAddress, httpContent);
var responseContent = await response.Content.ReadAsStringAsync();
return GetResponse<TResponse>(responseContent);
}


Остается только подставить соответствующие классы TRequest и TResponse которые можно получить на основе описания сервиса. SOAP сервисы описываются при помощи Web Services Description Language ( WSDL), языка, описывающего API сервиса в виде операций и типов данных.

К получению информации о сервисе можно подойти с разных сторон:

Исходный код полученный при помощи SvcUtil не может напрямую использоваться для приложений магазина Windows Phone по причине наличия следующих не поддерживаемых конструкций:


Преобразование кода производится при помощи Reflection + CodeDom. В итоге получаем реализацию классов TRequest и TRespone совместимых с платформой. Осталось только сгенерировать клиент сервиса реализующий соответствующий интерфейс. Всю необходимая для этого информация так же получается из исходного файла.

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

Расширяемость этого решения основана на возможности использования конструктора класса HttpClient, принимающего параметр IHttpFilter, за счет которого достаточно легко реализовать шаблон проектирования Декоратор. Таким образом, можно не затрагивая существующее API работать с HTTP заголовками, например, чтобы реализовать Digest аутентификацию, так и модифицировать SOAP запрос перед отправкой чтобы добавить требуемые параметры в элемент Header.

private static HttpClient GetClient(PasswordCredential cred, TimeSpan? timeDiff)
{
var baseFilter = new HttpBaseProtocolFilter
{
AllowUI = false,
};

if (cred == null)
return new HttpClient(baseFilter);

var httpDigestHttpFilter = new HttpDigestHttpFilter(baseFilter)
{
UserName = cred.UserName,
Password = cred.Password
};

var soapDigestHttpFilter = new SoapDigestHttpFilter(httpDigestHttpFilter)
{
UserName = cred.UserName,
Password = cred.Password,
TimeDiff = timeDiff
};
return new HttpClient(soapDigestHttpFilter);
}


Приложения магазина Windows менее обделены функционалом чем Windows Phone и сохранили некоторое подмножество WCF. Однако и тут можно столкнуться с проблемой, не позволяющей воспользоваться существующим функционалом. Проблема эта заключается в отправке с каждым запросом заголовка Expect: 100-Continue. Некоторые сервисы категорично отвечают на это ошибкой 417 Expectation Failed. В полной версии .Net Framework это решается сбросом флага Expect100Continue:

System.Net.ServicePointManager.Expect100Continue = false;


В .Net для приложений магазина Windows это свойство отсутствует. При использовании HttpClient это ограничение можно обойти и использовать полученную реализацию в том числе и для приложений магазина Windows.

Генерация исходного кода производится получившейся консольной утилитой в следующем формате:

SoapClientGenerator.exe <metadataDocumentPath> <file> <namespace> [/svcutil:<svcutilPath>]

Где:

Исходный код доступен на GitHub.


Ссылка: http://www.oszone.net/26141/SOAP