Введение в веб-службы

В этом руководстве показано, как использовать различные технологии веб-службы. В этой статье рассматриваются сведения о взаимодействии со службами REST, службами SOAP и службами Windows Communication Foundation.

Для правильной работы многие мобильные приложения зависят от облака, поэтому интеграция веб-служб в мобильные приложения является общим сценарием. Платформа Xamarin поддерживает использование различных технологий веб-службы и включает встроенную и стороннюю поддержку использования служб RESTful, ASMX и Windows Communication Foundation (WCF).

Для клиентов, использующих Xamarin.Forms, приведены полные примеры использования каждого из этих технологий в документации по веб-службам Xamarin.Forms.

Внимание

В iOS 9 безопасность транспорта приложений (ATS) обеспечивает безопасные подключения между интернет-ресурсами (например, сервером сервером приложения) и приложением, тем самым предотвращая случайное раскрытие конфиденциальной информации. Так как ATS включен по умолчанию в приложениях, созданных для iOS 9, все подключения будут соответствовать требованиям безопасности ATS. Если подключения не соответствуют этим требованиям, они завершаются сбоем с исключением.

Вы можете отказаться от ATS, если невозможно использовать HTTPS протокол и безопасный обмен данными для интернет-ресурсов. Это можно сделать, обновив файл Info.plist приложения. Дополнительные сведения см. в разделе "Безопасность транспорта приложений".

REST

Передача репрезентативного состояния (REST) — это архитектурный стиль для создания веб-служб. Запросы REST выполняются по протоколу HTTP с использованием тех же HTTP-команд, которые используются веб-браузерами для получения веб-страниц и отправки данных на серверы. Ниже приведен перечень команд.

  • GET — эта операция используется для получения данных из веб-службы.
  • POST — эта операция используется для создания нового элемента данных в веб-службе.
  • PUT — эта операция используется для обновления элемента данных в веб-службе.
  • PATCH — эта операция используется для обновления элемента данных веб-службы путем описания набора инструкций по изменению элемента. Эта команда не используется в примере приложения.
  • DELETE — эта операция используется для удаления элемента данных в веб-службе.

API-интерфейсы веб-службы, которые соответствуют REST, называются RESTful API и определяются с помощью следующих элементов:

  • Базовый универсальный код ресурса (URI).
  • Методы HTTP, такие как GET, POST, WHERE, PATCH или DELETE.
  • Тип носителя для данных, например нотация объектов JavaScript (JSON).

Простота REST помогла сделать его основным методом для доступа к веб-службам в мобильных приложениях.

Использование служб REST

Существует ряд библиотек и классов, которые можно использовать для использования служб REST, и в следующих подразделах их рассматриваются. Дополнительные сведения об использовании службы REST см. в разделе "Использование веб-службы RESTful".

HttpClient

Клиентские библиотеки Microsoft HTTP предоставляют HttpClient класс, который используется для отправки и получения запросов по протоколу HTTP. Он предоставляет функциональные возможности для отправки HTTP-запросов и получения HTTP-ответов из ресурса, определяемого URI. Каждый запрос отправляется как асинхронная операция. Дополнительные сведения об асинхронных операциях см. в обзоре поддержки Async.

Класс HttpResponseMessage представляет сообщение HTTP-ответа, полученное от веб-службы после выполнения HTTP-запроса. Он содержит сведения об ответе, включая код состояния, заголовки и текст. HttpContent Класс представляет тело HTTP и заголовки содержимого, таких как Content-Type и Content-Encoding. Содержимое можно считывать с помощью любого из ReadAs методов, таких как ReadAsStringAsync и ReadAsByteArrayAsyncв зависимости от формата данных.

Дополнительные сведения о классе см. в HttpClient разделе "Создание объекта HTTPClient".

HTTPWebRequest

Вызов веб-служб с HTTPWebRequest включает в себя:

  • Создание экземпляра запроса для определенного URI.
  • Задание различных свойств HTTP в экземпляре запроса.
  • HttpWebResponse Получение из запроса.
  • Чтение данных из ответа.

