Использование веб-службы Windows Communication Foundation (WCF)
WCF — это единая платформа Майкрософт для создания приложений, ориентированных на обслуживание. Это позволяет разработчикам создавать безопасные, надежные, трансактированные и совместимые распределенные приложения. В этой статье показано, как использовать службу Xamarin.Forms протокола SOAP (SOAP) WCF.
WCF описывает службу с различными контрактами, включая:
- Контракты данных — определяют структуры данных, которые формируют основу для содержимого в сообщении.
- Контракты сообщений — создание сообщений из существующих контрактов данных.
- Контракты сбоя — позволяют указывать пользовательские ошибки SOAP.
- Контракты служб — укажите операции, которые поддерживают службы и сообщения, необходимые для взаимодействия с каждой операцией. Они также указывают любое пользовательское поведение сбоя, которое может быть связано с операциями в каждой службе.
Существуют различия между ASP.NET веб-службами (ASMX) и WCF, но WCF поддерживает те же возможности, что и ASMX— сообщения SOAP по протоколу HTTP. Дополнительные сведения об использовании службы ASMX см. в разделе "Использование ASP.NET веб-служб (ASMX)".
Внимание
Поддержка платформы Xamarin для WCF ограничена текстовыми сообщениями SOAP по протоколу HTTP/HTTPS с помощью BasicHttpBinding
класса.
Поддержка WCF требует использования средств, доступных только в среде Windows, для создания прокси-сервера и размещения TodoWCFService. Для создания и тестирования приложения iOS потребуется развернуть TodoWCFService на компьютере Windows или в качестве веб-службы Azure.
Собственные приложения Xamarin Forms обычно совместно используют код с библиотекой классов .NET Standard. Однако .NET Core в настоящее время не поддерживает WCF, поэтому общий проект должен быть устаревшей переносимой библиотекой классов. Сведения о поддержке WCF в .NET Core см. в разделе Выбор между .NET Core и платформа .NET Framework для серверных приложений.
Пример решения приложения включает службу WCF, которая может выполняться локально и показана на следующем снимке экрана:
Примечание.
В iOS 9 и более поздней версии безопасность транспорта приложений (ATS) обеспечивает безопасные подключения между интернет-ресурсами (например, сервером приложения) и приложением, тем самым предотвращая случайное раскрытие конфиденциальной информации. Так как ATS включен по умолчанию в приложениях, созданных для iOS 9, все подключения будут соответствовать требованиям безопасности ATS. Если подключения не соответствуют этим требованиям, они завершаются сбоем с исключением.
ATS можно отказаться от использования протокола и безопасного HTTPS
обмена данными для интернет-ресурсов. Это можно сделать, обновив файл Info.plist приложения. Дополнительные сведения см. в разделе "Безопасность транспорта приложений".
Использование веб-службы
Служба WCF предоставляет следующие операции:
Операция | Description | Параметры |
---|---|---|
GetTodoItems | Получение списка элементов задач | |
CreateTodoItem | Создание нового элемента для выполнения | Сериализованный XML TodoItem |
EditTodoItem | Обновление элемента задачи | Сериализованный XML TodoItem |
DeleteTodoItem | Удаление элемента задачи | Сериализованный XML TodoItem |
Дополнительные сведения о модели данных, используемой в приложении, см. в разделе "Моделирование данных".
Прокси-сервер должен быть создан для использования службы WCF, которая позволяет приложению подключаться к службе. Прокси-сервер создается путем использования метаданных службы, определяющих методы и связанную конфигурацию службы. Эти метаданные предоставляются в виде документа языка описания веб-служб (WSDL), созданного веб-службой. Прокси-сервер можно создать с помощью поставщика ссылок веб-службы WCF в Visual Studio 2017, чтобы добавить ссылку на службу для веб-службы в библиотеку .NET Standard. Альтернативой созданию прокси-сервера с помощью поставщика ссылок на веб-службы WCF в Visual Studio 2017 является использование средства служебной программы метаданных ServiceModel (svcutil.exe). Дополнительные сведения см. в статье ServiceModel Metadata Utility Tool (Svcutil.exe).
Созданные прокси-классы предоставляют методы для использования веб-служб, использующих шаблон конструктора асинхронной модели программирования (APM). В этом шаблоне асинхронная операция реализуется в виде двух методов с именем BeginOperationName и EndOperationName, которые начинаются и заканчиваются асинхронной операцией.
Метод BeginOperationName начинает асинхронную операцию и возвращает объект, реализующий IAsyncResult
интерфейс. После вызова BeginOperationName приложение может продолжить выполнение инструкций в вызывающем потоке, а асинхронная операция выполняется в потоке пула потоков.
Для каждого вызова BeginOperationName приложение также должно вызвать EndOperationName, чтобы получить результаты операции. Возвращаемое значение EndOperationName совпадает с типом, возвращаемым методом синхронной веб-службы. Например, EndGetTodoItems
метод возвращает коллекцию TodoItem
экземпляров. Метод EndOperationName также включает IAsyncResult
параметр, который следует задать экземпляру, возвращаемого соответствующим вызовом метода BeginOperationName .
Библиотека параллельных задач (TPL) может упростить процесс использования пары методов APM begin/end, инкапсулируя асинхронные операции в одном Task
объекте. Эта инкапсуляция обеспечивается несколькими перегрузками TaskFactory.FromAsync
метода.
Дополнительные сведения об APM см. в статье "Асинхронное программирование модели" и TPL и традиционных платформа .NET Framework асинхронного программирования на сайте MSDN.
Создание объекта TodoServiceClient
Созданный прокси-класс предоставляет TodoServiceClient
класс, который используется для взаимодействия со службой WCF по протоколу HTTP. Он предоставляет функциональные возможности для вызова методов веб-службы в качестве асинхронных операций из определяемого экземпляра службы URI. Дополнительные сведения об асинхронных операциях см. в обзоре поддержки Async.
TodoServiceClient
Экземпляр объявляется на уровне класса, чтобы объект работал до тех пор, пока приложение должно использовать службу WCF, как показано в следующем примере кода:
public class SoapService : ISoapService
{
ITodoService todoService;
...
public SoapService ()
{
todoService = new TodoServiceClient (
new BasicHttpBinding (),
new EndpointAddress (Constants.SoapUrl));
}
...
}
Экземпляр TodoServiceClient
настраивается с информацией о привязке и адресом конечной точки. Привязка используется для указания сведений о транспорте, кодировке и протоколе, необходимых для взаимодействия между приложениями и службами. Указывает BasicHttpBinding
, что текстовые сообщения SOAP будут отправляться по протоколу транспорта HTTP. Указание адреса конечной точки позволяет приложению подключаться к разным экземплярам службы WCF, при условии, что существует несколько опубликованных экземпляров.
Дополнительные сведения о настройке ссылки на службу см. в разделе "Настройка ссылки на службу".
Создание объектов передачи данных
Пример приложения использует TodoItem
класс для моделирования данных. Чтобы сохранить TodoItem
элемент в веб-службе, сначала его необходимо преобразовать в созданный TodoItem
прокси-сервер. Это достигается методом ToWCFServiceTodoItem
, как показано в следующем примере кода:
TodoWCFService.TodoItem ToWCFServiceTodoItem (TodoItem item)
{
return new TodoWCFService.TodoItem
{
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
Этот метод просто создает новый TodoWCFService.TodoItem
экземпляр и задает каждому свойству идентичное свойство из экземпляра TodoItem
.
Аналогичным образом, когда данные извлекаются из веб-службы, его необходимо преобразовать из созданного TodoItem
прокси-сервера в TodoItem
экземпляр. Это достигается с FromWCFServiceTodoItem
помощью метода, как показано в следующем примере кода:
static TodoItem FromWCFServiceTodoItem (TodoWCFService.TodoItem item)
{
return new TodoItem
{
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
Этот метод просто извлекает данные из созданного TodoItem
прокси-сервера типа и задает его в только что созданном TodoItem
экземпляре.
Извлечение данных
TodoServiceClient.EndGetTodoItems
Методы TodoServiceClient.BeginGetTodoItems
используются для вызова GetTodoItems
операции, предоставляемой веб-службой. Эти асинхронные методы инкапсулируются в Task
объекте, как показано в следующем примере кода:
public async Task<List<TodoItem>> RefreshDataAsync ()
{
...
var todoItems = await Task.Factory.FromAsync <ObservableCollection<TodoWCFService.TodoItem>> (
todoService.BeginGetTodoItems,
todoService.EndGetTodoItems,
null,
TaskCreationOptions.None);
foreach (var item in todoItems)
{
Items.Add (FromWCFServiceTodoItem (item));
}
...
}
Метод Task.Factory.FromAsync
создает Task
метод, который выполняет TodoServiceClient.EndGetTodoItems
метод после TodoServiceClient.BeginGetTodoItems
завершения метода, с null
параметром, указывающим, что данные не передаются делегату BeginGetTodoItems
. Наконец, значение перечисления TaskCreationOptions
указывает, что поведение по умолчанию для создания и выполнения задач должно использоваться.
Метод TodoServiceClient.EndGetTodoItems
возвращает ObservableCollection
TodoWCFService.TodoItem
экземпляры, которые затем преобразуются в List
TodoItem
экземпляры для отображения.
Создание данных
TodoServiceClient.EndCreateTodoItem
Методы TodoServiceClient.BeginCreateTodoItem
используются для вызова CreateTodoItem
операции, предоставляемой веб-службой. Эти асинхронные методы инкапсулируются в Task
объекте, как показано в следующем примере кода:
public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
...
var todoItem = ToWCFServiceTodoItem (item);
...
await Task.Factory.FromAsync (
todoService.BeginCreateTodoItem,
todoService.EndCreateTodoItem,
todoItem,
TaskCreationOptions.None);
...
}
Метод Task.Factory.FromAsync
создает Task
метод, который выполняет TodoServiceClient.EndCreateTodoItem
метод после TodoServiceClient.BeginCreateTodoItem
завершения метода, с todoItem
параметром, передаваемым в BeginCreateTodoItem
делегат, чтобы указать TodoItem
созданный веб-службой параметр. Наконец, значение перечисления TaskCreationOptions
указывает, что поведение по умолчанию для создания и выполнения задач должно использоваться.
Веб-служба выдает исключение FaultException
, если не удается создать TodoItem
объект, который обрабатывается приложением.
Обновление данных
TodoServiceClient.EndEditTodoItem
Методы TodoServiceClient.BeginEditTodoItem
используются для вызова EditTodoItem
операции, предоставляемой веб-службой. Эти асинхронные методы инкапсулируются в Task
объекте, как показано в следующем примере кода:
public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
...
var todoItem = ToWCFServiceTodoItem (item);
...
await Task.Factory.FromAsync (
todoService.BeginEditTodoItem,
todoService.EndEditTodoItem,
todoItem,
TaskCreationOptions.None);
...
}
Метод Task.Factory.FromAsync
создает Task
метод, который выполняет TodoServiceClient.EndEditTodoItem
метод после TodoServiceClient.BeginCreateTodoItem
завершения метода, с todoItem
параметром, передаваемым в BeginEditTodoItem
делегат, чтобы указать TodoItem
, который будет обновляться веб-службой. Наконец, значение перечисления TaskCreationOptions
указывает, что поведение по умолчанию для создания и выполнения задач должно использоваться.
Веб-служба создает исключение FaultException
, если не удается найти или обновить TodoItem
объект, который обрабатывается приложением.
Удаление данных
TodoServiceClient.EndDeleteTodoItem
Методы TodoServiceClient.BeginDeleteTodoItem
используются для вызова DeleteTodoItem
операции, предоставляемой веб-службой. Эти асинхронные методы инкапсулируются в Task
объекте, как показано в следующем примере кода:
public async Task DeleteTodoItemAsync (string id)
{
...
await Task.Factory.FromAsync (
todoService.BeginDeleteTodoItem,
todoService.EndDeleteTodoItem,
id,
TaskCreationOptions.None);
...
}
Метод Task.Factory.FromAsync
создает Task
метод, который выполняет TodoServiceClient.EndDeleteTodoItem
метод после TodoServiceClient.BeginDeleteTodoItem
завершения метода, с id
параметром, передаваемым в BeginDeleteTodoItem
делегат, чтобы указать TodoItem
удаление веб-службой. Наконец, значение перечисления TaskCreationOptions
указывает, что поведение по умолчанию для создания и выполнения задач должно использоваться.
Веб-служба создает исключение FaultException
, если не удается найти или удалить TodoItem
объект, который обрабатывается приложением.
Настройка удаленного доступа к IIS Express
В Visual Studio 2017 или Visual Studio 2019 вы сможете протестировать приложение UWP на компьютере без дополнительной настройки. Для тестирования клиентов Android и iOS могут потребоваться дополнительные действия, описанные в этом разделе. Дополнительные сведения см. в разделе Подключение локальных веб-служб из симуляторов iOS и эмуляторов Android.
По умолчанию СЛУЖБА IIS Express будет отвечать только на запросы localhost
. Удаленные устройства (например, устройство Android, i Телефон или даже симулятор) не будут иметь доступа к локальной службе WCF. Вам потребуется знать IP-адрес рабочей станции Windows 10 в локальной сети. В этом примере предположим, что у рабочей станции есть IP-адрес 192.168.1.143
. Ниже описано, как настроить Windows 10 и IIS Express для приема удаленных подключений и подключения к службе с физического или виртуального устройства:
Добавьте исключение в брандмауэр Windows. Необходимо открыть порт через брандмауэр Windows, который приложения в подсети могут использовать для взаимодействия со службой WCF. Создайте правило для входящего трафика, открывающее порт 49393 в брандмауэре. В командной строке администрирования выполните следующую команду:
netsh advfirewall firewall add rule name="TodoWCFService" dir=in protocol=tcp localport=49393 profile=private remoteip=localsubnet action=allow
Настройка IIS Express для принятия удаленных подключений. Вы можете настроить IIS Express, изменив файл конфигурации для IIS Express в [каталоге решения].vs\config\applicationhost.config.
site
Найдите элемент с именемTodoWCFService
. Он должен выглядеть примерно так:<site name="TodoWCFService" id="2"> <application path="/" applicationPool="Clr4IntegratedAppPool"> <virtualDirectory path="/" physicalPath="C:\Users\tom\TodoWCF\TodoWCFService\TodoWCFService" /> </application> <bindings> <binding protocol="http" bindingInformation="*:49393:localhost" /> </bindings> </site>
Необходимо добавить два
binding
элемента, чтобы открыть порт 49393 для внешнего трафика и эмулятора Android. Привязка использует формат, определяющий[IP address]:[port]:[hostname]
способ реагирования IIS Express на запросы. Внешние запросы будут иметь имена узлов, которые должны быть указаны в качествеbinding
имени. Добавьте следующий XML-код вbindings
элемент, заменив IP-адрес собственным IP-адресом:<binding protocol="http" bindingInformation="*:49393:192.168.1.143" /> <binding protocol="http" bindingInformation="*:49393:127.0.0.1" />
После внесения изменений
bindings
элемент должен выглядеть следующим образом:<site name="TodoWCFService" id="2"> <application path="/" applicationPool="Clr4IntegratedAppPool"> <virtualDirectory path="/" physicalPath="C:\Users\tom\TodoWCF\TodoWCFService\TodoWCFService" /> </application> <bindings> <binding protocol="http" bindingInformation="*:49393:localhost" /> <binding protocol="http" bindingInformation="*:49393:192.168.1.143" /> <binding protocol="http" bindingInformation="*:49393:127.0.0.1" /> </bindings> </site>
Внимание
По умолчанию СЛУЖБА IIS Express не будет принимать подключения из внешних источников по соображениям безопасности. Чтобы включить подключения с удаленных устройств, необходимо запустить IIS Express с разрешениями Администратор istrative. Самый простой способ сделать это — запустить Visual Studio 2017 с разрешениями Администратор istrative. При запуске TodoWCFService будет запускаться СЛУЖБА IIS Express с Администратор istrative разрешения.
После выполнения этих действий вы сможете запустить TodoWCFService и подключиться с других устройств в подсети. Это можно проверить, запустив приложение и посещая
http://localhost:49393/TodoService.svc
его. Если при посещении этого URL-адреса возникает ошибка с неправильным запросом, возможно,bindings
в конфигурации IIS Express (запрос достигает IIS Express, но отклоняется). Если возникает другая ошибка, возможно, приложение не запущено или брандмауэр настроен неправильно.Чтобы разрешить службам IIS Express работать и обслуживать службу, отключите параметр "Изменить и продолжить" в веб-отладчиках> свойств > проекта.
Настройте устройства конечной точки, используемые для доступа к службе. Этот шаг включает настройку клиентского приложения, работающего на физическом или эмулированном устройстве, для доступа к службе WCF.
Эмулятор Android использует внутренний прокси-сервер, который запрещает эмулятору напрямую получать доступ к адресу хост-компьютера
localhost
. Вместо этого адрес10.0.2.2
эмулятораlocalhost
направляется на главный компьютер через внутренний прокси-сервер. Эти прокси-запросы будут иметь127.0.0.1
имя узла в заголовке запроса, поэтому вы создали привязку IIS Express для этого имени узла в описанных выше шагах.Симулятор iOS запускается на узле сборки Mac, даже если вы используете удаленный симулятор iOS для Windows. Сетевые запросы от симулятора будут иметь IP-адрес рабочей станции в локальной сети в качестве имени узла (в этом примере это
192.168.1.143
так, но фактический IP-адрес, скорее всего, будет отличаться). Поэтому вы создали привязку IIS Express для этого имени узла, выполнив описанные выше действия.Убедитесь,
SoapUrl
что свойство в файле Constants.cs в проекте TodoWCF (переносимое) имеет значения, правильные для вашей сети:public static string SoapUrl { get { var defaultUrl = "http://localhost:49393/TodoService.svc"; if (Device.RuntimePlatform == Device.Android) { defaultUrl = "http://10.0.2.2:49393/TodoService.svc"; } else if (Device.RuntimePlatform == Device.iOS) { defaultUrl = "http://192.168.1.143:49393/TodoService.svc"; } return defaultUrl; } }
После настройки Constants.cs с соответствующими конечными точками вы сможете подключиться к TodoWCFService, работающей на рабочей станции Windows 10 с физических или виртуальных устройств.