Введение в веб-службы
В этом руководстве показано, как использовать различные технологии веб-службы. В этой статье рассматриваются сведения о взаимодействии со службами 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#, такие как HttpWebRequest
RestSharp, классы, зависящие от платформы, также доступны для использования веб-служб. Например, в 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
Это создает прокси-сервер в папке "Ссылки на веб- или службы" проекта. Так как прокси-сервер создается код, его не следует изменять.
Добавление прокси-сервера вручную в проект
Если у вас есть существующий прокси-сервер, созданный с помощью совместимых средств, эти выходные данные можно использовать при включении в проект. В 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".