Например, следующий код извлекает данные из веб-службы Национальной библиотеки медицины США:

var rxcui = "198440";
var request = HttpWebRequest.Create(string.Format(@"https://rxnav.nlm.nih.gov/REST/RxTerms/rxcui/{0}/allinfo", rxcui));
request.ContentType = "application/json";
request.Method = "GET";

using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
  if (response.StatusCode != HttpStatusCode.OK)
     Console.Out.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
  using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  {
               var content = reader.ReadToEnd();
               if(string.IsNullOrWhiteSpace(content)) {
                       Console.Out.WriteLine("Response contained empty body...");
               }
               else {
                       Console.Out.WriteLine("Response Body: \r\n {0}", content);
               }

               Assert.NotNull(content);
  }
}

В приведенном выше примере создается объект HttpWebRequest , который возвращает данные в формате JSON. Данные возвращаются в объекте HttpWebResponse, из которого StreamReader можно получить данные для чтения данных.

RestSharp

Другим подходом к использованию служб REST является использование библиотеки RestSharp . RestSharp инкапсулирует HTTP-запросы, включая поддержку получения результатов в виде необработанного содержимого строки или в виде десериализированного объекта C#. Например, следующий код отправляет запрос к веб-службе Национальной библиотеки медицины США и получает результаты в формате JSON:

var request = new RestRequest(string.Format("{0}/allinfo", rxcui));
request.RequestFormat = DataFormat.Json;
var response = Client.Execute(request);
if(string.IsNullOrWhiteSpace(response.Content) || response.StatusCode != System.Net.HttpStatusCode.OK) {
       return null;
}
rxTerm = DeserializeRxTerm(response.Content);

DeserializeRxTerm — это метод, который будет принимать необработанную строку JSON из RestSharp.RestResponse.Content свойства и преобразовывать ее в объект C#. Десериализация данных, возвращаемых из веб-служб, рассматривается далее в этой статье.

NSUrl Подключение ion

Помимо классов, доступных в библиотеке базовых классов Mono (BCL), таких как, и сторонние библиотеки C#, такие как HttpWebRequestRestSharp, классы, зависящие от платформы, также доступны для использования веб-служб. Например, в iOS NSUrlConnection можно использовать классы и NSMutableUrlRequest классы.

В следующем примере кода показано, как вызвать веб-службу Национальной библиотеки медицины США с помощью классов iOS:

var rxcui = "198440";
var request = new NSMutableUrlRequest(new NSUrl(string.Format("https://rxnav.nlm.nih.gov/REST/RxTerms/rxcui/{0}/allinfo", rxcui)),
       NSUrlRequestCachePolicy.ReloadRevalidatingCacheData, 20);
request["Accept"] = "application/json";

var connectionDelegate = new RxTermNSURLConnectionDelegate();
var connection = new NSUrlConnection(request, connectionDelegate);
connection.Start();

public class RxTermNSURLConnectionDelegate : NSUrlConnectionDelegate
{
       StringBuilder _ResponseBuilder;
       public bool IsFinishedLoading { get; set; }
       public string ResponseContent { get; set; }

       public RxTermNSURLConnectionDelegate()
               : base()
       {
               _ResponseBuilder = new StringBuilder();
       }

       public override void ReceivedData(NSUrlConnection connection, NSData data)
       {
               if(data != null) {
                       _ResponseBuilder.Append(data.ToString());
               }
       }
       public override void FinishedLoading(NSUrlConnection connection)
       {
               IsFinishedLoading = true;
               ResponseContent = _ResponseBuilder.ToString();
       }
}

Как правило, классы конкретной платформы для использования веб-служб должны быть ограничены сценариями, в которых машинный код переносится в C#. По возможности код доступа к веб-службе должен быть переносимым, чтобы его можно было совместно использовать для кроссплатформенного доступа.

