Использование веб-службы 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 возвращает ObservableCollectionTodoWCFService.TodoItem экземпляры, которые затем преобразуются в ListTodoItem экземпляры для отображения.

Создание данных

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 для приема удаленных подключений и подключения к службе с физического или виртуального устройства:

  1. Добавьте исключение в брандмауэр Windows. Необходимо открыть порт через брандмауэр Windows, который приложения в подсети могут использовать для взаимодействия со службой WCF. Создайте правило для входящего трафика, открывающее порт 49393 в брандмауэре. В командной строке администрирования выполните следующую команду:

    netsh advfirewall firewall add rule name="TodoWCFService" dir=in protocol=tcp localport=49393 profile=private remoteip=localsubnet action=allow
    
  2. Настройка 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 работать и обслуживать службу, отключите параметр "Изменить и продолжить" в веб-отладчиках> свойств > проекта.

  3. Настройте устройства конечной точки, используемые для доступа к службе. Этот шаг включает настройку клиентского приложения, работающего на физическом или эмулированном устройстве, для доступа к службе 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 с физических или виртуальных устройств.