Follow me: Jack Histon's Twitter Share on LinkedIn Share on Google+ RSS Feed

Author avatar

Welcome. I am Jack Histon. My career would not be what it is today without dedication and hard work from software bloggers. My purpose is to give back to that online community.

A type-safe REST

Monday, 28 August 2017

Tweet about this on Twitter Share on Facebook Share on LinkedIn Share on Google+ Pin on Pinterest Share on Reddit Share on StumbleUpon

In the current age of microservices, we have communication between different processes across a wide variety of hosts and platforms. At other times, we integrate with 3rd party libraries, downloading information and metadata that may be necessary for our current application. On some of those occasions, we need to interact with a REST API.

Wouldn't it be nice if when interacting with REST APIs, we could allow the compiler to help us out? what if we could create a type safe way of interacting with a REST api, and do away with HttpClient, and other unopinionated abstractions? This is what Refit, "The automatic type-safe REST library for .NET Core, Xamarin, and .NET", can do for us.

What is Refit?

Refit is essentially a wrapper. It uses the HttpClient, and turns it's API into an opinionated API. Written by Paul Betts, it is an API that fits exactly your needs. It was heavily inspired by Retrofit; a similar idea for Android and Java.

Let's take an example. The UK's food standards agency has a lot of open and public apis for consumption. One such API is the UK food hygiene rating data API. The API allows you to query the local authorities within the area, and their acceptance ratings.

An HttpClient Example

A typical call to this REST API would be:


var client = new HttpClient();

client.BaseAddress = new Uri("http://api.ratings.food.gov.uk/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-version", "2");

var response = await client.GetAsync("Authorities");

We could then deserialise this into something like the following:


public class Link
{
    public string rel { get; set; }
    public string href { get; set; }
}

/// 
/// Represents a local authority within the government food rating api.
/// 
public class LocalAuthority
{
    public int LocalAuthorityId { get; set; }
    public string LocalAuthorityIdCode { get; set; }
    public string Name { get; set; }
    public string FriendlyName { get; set; }
    public string Url { get; set; }
    public string SchemeUrl { get; set; }
    public string Email { get; set; }
    public string RegionName { get; set; }
    public string FileName { get; set; }
    public string FileNameWelsh { get; set; }
    public int EstablishmentCount { get; set; }
    public string CreationDate { get; set; }
    public string LastPublishedDate { get; set; }
    public int SchemeType { get; set; }
    public List<Link> links { get; set; }
}

public class LocalAuthoritiesResult
{
    public List<LocalAuthority> authorities { get; set; }
    public Meta meta { get; set; }
    public List<Link> links { get; set; }
}

This could be achieved by using Newtonsoft.Json:


if (response.IsSuccessStatusCode)
{
    var data = await response.Content.ReadAsStringAsync();

    if (!string.IsNullOrWhiteSpace(data))
    {
        result = await Task.Run(() => JsonConvert.DeserializeObject<LocalAuthoritiesResult>(data));
    }
}

Here we are reading the content of the response as a string. We are then using the JsonConvert class to deserialise the string data into the POCO class "LocalAuthoritiesResult".

Refit Example

The main problem with the previous code is that the actual request strings are hard coded. Not only that, but the HTTP method of interaction with the api is also signified by a method call.

Refit can make this much simpler and straightforward. It can give you an API that reads well, and is not hiding any details of what you are actually interacting with.


public interface IFoodStandardsApi
{
    [Headers("x-api-version: 2", "Accept: application/json")]
    [Get("/Authorities")]
    Task<LocalAuthoritiesResult> GetLocalAuthorities();
}

This is the same example as before, but now we have turned out API into a type safe version. To use this API, we would do the following:


IFoodStandardsApi foodStandardsApi = RestService.For<IFoodStandardsApi>("http://api.ratings.food.gov.uk/");

LocalAuthoritiesResult localAuthorities = await foodStandardsApi.GetLocalAuthorities();

Summary

Refit is a fantastic tool to allow you to create interfaces out of your APIs, and consume them at runtime. This is not a new idea, such things as Retrofit have been around for some time.

I think that the simplicity and the quick setup of Refit, along with it's type safe approach, should be the go to tool for anything concerning REST apis.

Hope this helps.

Share with a friend

Please share this blog post so others can learn from it as well.

Tweet about this on Twitter Share on Facebook Share on LinkedIn Share on Google+ Pin on Pinterest Share on Reddit Share on StumbleUpon

Recent Posts

Archives



© 2017 - Jack Histon - Blog