Упражнение. Использование службы REST с HttpClient

Завершено

В рамках приложения, которое инженеры используют на посещениях сайта клиента, необходимо добавить функцию, которая позволяет инженеру искать сведения о электрических компонентах. Эти сведения будут храниться в базе данных и доступ к ним будет через веб-службу REST. Вам также было предложено предоставить интерфейс, позволяющий администратору создавать, удалять и изменять сведения о частях, содержащихся в базе данных, с помощью той же веб-службы REST.

В этом упражнении вы развернете веб-службу REST в Azure, а затем убедитесь, что к ней можно получить доступ с помощью веб-браузера. Затем вы добавите функции в существующее приложение, которое использует веб-службу REST для получения, добавления, удаления и обновления сведений о электрических компонентах.

Это упражнение выполняется с помощью песочницы Azure.

Совет

Чтобы скопировать команду в буфер обмена, нажмите кнопку Копировать. Для вставки щелкните правой кнопкой мыши новую строку в терминале Cloud Shell и выберите команду Вставить или нажмите клавиши SHIFT+INSERT (⌘+V в macOS).

Развертывание веб-службы Parts REST

  1. В окне Cloud Shell выполните следующую команду, чтобы клонировать репозиторий, содержащий код для этого упражнения, включая веб-службу Parts REST:

    git clone https://github.com/microsoftdocs/mslearn-dotnetmaui-consume-rest-services
    
  2. Перейдите в папку "Использование rest-services ":

    cd mslearn-dotnetmaui-consume-rest-services/src
    
  3. Выполните следующую команду, чтобы развернуть веб-службу частей с помощью песочницы Azure Cloud Shell. Эта команда делает службу доступной по уникальному URL-адресу. Запишите этот URL-адрес, когда он отобразится. Настройка приложения для подключения к веб-службе будет выполнена с использованием этого URL-адреса.

    bash initenvironment.sh
    

Изучение кода для веб-службы

Примечание.

Оставшаяся часть этого упражнения будет выполнена на локальном компьютере разработки.

  1. На компьютере откройте окно командной строки и клонируйте репозиторий для этого упражнения. Код находится в репозитории net-maui-learn-consume-rest-services.

    git clone https://github.com/microsoftdocs/mslearn-dotnetmaui-consume-rest-services
    

    Примечание.

    Рекомендуется клонировать или скачать содержимое упражнения по короткому пути к папке, например C:\dev, чтобы избежать превышения максимальной длины пути для созданных файлов.

  2. Перейдите в папку src\webservice\PartsServer в клоне репозитория и откройте решение PartsServer.sln с помощью Visual Studio или папки в Visual Studio Code. Это решение содержит копию кода для веб-службы, развернутой в Azure во время предыдущей процедуры.

  3. В окне Обозревателя решений разверните папку Модели. Эта папка содержит два файла:

    • Part.cs. Класс Part представляет часть, предоставляемую веб-службой REST. Поля включают идентификатор части, имя части, тип части, дату доступности (при первом указании части) и список поставщиков. Свойство Href возвращает относительный URI части. Клиент REST может использовать этот URI для ссылки на эту конкретную часть в веб-службе REST. Свойство Поставщики возвращает список поставщиков части в виде строки.

    • PartsFactory.cs. Класс PartsFactory инициализирует список частей, предоставляемых службой, используя небольшой набор жестко заданных значений. В реальном мире эти данные будут получены из базы данных.

  4. В окне Обозревателя решений разверните папку Контроллеры. Она содержит следующие файлы:

    • 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.

  1. Закройте решение PartsServer и откройте решение PartsClient в папке src\client\PartsClient в клонированного репозитория. Это решение содержит частичную реализацию клиентского приложения .NET MAUI, которое использует веб-службу PartsServer.

  2. В окне Обозреватель решений разверните папку "Данные". Эта папка содержит код для двух классов:

    • PartsManager.cs. Класс PartsManager предоставляет методы, которые клиентское приложение использует для взаимодействия с веб-службой REST. Этот класс в настоящее время является неполным. Вы добавите необходимый код в этом упражнении. По завершении метод GetClient подключается к веб-службе REST. Метод GetAll возвращает список частей из веб-службы REST. Метод Add добавляет новую часть в список частей, управляемых веб-службой REST. Метод Update изменяет сведения о части, сохраненной веб-службой REST, и метод Delete удаляет часть.

    • Part.cs. Класс Part моделирует часть, хранимую в базе данных. Он предоставляет свойства, которые приложение может использовать для доступа к полям PartID (Идентификатор части), PartName (Имя части), PartAvailableDate (Дата доступности части), PartType (Тип части) и PartSuppliers (Поставщики части). Этот класс также предоставляет служебный метод с именем SupplierString, который приложение может использовать для получения отформатированной строки, содержащей имена поставщиков.

  3. В окне Обозревателя решений откройте папку Страницы. Эта папка содержит разметку и код для двух страниц:

    • PartsPage.xaml. На этой странице используется макет CollectionView с DataTemplate для отображения сведений о частях, доступных в виде списка. DataTemplate использует привязку данных для подключения отображаемых для частей данных, полученных из веб-службы. Можно выбрать строку в CollectionView , чтобы изменить часть в AddPartPage, или нажмите кнопку "Добавить новую часть ", чтобы добавить новую часть.

    • AddPartPage.xaml. Эта страница позволяет пользователям вводить и сохранять сведения для новой части. Пользователи могут указать имя части, тип части и начального поставщика. Идентификатор части и дата доступности части создаются автоматически.

  4. В окне Обозревателя решений разверните папку Модели представления. Эта папка содержит два класса: AddPartViewModel.cs и PartsViewModel.cs. Это модели представления для соответствующих страниц и содержат свойства и логику страницы, необходимые для отображения и управления данными.