ServiceStack

Другим вариантом вызова веб-служб является библиотека стека служб. Например, в следующем коде показано, как использовать метод Service Stack IServiceClient.GetAsync для выдачи запроса на обслуживание:

client.GetAsync<CustomersResponse>("",
          (response) => {
               foreach(var c in response.Customers) {
                       Console.WriteLine(c.CompanyName);
               }
       },
       (response, ex) => {
               Console.WriteLine(ex.Message);
       });

Внимание

Хотя такие средства, как ServiceStack и RestSharp, упрощают вызов и использование служб REST, иногда нетривиал для использования XML или JSON, которые не соответствуют стандартным соглашениям о сериализации DataContract . При необходимости вызовите запрос и обработайте соответствующую сериализацию явным образом с помощью библиотеки ServiceStack.Text, описанной ниже.

Использование данных RESTful

Веб-службы RESTful обычно используют сообщения JSON для возврата данных клиенту. JSON — это текстовый формат обмена данными, который создает компактные полезные данные, что приводит к снижению требований к пропускной способности при отправке данных. В этом разделе рассматриваются механизмы использования ответов RESTful в формате JSON и Plain-Old-XML (POX).

System.JSON

Платформа Xamarin поставляется с поддержкой JSON из коробки. С помощью JsonObjectрезультата можно получить, как показано в следующем примере кода:

var obj = JsonObject.Parse(json);
var properties = obj["rxtermsProperties"];
term.BrandName = properties["brandName"];
term.DisplayName = properties["displayName"];
term.Synonym = properties["synonym"];
term.FullName = properties["fullName"];
term.FullGenericName = properties["fullGenericName"];
term.Strength = properties["strength"];

Однако важно знать, что System.Json средства загружают все данные в память.

JSON.NET

Библиотека NewtonSoft JSON.NET широко используется для сериализации и десериализации сообщений JSON. В следующем примере кода показано, как использовать JSON.NET для десериализации сообщения JSON в объект C#:

var term = new RxTerm();
var properties = JObject.Parse(json)["rxtermsProperties"];
term.BrandName = properties["brandName"].Value<string>();
term.DisplayName = properties["displayName"].Value<string>();
term.Synonym = properties["synonym"].Value<string>();;
term.FullName = properties["fullName"].Value<string>();;
term.FullGenericName = properties["fullGenericName"].Value<string>();;
term.Strength = properties["strength"].Value<string>();
term.RxCUI = properties["rxcui"].Value<string>();

ServiceStack.Text

ServiceStack.Text — это библиотека сериализации JSON, предназначенная для работы с библиотекой ServiceStack. В следующем примере кода показано, как проанализировать JSON с помощью ServiceStack.Text.JsonObject:

var result = JsonObject.Parse(json).Object("rxtermsProperties")
       .ConvertTo(x => new RxTerm {
               BrandName = x.Get("brandName"),
               DisplayName = x.Get("displayName"),
               Synonym = x.Get("synonym"),
               FullName = x.Get("fullName"),
               FullGenericName = x.Get("fullGenericName"),
               Strength = x.Get("strength"),
               RxTermDoseForm = x.Get("rxtermsDoseForm"),
               Route = x.Get("route"),
               RxCUI = x.Get("rxcui"),
               RxNormDoseForm = x.Get("rxnormDoseForm"),
       });

System.Xml.Linq

В случае использования веб-службы REST на основе XML можно использовать LINQ to XML для анализа XML и заполнения встроенного объекта C#, как показано в следующем примере кода:

var doc = XDocument.Parse(xml);
var result = doc.Root.Descendants("rxtermsProperties")
.Select(x=> new RxTerm()
       {
               BrandName = x.Element("brandName").Value,
               DisplayName = x.Element("displayName").Value,
               Synonym = x.Element("synonym").Value,
               FullName = x.Element("fullName").Value,
               FullGenericName = x.Element("fullGenericName").Value,
               //bind more here...
               RxCUI = x.Element("rxcui").Value,
       });

