Упражнение. Использование службы REST с HttpClient
В рамках приложения, которое инженеры используют на посещениях сайта клиента, необходимо добавить функцию, которая позволяет инженеру искать сведения о электрических компонентах. Эти сведения будут храниться в базе данных и доступ к ним будет через веб-службу REST. Вам также было предложено предоставить интерфейс, позволяющий администратору создавать, удалять и изменять сведения о частях, содержащихся в базе данных, с помощью той же веб-службы REST.
В этом упражнении вы развернете веб-службу REST в Azure, а затем убедитесь, что к ней можно получить доступ с помощью веб-браузера. Затем вы добавите функции в существующее приложение, которое использует веб-службу REST для получения, добавления, удаления и обновления сведений о электрических компонентах.
Это упражнение выполняется с помощью песочницы Azure.
Совет
Чтобы скопировать команду в буфер обмена, нажмите кнопку Копировать. Для вставки щелкните правой кнопкой мыши новую строку в терминале Cloud Shell и выберите команду Вставить или нажмите клавиши SHIFT+INSERT (⌘+V в macOS).
Развертывание веб-службы Parts REST
В окне Cloud Shell выполните следующую команду, чтобы клонировать репозиторий, содержащий код для этого упражнения, включая веб-службу Parts REST:
git clone https://github.com/microsoftdocs/mslearn-dotnetmaui-consume-rest-services
Перейдите в папку "Использование rest-services ":
cd mslearn-dotnetmaui-consume-rest-services/src
Выполните следующую команду, чтобы развернуть веб-службу частей с помощью песочницы Azure Cloud Shell. Эта команда делает службу доступной по уникальному URL-адресу. Запишите этот URL-адрес, когда он отобразится. Настройка приложения для подключения к веб-службе будет выполнена с использованием этого URL-адреса.
bash initenvironment.sh
Изучение кода для веб-службы
Примечание.
Оставшаяся часть этого упражнения будет выполнена на локальном компьютере разработки.
На компьютере откройте окно командной строки и клонируйте репозиторий для этого упражнения. Код находится в репозитории net-maui-learn-consume-rest-services.
git clone https://github.com/microsoftdocs/mslearn-dotnetmaui-consume-rest-services
Примечание.
Рекомендуется клонировать или скачать содержимое упражнения по короткому пути к папке, например C:\dev, чтобы избежать превышения максимальной длины пути для созданных файлов.
Перейдите в папку src\webservice\PartsServer в клоне репозитория и откройте решение PartsServer.sln с помощью Visual Studio или папки в Visual Studio Code. Это решение содержит копию кода для веб-службы, развернутой в Azure во время предыдущей процедуры.
В окне Обозревателя решений разверните папку Модели. Эта папка содержит два файла:
Part.cs. Класс Part представляет часть, предоставляемую веб-службой REST. Поля включают идентификатор части, имя части, тип части, дату доступности (при первом указании части) и список поставщиков. Свойство Href возвращает относительный URI части. Клиент REST может использовать этот URI для ссылки на эту конкретную часть в веб-службе REST. Свойство Поставщики возвращает список поставщиков части в виде строки.
PartsFactory.cs. Класс PartsFactory инициализирует список частей, предоставляемых службой, используя небольшой набор жестко заданных значений. В реальном мире эти данные будут получены из базы данных.
В окне Обозревателя решений разверните папку Контроллеры. Она содержит следующие файлы:
PartsController.cs. Класс PartsController реализует веб-API для службы. Он включает методы, позволяющие клиентским приложениям получать список всех частей (Получить), находить сведения о конкретной части по идентификатору части (перегруженная версия Получить), обновлять сведения о части (Разместить), добавлять новую часть в список (Post) и удалять часть из списка (Удалить).
LoginController.cs. Класс LoginController реализует простую форму проверки подлинности для веб-службы. Приложение должно отправить HTTP-запрос GET этому контроллеру, который возвращает маркер проверки подлинности. Этот маркер проверки подлинности используется для проверки подлинности запросов, отправленных в PartsController.
BaseController.cs. Класс BaseController содержит логику, используемую для проверки подлинности запросов. Класс PartsController наследуется от этого класса. Если клиент пытается вызвать методы в классе PartsController без предоставления допустимого маркера проверки подлинности, методы возвращают ответ HTTP 401 (не санкционировано).
Изучение кода для клиентского приложения .NET MAUI
В этом модуле используется пакет SDK для .NET 8.0. Убедитесь, что установлен .NET 8.0, выполнив следующую команду в предпочтительном терминале команд:
dotnet --list-sdks
Выходные данные, аналогичные следующему примеру, отображаются:
6.0.317 [C:\Program Files\dotnet\sdk]
7.0.401 [C:\Program Files\dotnet\sdk]
8.0.100 [C:\Program Files\dotnet\sdk]
Убедитесь, что в списке есть версия, которая начинается с цифры 8
. Если нет списка или команда не найдена, установите последний пакет SDK для .NET 8.0.
Закройте решение PartsServer и откройте решение PartsClient в папке src\client\PartsClient в клонированного репозитория. Это решение содержит частичную реализацию клиентского приложения .NET MAUI, которое использует веб-службу PartsServer.
В окне Обозреватель решений разверните папку "Данные". Эта папка содержит код для двух классов:
PartsManager.cs. Класс PartsManager предоставляет методы, которые клиентское приложение использует для взаимодействия с веб-службой REST. Этот класс в настоящее время является неполным. Вы добавите необходимый код в этом упражнении. По завершении метод GetClient подключается к веб-службе REST. Метод GetAll возвращает список частей из веб-службы REST. Метод Add добавляет новую часть в список частей, управляемых веб-службой REST. Метод Update изменяет сведения о части, сохраненной веб-службой REST, и метод Delete удаляет часть.
Part.cs. Класс Part моделирует часть, хранимую в базе данных. Он предоставляет свойства, которые приложение может использовать для доступа к полям PartID (Идентификатор части), PartName (Имя части), PartAvailableDate (Дата доступности части), PartType (Тип части) и PartSuppliers (Поставщики части). Этот класс также предоставляет служебный метод с именем SupplierString, который приложение может использовать для получения отформатированной строки, содержащей имена поставщиков.
В окне Обозревателя решений откройте папку Страницы. Эта папка содержит разметку и код для двух страниц:
PartsPage.xaml. На этой странице используется макет CollectionView с DataTemplate для отображения сведений о частях, доступных в виде списка. DataTemplate использует привязку данных для подключения отображаемых для частей данных, полученных из веб-службы. Можно выбрать строку в CollectionView , чтобы изменить часть в AddPartPage, или нажмите кнопку "Добавить новую часть ", чтобы добавить новую часть.
AddPartPage.xaml. Эта страница позволяет пользователям вводить и сохранять сведения для новой части. Пользователи могут указать имя части, тип части и начального поставщика. Идентификатор части и дата доступности части создаются автоматически.
В окне Обозревателя решений разверните папку Модели представления. Эта папка содержит два класса: AddPartViewModel.cs и PartsViewModel.cs. Это модели представления для соответствующих страниц и содержат свойства и логику страницы, необходимые для отображения и управления данными.
Вход в службу
Служба REST требует, чтоб вы сначала получили маркер проверки подлинности. Проверка подлинности пользователя отсутствует. Сначала необходимо вызвать определенную конечную точку, чтобы получить маркер авторизации, а затем отправить маркер обратно серверу на каждый последующий запрос в заголовке HTTP.
Откройте файл PartsManager.cs в папке Данные.
Добавьте статические поля BaseAddress и Url, как определено в следующем фрагменте кода, в класс PartsManager. Замените URL GOES HERE (URL-АДРЕС ТУТ) URL-адресом веб-службы REST, который вы записали ранее:
public class PartsManager { static readonly string BaseAddress = "URL GOES HERE"; static readonly string Url = $"{BaseAddress}/api/"; ... }
Добавьте следующее поле в класс после поля URL-адреса. Это поле будет содержать маркер проверки подлинности, возвращаемый при входе пользователя:
private static string authorizationKey;
Найдите метод GetClient. В настоящее время этот метод вызывает исключение NotImplementedException. Замените существующий в этом методе код следующим кодом. Этот код создает объект HttpClient , а затем отправляет запрос в конечную точку входа веб-службы REST. Служба должна ответить сообщением, содержащее маркер проверки подлинности. Десериализуйте этот маркер и добавьте его в качестве заголовка запроса авторизации по умолчанию для последующих запросов, отправленных с помощью объекта HttpClient:
private static async Task<HttpClient> GetClient() { if (client != null) return client; client = new HttpClient(); if (string.IsNullOrEmpty(authorizationKey)) { authorizationKey = await client.GetStringAsync($"{Url}login"); authorizationKey = JsonSerializer.Deserialize<string>(authorizationKey); } client.DefaultRequestHeaders.Add("Authorization", authorizationKey); client.DefaultRequestHeaders.Add("Accept", "application/json"); return client; }
Выполнение операции GET для получения сведений о частях
В файле PartsManager.cs найдите метод GetAll. Это асинхронный метод, который возвращает перечисляемый список частей. Этот метод еще не реализован.
В этом методе удалите код, который вызывает исключение NotImplementedException.
Проверьте, подключено ли устройство к Интернету с помощью класса
Connectivity
. Если интернет отсутствует, верните пустоеList<Part>
значение.if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet) return new List<Part>();
Вызовите метод GetClient, чтобы получить объект HttpClient для работы. Помните, что GetClient является асинхронным, поэтому используйте оператор await для записи объекта, возвращаемого этим методом.
Вызовите метод GetStringAsync объекта HttpClient и укажите базовый URL-адрес для получения массива частей из веб-службы REST. Данные возвращаются асинхронно в виде строки JSON.
Десериализация строки JSON, возвращаемой этим методом, в список объектов Part с помощью метода JsonSerializer.Deserialize . Верните этот список вызывающей стороне.
Готовый метод должен выглядеть так:
public static async Task<IEnumerable<Part>> GetAll() { if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet) return new List<Part>(); var client = await GetClient(); string result = await client.GetStringAsync($"{Url}parts"); return JsonSerializer.Deserialize<List<Part>>(result, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, }); }
Выполните сборку и запустите приложение. При запуске приложения должна появиться страница списка частей и список частей, полученных методом GetAll. На следующем рисунке показано приложение, работающее на Android:
Завершив просмотр данных, закройте приложение и вернитесь в Visual Studio или Visual Studio Code.
Выполнение операции POST для добавления новой части в базу данных
В классе PartsManager найдите метод Add. Этот метод имеет параметры для имени части, поставщика и типа части. Этот метод является асинхронным. Цель метода — вставить новую часть в базу данных и вернуть объект Part , представляющий только что созданный элемент.
Удалите существующий код в методе.
Проверьте, подключено ли устройство к Интернету с помощью класса
Connectivity
. Если интернет отсутствует, верните пустоеPart
значение.if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet) return new Part();
Создайте новый объект части. Заполните поля переданными данными:
- Задайте для поля PartID (Идентификатор части) пустую строку. Этот идентификатор будет создан веб-службой REST.
- Создайте новый список для хранения имени поставщика.
- Задайте для поля PartAvailableDate (Дата доступности части) значение DateTime.Now.
- Получите HTTP-клиента из метода GetClient.
var part = new Part() { PartName = partName, Suppliers = new List<string>(new[] { supplier }), PartID = string.Empty, PartType = partType, PartAvailableDate = DateTime.Now.Date };
Вызовите метод GetClient, чтобы получить объект HttpClient для работы.
Создайте объект
HttpRequestMessage
. Этот объект используется для моделирования запроса, отправляемого в веб-службу. Инициируйте его с параметрами, указывающими, какую команду HTTP следует использовать, и URL-адресом веб-службы для взаимодействия.var msg = new HttpRequestMessage(HttpMethod.Post, $"{Url}parts");
Необходимо отправить полезные данные в веб-службу со сведениями о части для создания. Эти полезные данные будут сериализованы в JSON. Полезные данные JSON будут добавлены в свойство
HttpRequestMessage.Content
и сериализированы с помощью методаJsonContent.Create
.msg.Content = JsonContent.Create<Part>(part);
Теперь отправьте сообщение в веб-службу с помощью функции
HttpClient.SendAsync
. Эта функция возвращает объектHttpResponseMessage
, содержащий сведения об операции на сервере. Например, коды отклика HTTP и сведения, передаваемые с сервера.var response = await client.SendAsync(msg); response.EnsureSuccessStatusCode();
Обратите внимание, что в предыдущем примере используется
response.EnsureSuccessStatusCode
метод. Это приведет к ошибке при возврате чего-либо, кроме кода состояния HTTP 2xx.Если веб-служба возвращает информацию, например объект, сериализованный в ФОРМАТЕ JSON, его можно считывать из
HttpResponseMessage
. Затем можно десериализировать JSON с помощьюJsonSerializer.Deserialize
.var returnedJson = await response.Content.ReadAsStringAsync(); var insertedPart = JsonSerializer.Deserialize<Part>(returnedJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, });
Наконец, возвращается новая вставленная часть.
return insertedPart;
Выполните сборку и запустите приложение. Нажмите кнопку Add New Part (Добавить новую часть) и введите имя, тип и поставщика, чтобы создать новую часть. Выберите Сохранить. Будет вызван метод Add в классе PartsManager, который создает новую часть в веб-службе. Если операция выполнена успешно, страница списка частей снова появится, а новая часть будет находиться в нижней части списка.
Завершив просмотр данных, закройте приложение и вернитесь в Visual Studio или Visual Studio Code.
Выполнение операции PUT для обновления сведений о части в базе данных
В классе PartsManager найдите метод Update. Это асинхронный метод, который принимает объект Часть в качестве параметра. Метод не имеет явного возвращаемого значения. Однако тип возвращаемого значения — Задача, поэтому исключения возвращаются вызываемой стороне должным образом. Давайте реализуем функцию PUT.
Удалите существующий код.
Как и ранее, проверьте наличие подключения к Интернету.
if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet) return;
Создайте новое сообщение
HttpRequestMessage
, на этот раз указав операцию PUT и URL-адрес для обновления частей.HttpRequestMessage msg = new(HttpMethod.Put, $"{Url}parts/{part.PartID}");
Задайте свойство
Content
дляHttpRequestMessage
с помощью функцииJsonContent.Create
и параметра part, переданного в функцию.msg.Content = JsonContent.Create<Part>(part);
Получите HTTP-клиента из метода GetClient.
var client = await GetClient();
Отправьте запрос с помощью
HttpClient
и убедитесь, что он выполнен успешно.var response = await client.SendAsync(msg); response.EnsureSuccessStatusCode();
Выполните сборку и запустите приложение. Выберите одну из частей из списка. Откроется страница AddPart , на этот раз со свойствами, которые уже заполнены. Обновите все, что нужно.
Выберите Сохранить. При этом вызывается метод Update в классе PartsManager для отправки изменений в веб-службу. В случае успешного выполнения на странице списка частей снова отобразятся изменения.
Примечание.
Часть, добавленная в предыдущей задаче, не будет отображаться на странице списка частей. Данные, которые использует приложение, сбрасываются в список предопределенных частей при каждом запуске приложения. Это обеспечивает согласованность для тестирования приложения.
Выполните операцию DELETE, чтобы удалить сведения о части из базы данных.
В классе PartsManager найдите метод Delete. Это асинхронный метод, который принимает строку partId и возвращает задачу.
Удалите существующий код.
Проверьте наличие подключения к Интернету.
if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet) return;
Создайте новый объект
HttpRequestMessage
. Теперь укажите только HTTP-команду DELETE и URL-адрес для удаления части.HttpRequestMessage msg = new(HttpMethod.Delete, $"{Url}parts/{partID}");
Получите HTTP-клиента из метода GetClient.
var client = await GetClient();
Отправьте запрос в веб-службу. Проверьте успешность после возврата.
var response = await client.SendAsync(msg); response.EnsureSuccessStatusCode();
Выполните сборку и запустите приложение. Выберите часть из списка и нажмите кнопку "Удалить" на странице "Добавить часть". В случае успешного выполнения страница списка частей снова появится, а удаленная часть больше не будет отображаться.