Вход в службу

Служба REST требует, чтоб вы сначала получили маркер проверки подлинности. Проверка подлинности пользователя отсутствует. Сначала необходимо вызвать определенную конечную точку, чтобы получить маркер авторизации, а затем отправить маркер обратно серверу на каждый последующий запрос в заголовке HTTP.

  1. Откройте файл PartsManager.cs в папке Данные.

  2. Добавьте статические поля 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/";
        ...
    }
    
  3. Добавьте следующее поле в класс после поля URL-адреса. Это поле будет содержать маркер проверки подлинности, возвращаемый при входе пользователя:

    private static string authorizationKey;
    
  4. Найдите метод 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 для получения сведений о частях

  1. В файле PartsManager.cs найдите метод GetAll. Это асинхронный метод, который возвращает перечисляемый список частей. Этот метод еще не реализован.

  2. В этом методе удалите код, который вызывает исключение NotImplementedException.

  3. Проверьте, подключено ли устройство к Интернету с помощью класса Connectivity. Если интернет отсутствует, верните пустое List<Part>значение.

    if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet)
        return new List<Part>();
    
  4. Вызовите метод GetClient, чтобы получить объект HttpClient для работы. Помните, что GetClient является асинхронным, поэтому используйте оператор await для записи объекта, возвращаемого этим методом.

  5. Вызовите метод GetStringAsync объекта HttpClient и укажите базовый URL-адрес для получения массива частей из веб-службы REST. Данные возвращаются асинхронно в виде строки JSON.

  6. Десериализация строки 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,
            });                     
    }
    
  7. Выполните сборку и запустите приложение. При запуске приложения должна появиться страница списка частей и список частей, полученных методом GetAll. На следующем рисунке показано приложение, работающее на Android:

    A screenshot of the Parts Client app running on Android showing a list of parts.

  8. Завершив просмотр данных, закройте приложение и вернитесь в Visual Studio или Visual Studio Code.