веб-служба ASP.NET (ASMX)

ASMX предоставляет возможность создавать веб-службы, отправляющие сообщения с помощью протокола SOAP. SOAP — это независимый от платформы и независимый от языка протокол для создания и доступа к веб-службам. Потребители службы ASMX не должны знать ничего о платформе, объектной модели или языке программирования, используемом для реализации службы. Им нужно только понять, как отправлять и получать сообщения SOAP.

Сообщение SOAP — это XML-документ, содержащий следующие элементы:

  • Корневой элемент с именем Envelope , который идентифицирует XML-документ как сообщение SOAP.
  • Необязательный элемент Заголовка , содержащий сведения, относящиеся к приложению, такие как данные проверки подлинности. Если элемент Header присутствует, он должен быть первым дочерним элементом элемента Envelope.
  • Обязательный элемент Body , содержащий сообщение SOAP, предназначенное для получателя.
  • Необязательный элемент fault , используемый для указания сообщений об ошибках. Если элемент Fault присутствует, он должен быть дочерним элементом элемента Body.

SOAP может работать над множеством транспортных протоколов, включая ПРОТОКОЛ HTTP, SMTP, TCP и UDP. Однако служба ASMX может работать только по протоколу HTTP. Платформа Xamarin поддерживает стандартные реализации SOAP 1.1 по протоколу HTTP, и это включает поддержку многих стандартных конфигураций служб ASMX.

Создание прокси-сервера

Прокси-сервер должен быть создан для использования службы ASMX, которая позволяет приложению подключаться к службе. Прокси-сервер создается путем использования метаданных службы, определяющих методы и связанную конфигурацию службы. Эти метаданные предоставляются в виде документа языка описания веб-служб (WSDL), созданного веб-службой. Прокси-сервер создается с помощью Visual Studio для Mac или Visual Studio для добавления веб-ссылки для веб-службы в проекты, относящиеся к платформе.

URL-адрес веб-службы может быть размещенным удаленным источником или ресурсом локальной файловой системы, доступным через file:/// префикс пути, например:

file:///Users/myUserName/projects/MyProjectName/service.wsdl

The web service URL can either be a hosted remote source or local file system resource accessible via the file path prefix

Это создает прокси-сервер в папке "Ссылки на веб- или службы" проекта. Так как прокси-сервер создается код, его не следует изменять.

Добавление прокси-сервера вручную в проект

Если у вас есть существующий прокси-сервер, созданный с помощью совместимых средств, эти выходные данные можно использовать при включении в проект. В Visual Studio для Mac используйте пункт меню "Добавить файлы...", чтобы добавить прокси-сервер. Кроме того, это требует явного ссылки на System.Web.Services.dll с помощью диалогового окна "Добавить ссылки... ".

Использование прокси-сервера

Созданные прокси-классы предоставляют методы использования веб-службы, использующую шаблон конструктора асинхронной модели программирования (APM). В этом шаблоне асинхронная операция реализуется как два метода с именем BeginOperationName и EndOperationName, которые начинают и заканчивают асинхронную операцию.

Метод BeginOperationName начинает асинхронную операцию и возвращает объект, реализующий IAsyncResult интерфейс. После вызова BeginOperationName приложение может продолжить выполнение инструкций в вызывающем потоке, а асинхронная операция выполняется в потоке пула потоков.

Для каждого вызова BeginOperationName приложение также должно вызвать EndOperationName, чтобы получить результаты операции. Возвращаемое значение EndOperationName совпадает с типом, возвращаемым методом синхронной веб-службы. В следующем коде показан пример такого действия:

public async Task<List<TodoItem>> RefreshDataAsync ()
{
  ...
  var todoItems = await Task.Factory.FromAsync<ASMXService.TodoItem[]> (
    todoService.BeginGetTodoItems,
    todoService.EndGetTodoItems,
    null,
    TaskCreationOptions.None);
  ...
}

