HttpClient Extensions

ParkSquare.Extensions.Http

BUILD STATUS Continuous Integration Build Status

INSTALLATION

Install-Package ParkSquare.Extensions.Http

DESCRIPTION

HttpClient extensions to provide convenient methods for GET, POST, PUT and DELETE for JSON and XML web services.

Documentation

HttpClient extensions to provide convenient methods for GET, POST, PUT and DELETE. Includes typed request/responses with built-in serialization and deserialization to/from JSON and XML. Supports access to CookieContainer on the request and response and Bearer auth header. Has built-in conversion of any request object to JSON or querystring depending on the HTTP verb. Also supports FormUrlEncoded and binary (byte array) MultipartForm requests.

How To Use

Install the package and you will be able to use several extension methods on the HttpClient object. These conveniently wrap the functionality for turning your request object into something correctly serialized for the JSON or XML endpoint you are calling. For the typed overloads, the response object is also deserialized back into an object.

Although you can use these extension methods on any HttpClient you have instantiated, the recommended way is to use the built-in dependency injection. You may find it useful to read our guide on injecting HttpClient and IHttpClientFactory in .Net Core.

Calling JSON API Endpoints

GET


    using ParkSquare.Extensions.Http.Json;

    // GET from JSON endpoint with no response object

    Task GetAsync(Uri uri)

    // GET from JSON endpoint with no response object, automatically converting request object into query string

    Task GetAsync(Uri uri, object request)

    // GET from JSON endpoint, automatically deserializing into TResponse object

    Task<TResponse> GetAsync<TResponse>(Uri uri)

    // GET from JSON endpoint, automatically converting request object into query string and deserializing response into TResponse object

    Task<TResponse> GetAsync<TResponse>(Uri uri, object request)

    // GET from JSON endpoint with Bearer auth token header

    Task<TResponse> GetAsync<TResponse>(Uri uri, object request, string bearerToken)

POST



    using ParkSquare.Extensions.Http.Json;
    
    // POST to JSON endpoint with no response object

    Task PostAsync(Uri uri)

    // POST to JSON endpoint with no response object, automatically serializing request into request body

    Task PostAsync(Uri uri, object request)

    // POST to JSON endpoint, automatically deserializing response into TResponse object

    Task<TResponse> PostAsync<TResponse>(Uri uri)

    // POST to JSON endpoint, automatically serializing request into request body, and deserializing response into TResponse object

    Task<TResponse> PostAsync<TResponse>(Uri uri, object request)

    // POST to JSON endpoint, with Bearer auth token header

    Task<TResponse> PostAsync<TResponse>(Uri uri, object request, string bearerToken)

PUT



    using ParkSquare.Extensions.Http.Json;
    
    // PUT to JSON endpoint with no response object, automatically converting request object into request body

    Task PutAsync(Uri uri, object request)

    // PUT to JSON endpoint, automatically converting request object into request body and deserializing into TResponse object

    Task<TResponse> PutAsync<TResponse>(Uri uri, object request)

    // PUT to JSON endpoint with Bearer auth token header

    Task<TResponse> PutAsync<TResponse>(Uri uri, object request, string bearerToken)

DELETE


    using ParkSquare.Extensions.Http.Json;

    // DELETE

    Task DeleteAsync(Uri uri)

POSTing Files to JSON API Using Multipart Form

These methods make it easy to post multipart form data containing a byte array. This is generally used for uploading a file from a 'contact us' type form. The byte array content can be given a name and a filename. Under the hood, this creates a MultipartFormDataContent object containing a single ByteArrayContent part.


    using ParkSquare.Extensions.Http.Json;
        
    Task PostAsync(Uri uri, string filename, byte[] data, string contentName = "file")

    // Similar to above, but deserializes the JSON response into a TResponse object

    Task<TResponse> PostAsync<TResponse>(Uri uri, string filename, byte[] data, string contentName = "file")

API Calls With Cookies

The cookie jar in .Net Core is handled by the CookieContainer class, which is maintained by the HttpClient's HttpClientHandler. When using dependency injection techniques it is possible to specify a CookieContainer instance for a specific HttpClient. This neatly solves the problem of every HttpClient being able to read or write cookies in the container, which may not be desirable.

This library provides the CookieAccessor class to simplify the creation, and subsequent access to the per-client CookieContainer instance.

Dependency Registration


    services.AddSingleton<ICookieAccessor, CookieAccessor>();

    services.AddHttpClient<IClientUsingCookies, ClientUsingCookies>()
        .ConfigurePrimaryHttpMessageHandler(serviceProvider =>
            new HttpClientHandler
            {
                UseCookies = true,
                CookieContainer = serviceProvider.GetRequiredService<ICookieAccessor>().Container
            });

Client Implementation


    public class ClientUsingCookies : IClientUsingCookies
    {
        private readonly HttpClient _httpClient;
        private readonly ICookieAccessor _cookieAccessor;

        public ClientUsingCookies(HttpClient httpClient, ICookieAccessor cookieAccessor)
        {
            _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
            _cookieAccessor = cookieAccessor ?? throw new ArgumentNullException(nameof(cookieAccessor));
        }

        public async Task DoSomethingAsync()
        {
            var uri = new Uri("https://api.example.com/");

            // Set a test cookie
            _cookieAccessor.SetCookie(new Cookie("test", "hello", "", uri.DnsSafeHost));
        
            // Make the call. You can use Fiddler to verify the cookie is set on the request.
            var response = await _httpClient.GetAsync(uri);
    
            // Use the CookieAccessor again to directly access the CookieContainer
            var value = _cookieAccessor.GetCookie(uri, "test");

            // An alternative way of reading the cookies is to get the raw value from this header
            var cookies = response.Result.Headers.SingleOrDefault(header => header.Key == "Set-Cookie");
        }
    }

Calling XML API Endpoints

The XML extensions are rather more limited than the JSON ones, but provide a similar level of convenience.

GET


    using ParkSquare.Extensions.Http.Xml;

    // GET from JSON endpoint, automatically deserializing into TResponse object

    Task<TResponse> GetAsync<TResponse>(Uri uri)