Выполнение операции POST для добавления новой части в базу данных

  1. В классе PartsManager найдите метод Add. Этот метод имеет параметры для имени части, поставщика и типа части. Этот метод является асинхронным. Цель метода — вставить новую часть в базу данных и вернуть объект Part , представляющий только что созданный элемент.

  2. Удалите существующий код в методе.

  3. Проверьте, подключено ли устройство к Интернету с помощью класса Connectivity. Если интернет отсутствует, верните пустое Partзначение.

    if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet)
        return new Part();
    
  4. Создайте новый объект части. Заполните поля переданными данными:

    • Задайте для поля 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
    };
    
  5. Вызовите метод GetClient, чтобы получить объект HttpClient для работы.

  6. Создайте объект HttpRequestMessage. Этот объект используется для моделирования запроса, отправляемого в веб-службу. Инициируйте его с параметрами, указывающими, какую команду HTTP следует использовать, и URL-адресом веб-службы для взаимодействия.

    var msg = new HttpRequestMessage(HttpMethod.Post, $"{Url}parts");
    
  7. Необходимо отправить полезные данные в веб-службу со сведениями о части для создания. Эти полезные данные будут сериализованы в JSON. Полезные данные JSON будут добавлены в свойство HttpRequestMessage.Content и сериализированы с помощью метода JsonContent.Create.

    msg.Content = JsonContent.Create<Part>(part);
    
  8. Теперь отправьте сообщение в веб-службу с помощью функции HttpClient.SendAsync. Эта функция возвращает объект HttpResponseMessage, содержащий сведения об операции на сервере. Например, коды отклика HTTP и сведения, передаваемые с сервера.

    var response = await client.SendAsync(msg);
    response.EnsureSuccessStatusCode();
    

    Обратите внимание, что в предыдущем примере используется response.EnsureSuccessStatusCode метод. Это приведет к ошибке при возврате чего-либо, кроме кода состояния HTTP 2xx.

  9. Если веб-служба возвращает информацию, например объект, сериализованный в ФОРМАТЕ JSON, его можно считывать из HttpResponseMessage. Затем можно десериализировать JSON с помощью JsonSerializer.Deserialize.

    var returnedJson = await response.Content.ReadAsStringAsync();
    
    var insertedPart = JsonSerializer.Deserialize<Part>(returnedJson, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true,
            });
    
  10. Наконец, возвращается новая вставленная часть.

    return insertedPart;
    
  11. Выполните сборку и запустите приложение. Нажмите кнопку Add New Part (Добавить новую часть) и введите имя, тип и поставщика, чтобы создать новую часть. Выберите Сохранить. Будет вызван метод Add в классе PartsManager, который создает новую часть в веб-службе. Если операция выполнена успешно, страница списка частей снова появится, а новая часть будет находиться в нижней части списка.

    A screenshot of the app running after a new part has been added. The new part is at the bottom of the list.

  12. Завершив просмотр данных, закройте приложение и вернитесь в Visual Studio или Visual Studio Code.

Выполнение операции PUT для обновления сведений о части в базе данных

  1. В классе PartsManager найдите метод Update. Это асинхронный метод, который принимает объект Часть в качестве параметра. Метод не имеет явного возвращаемого значения. Однако тип возвращаемого значения — Задача, поэтому исключения возвращаются вызываемой стороне должным образом. Давайте реализуем функцию PUT.

  2. Удалите существующий код.

  3. Как и ранее, проверьте наличие подключения к Интернету.

    if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet)
        return;
    
  4. Создайте новое сообщение HttpRequestMessage, на этот раз указав операцию PUT и URL-адрес для обновления частей.

    HttpRequestMessage msg = new(HttpMethod.Put, $"{Url}parts/{part.PartID}");
    
  5. Задайте свойство Content для HttpRequestMessage с помощью функции JsonContent.Create и параметра part, переданного в функцию.

    msg.Content = JsonContent.Create<Part>(part);
    
  6. Получите HTTP-клиента из метода GetClient.

    var client = await GetClient();
    
  7. Отправьте запрос с помощью HttpClient и убедитесь, что он выполнен успешно.

    var response = await client.SendAsync(msg);
    response.EnsureSuccessStatusCode();
    
  8. Выполните сборку и запустите приложение. Выберите одну из частей из списка. Откроется страница AddPart , на этот раз со свойствами, которые уже заполнены. Обновите все, что нужно.

  9. Выберите Сохранить. При этом вызывается метод Update в классе PartsManager для отправки изменений в веб-службу. В случае успешного выполнения на странице списка частей снова отобразятся изменения.

    A screenshot of the app running with the first item in the list updated.

    Примечание.

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

Выполните операцию DELETE, чтобы удалить сведения о части из базы данных.

  1. В классе PartsManager найдите метод Delete. Это асинхронный метод, который принимает строку partId и возвращает задачу.

  2. Удалите существующий код.

  3. Проверьте наличие подключения к Интернету.

    if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet)
        return;
    
  4. Создайте новый объект HttpRequestMessage. Теперь укажите только HTTP-команду DELETE и URL-адрес для удаления части.

    HttpRequestMessage msg = new(HttpMethod.Delete, $"{Url}parts/{partID}");
    
  5. Получите HTTP-клиента из метода GetClient.

    var client = await GetClient();
    
  6. Отправьте запрос в веб-службу. Проверьте успешность после возврата.

    var response = await client.SendAsync(msg);
    response.EnsureSuccessStatusCode();
    
  7. Выполните сборку и запустите приложение. Выберите часть из списка и нажмите кнопку "Удалить" на странице "Добавить часть". В случае успешного выполнения страница списка частей снова появится, а удаленная часть больше не будет отображаться.