Библиотека параллельных задач (TPL) может упростить процесс использования пары методов APM begin/end, инкапсулируя асинхронные операции в одном Task объекте. Эта инкапсуляция обеспечивается несколькими перегрузками Task.Factory.FromAsync метода. Этот метод создает Task метод, который выполняет TodoService.EndGetTodoItems метод после TodoService.BeginGetTodoItems завершения метода, с null параметром, указывающим, что данные не передаются делегату BeginGetTodoItems . Наконец, значение перечисления TaskCreationOptions указывает, что поведение по умолчанию для создания и выполнения задач должно использоваться.

Дополнительные сведения об APM см. в статье "Асинхронное программирование модели" и TPL и традиционного платформа .NET Framework асинхронного программирования на сайте MSDN.

Дополнительные сведения об использовании службы ASMX см. в разделе "Использование ASP.NET веб-службы (ASMX)".

Windows Communication Foundation (WCF)

WCF — это единая платформа Майкрософт для создания приложений, ориентированных на обслуживание. Это позволяет разработчикам создавать безопасные, надежные, трансактированные и совместимые распределенные приложения.

WCF описывает службу с различными контрактами, которые включают следующие:

  • Контракты данных — определяют структуры данных, которые формируют основу для содержимого в сообщении.
  • Контракты сообщений — создание сообщений из существующих контрактов данных.
  • Контракты сбоя — позволяют указывать пользовательские ошибки SOAP.
  • Контракты служб — укажите операции, которые поддерживают службы и сообщения, необходимые для взаимодействия с каждой операцией. Они также указывают любое пользовательское поведение сбоя, которое может быть связано с операциями в каждой службе.

Существуют различия между веб-службами ASP.NET (ASMX) и WCF, но важно понимать, что WCF поддерживает те же возможности, которые предоставляет ASMX — сообщения SOAP по протоколу HTTP.

Внимание

Поддержка платформы Xamarin для WCF ограничена текстовыми сообщениями SOAP по протоколу HTTP/HTTPS с помощью BasicHttpBinding класса. Кроме того, поддержка WCF требует использования средств, доступных только в среде Windows для создания прокси-сервера.

Создание прокси-сервера

Прокси-сервер должен быть создан для использования службы WCF, которая позволяет приложению подключаться к службе. Прокси-сервер создается путем использования метаданных службы, определяющих методы и связанную конфигурацию службы. Эти метаданные предоставляются в виде документа языка описания веб-служб (WSDL), созданного веб-службой. Прокси-сервер можно создать с помощью поставщика справочника веб-службы WCF в Visual Studio 2017, чтобы добавить ссылку на службу для веб-службы в библиотеку .NET Standard.

Альтернативой созданию прокси-сервера с помощью поставщика ссылок на веб-службы WCF в Visual Studio 2017 является использование средства служебной программы метаданных ServiceModel (svcutil.exe). Дополнительные сведения см. в статье ServiceModel Metadata Utility Tool (Svcutil.exe).

Настройка прокси-сервера

Настройка созданного прокси-сервера обычно принимает два аргумента конфигурации (в зависимости от SOAP 1.1/ASMX или WCF) во время инициализации: EndpointAddress и (или) связанных сведений о привязке, как показано в следующем примере:

var binding = new BasicHttpBinding () {
       Name= "basicHttpBinding",
       MaxReceivedMessageSize = 67108864,
};

binding.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() {
       MaxArrayLength = 2147483646,
       MaxStringContentLength = 5242880,
};

var timeout = new TimeSpan(0,1,0);
binding.SendTimeout= timeout;
binding.OpenTimeout = timeout;
binding.ReceiveTimeout = timeout;

client = new Service1Client (binding, new EndpointAddress ("http://192.168.1.100/Service1.svc"));

