Сериализация и десериализация запросов и ответов при использовании HttpClient

Просто о NET | создано: 10.09.2018 | опубликовано: 10.09.2018 | обновлено: 13.01.2024 | просмотров: 4416

Приятно работать с объектами, не правда ли? А еще хорошо, когда ты отправляешь один объект в запросе, а в ответ получаешь другой объект. То есть совсем не нужно парсить ответ от сервера и следить за полнотой данных отправленных этому серверу.

Вступление

В последнее время часто, даже очень часто, приходится отправлять запросы и получать ответы. Такова тенденция разработки на любой платформе. Так или иначе, всё что может "уйти в облако" - уходит в облако! А это значит, что для того чтобы получить данные из облака (или любого другого сервиса или даже микросервиса) приходится использовать протокол HTTP (или его защищенную версию - HTTPS). Таким образом, получается, что если вы не используете на стороне Backend конкретно ASP.NET MVC (Core) или WEB API, то вам приходилось использовать объект HttpClient. Хотя, правды ради, надо сказать, что HttpClient можно использовать и на перечисленных платформах. HttpClient является универсальным объектом, который работает на всех (или почти на всех) платформах. А это значит, что он работает с универсальными объектами, доступными на разных платформах, совершенно никак не связанных с вашей бизнес-логикой. Например: HttpResponseMessage, HttpMessageHandler, HttpContent и прочие объекты. В любом случае вы всегда по протоколу HTTP отправляется сериализованные в строку объекты, и получается также сериализованные в строку объекты. А это, согласитесь, не совсем удобно, если вы работаете с Domain-моделями.

Зачем всё это

Я предлагаю HttpGetPost - nuget-пакет, который ничего в себе сверхестественного не содержит, кроме HttpClient и JsonConverter. Котороый призван, чтобы облегчить процесс сериализации нужного объекта перед отправкой по http и десериализацией в объект после получения его от сервера.

Про HttpGetPost

Как я уже сказал, HttpGetPost - это nuget-пакет, которые может сериализовать и десериализовать объекты при работе с ними через HttpClient. Помимо этого, есть еще некоторые полезные "фишки", такие как класс LoaderResult, который возвращается как результат работы любого метода:

/// <summary>
/// Base Loader Result
/// </summary>
public abstract class LoaderResultBase
{
    /// <summary>
    /// HttpClient response Wrapper
    /// </summary>
    /// <param name="requestedUrl"></param>
    protected LoaderResultBase(string requestedUrl)
    {
        RequestedUrl = requestedUrl;
    }

    /// <summary>
    /// Error
    /// </summary>
    public Exception Exception { get; set; }

    /// <summary>
    /// Requested Url
    /// </summary>
    public string RequestedUrl { get; set; }
}

Надо отметить, что это не первая попытка "обложить кодом" HttpClient. До этого был ApiResult, после него ApiLoader и вот, наконец, HttpGetPost.

Что внутри

Внутри есть основной класс HttpLoader, который реализует интерфейс IHttpLoader.

/// <summary>
/// Generic HttpClient loader (get/post) (with/without) payload
/// It is a wrapper for <seealso cref="HttpClient"/>.
/// </summary>
public interface IHttpLoader
{

    /// <summary>
    /// Returns base URL
    /// </summary>
    string Url { get; }

    /// <summary>
    /// Replaces the base Url
    /// </summary>
    /// <param name="baseUrl"></param>
    void SetBaseUrl(string baseUrl);

    /// <summary>
    /// Load string data from string by Get Verb
    /// </summary>
    /// <param name="url">web api service URL</param>
    /// <param name="options"></param>
    /// <returns></returns>
    Task<LoaderResult> GetAsync(string url, HttpClientOptions options);

    /// <summary>
    /// Load string data from string by Get Verb
    /// </summary>
    /// <param name="url">web api service URL</param>
    /// <returns></returns>
    Task<LoaderResult> GetAsync(string url);

    /// <summary>
    /// Load data from string by Get Verb
    /// </summary>
    /// <param name="url">web api service URL</param>
    /// <param name="options"></param>
    /// <returns></returns>
    Task<LoaderResult<TResult>> GetAsync<TResult>(string url, HttpClientOptions options = null) where TResult : class;

    /// <summary>
    /// /// Send to the web api service payload data
    /// </summary>
    /// <typeparam name="TResult">generic type as deserialize target</typeparam>
    /// <typeparam name="TPayload">generic type of the payload</typeparam>
    /// <param name="url">web api service URL</param>
    /// <param name="payload">the payload for request</param>
    /// <param name="options"></param>
    /// <returns></returns>
    Task<LoaderResult<TResult>> PostAsync<TResult, TPayload>(string url, TPayload payload, HttpClientOptions options = null) where TResult : class;

    /// <summary>
    /// Send to the web api service payload data
    /// </summary>
    /// <param name="url">web api service URL</param>
    /// <param name="data">the payload for request</param>
    /// <param name="options">HttpClient options</param>
    /// <returns></returns>
    Task<LoaderResult<TResult>> PostAsync<TResult>(string url, object data, HttpClientOptions options = null) where TResult : class;
}

Все  методы имеют generic TPayload параметр на входе и LoadResult<TResult> на выходе. На основании этих generic-параметров и происходит сериализация и десериализация на базе NewtonSoft.Json. Всё просто, никакой магии, просто удобный инструмент для любой платформы (ну или почти любой).

Ссылки

HttpGetPost - nuget-пакет содержащий HttpClient + сериализация на базе NewtonSoft.Json.