Упражнение. Использование службы 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 9.0. Убедитесь, что установлен .NET 9.0, выполнив следующую команду в предпочтительном терминале команд:

dotnet --list-sdks

Выходные данные, аналогичные следующему примеру, отображаются:

8.0.100 [C:\Program Files\dotnet\sdk]
9.0.100 [C:\Program Files\dotnet\sdk]

Убедитесь, что в списке есть версия, которая начинается с цифры 9. Если ни один из них отсутствует или команда не найдена, установите последний пакет SDK для .NET 9.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:

    Снимок экрана: клиентское приложение частей, работающее в Android с списком частей.

  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, который создает новую часть в веб-службе. Если операция выполнена успешно, страница списка частей снова появится, а новая часть будет находиться в нижней части списка.

    Снимок экрана приложения, запущенного после добавления новой части. Новая часть находится в нижней части списка.

  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 для отправки изменений в веб-службу. В случае успешного выполнения на странице списка частей снова отобразятся изменения.

    Снимок экрана: приложение, работающее с первым элементом в списке.

    Примечание.

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

Выполните операцию 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. Выполните сборку и запустите приложение. Выберите часть из списка и нажмите кнопку "Удалить" на странице "Добавить часть". В случае успешного выполнения страница списка частей снова появится, а удаленная часть больше не будет отображаться.