[Из песочницы] Работа с SOAP сервисом из Windows Phone 8.1 приложения
С выходом Windows Phone 8.1 появилась новая возможность в разработке приложений магазина Windows / Windows phone с общей кодовой базой. Это так называемые универсальные приложения, базирующиеся на более общем API и возможности повторного использования разметки XAML в Visual Studio 2013 сразу из коробки.Если приложение магазина Windows использует WCF для работы с SOAP сервисами, то попытка портирования на Windows phone может завершиться неудачей. Как оказалось, пространство имен System.ServiceModel отныне недоступно. Соответственно требуется замена, отвечающая следующим требованиям:
Простота использования, аналогично старому Add Service Reference, где на выходе получается сгенерированный код строго типизированного клиента сервиса;
Расширяемость, как показала практика может потребоваться поддержка различных схем аутентификации.
SOAP запрос представляет собой особым образом сформированный XML документ. Все что необходимо сделать это сериализовать данные запроса в XML, поместить их в элемент Body и отправить в теле HTTP POST запроса. Структура ответа аналогична, результат получается из элемента Body.
На основе HttpClient реализуем базовый класс для формирования запроса. В результате получаем функцию следующего вида:
public async Task
К получению информации о сервисе можно подойти с разных сторон:
Работа с сырым WSDL. Можно, но для поставленной задачи слишком трудоемко, пойдем лучше по пути наименьшего сопротивления; Использовать класс System.ServiceModel.Description.MetadataExchangeClient, это самый разумный вариант, однако реализация этого класса не позволяет работать с любым WSDL. Если в документе содержится элемент import, то MetadataExchangeClient вываливается с ошибкой; Использовать консольную утилиту SvcUtil входящую в состав .Net Framework SDK. На выходе мы получим тот же исходный код что и при использовании Add Service Reference из Visual Studio, который и возьмем за основу. Исходный код полученный при помощи SvcUtil не может напрямую использоваться для приложений магазина Windows Phone по причине наличия следующих не поддерживаемых конструкций:
Клиент сервиса на основе System.ServiceModel.ClientBase
В результате, путем не хитрых манипуляций можно сгенерировать клиент для любого сервиса. В дополнении к этому 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