Привязка используется для указания сведений о транспорте, кодировке и протоколе, необходимых для взаимодействия между приложениями и службами. Указывает BasicHttpBinding , что текстовые сообщения SOAP будут отправляться по протоколу транспорта HTTP. Указание адреса конечной точки позволяет приложению подключаться к разным экземплярам службы WCF, при условии, что существует несколько опубликованных экземпляров.

Использование прокси-сервера

Созданные прокси-классы предоставляют методы для использования веб-служб, использующих шаблон конструктора асинхронной модели программирования (APM). В этом шаблоне асинхронная операция реализуется в виде двух методов с именем BeginOperationName и EndOperationName, которые начинаются и заканчиваются асинхронной операцией.

Метод BeginOperationName начинает асинхронную операцию и возвращает объект, реализующий IAsyncResult интерфейс. После вызова BeginOperationName приложение может продолжить выполнение инструкций в вызывающем потоке, а асинхронная операция выполняется в потоке пула потоков.

Для каждого вызова BeginOperationName приложение также должно вызвать EndOperationName, чтобы получить результаты операции. Возвращаемое значение EndOperationName совпадает с типом, возвращаемым методом синхронной веб-службы. В следующем коде показан пример такого действия:

public async Task<List<TodoItem>> RefreshDataAsync ()
{
  ...
  var todoItems = await Task.Factory.FromAsync <ObservableCollection<TodoWCFService.TodoItem>> (
    todoService.BeginGetTodoItems,
    todoService.EndGetTodoItems,
    null,
    TaskCreationOptions.None);
  ...
}

Библиотека параллельных задач (TPL) может упростить процесс использования пары методов APM begin/end, инкапсулируя асинхронные операции в одном Task объекте. Эта инкапсуляция обеспечивается несколькими перегрузками Task.Factory.FromAsync метода. Этот метод создает Task метод, который выполняет TodoServiceClient.EndGetTodoItems метод после TodoServiceClient.BeginGetTodoItems завершения метода, с null параметром, указывающим, что данные не передаются делегату BeginGetTodoItems . Наконец, значение перечисления TaskCreationOptions указывает, что поведение по умолчанию для создания и выполнения задач должно использоваться.

Дополнительные сведения об APM см. в статье "Асинхронное программирование модели" и TPL и традиционного платформа .NET Framework асинхронного программирования на сайте MSDN.

Дополнительные сведения об использовании службы WCF см. в разделе "Использование веб-службы Windows Communication Foundation (WCF).

Использование безопасности транспорта

Службы WCF могут использовать безопасность уровня транспорта для защиты от перехвата сообщений. Платформа Xamarin поддерживает привязки, использующие безопасность уровня транспорта с помощью SSL. Однако могут возникнуть случаи, когда стеку может потребоваться проверить сертификат, что приводит к непреднамеренным поведению. Проверка может быть переопределена путем регистрации делегата перед вызовом ServerCertificateValidationCallback службы, как показано в следующем примере кода:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(se, cert, chain, sslerror) => { return true; };

Это поддерживает шифрование транспорта, игнорируя проверку сертификата на стороне сервера. Однако этот подход фактически игнорирует проблемы доверия, связанные с сертификатом, и может быть не соответствующим. Дополнительные сведения см. в статье "Использование доверенных корней с уважением " на mono-project.com.

Использование безопасности учетных данных клиента

Службам WCF также может потребоваться проверка подлинности клиентов служб с помощью учетных данных. Платформа Xamarin не поддерживает протокол WS-Security, который позволяет клиентам отправлять учетные данные в конверт сообщения SOAP. Однако платформа Xamarin поддерживает возможность отправки учетных данных проверки подлинности HTTP Basic на сервер, указав соответствующие ClientCredentialTypeпараметры:

basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

Затем можно указать базовые учетные данные проверки подлинности:

client.ClientCredentials.UserName.UserName = @"foo";
client.ClientCredentials.UserName.Password = @"mrsnuggles";

Дополнительные сведения о базовой проверке подлинности HTTP, хотя в контексте веб-службы REST см. в разделе "Проверка подлинности веб-службы RESTful".