Net 5 Quality of life improvements

Net 5 has shipped with a slew of nice quality of life improvements, especially in the web domain, so big thumbs up there 👍

Records

The first of these are records. These little beauties remove a lot of the tedium around building classes for your API requests to serialize data into. They are dead simple, and coupled with the new HttpClient extensions they make querying external services a breeze.

public record Book(string title, string author)
public record Author(string firstName, string surname)
public record LibraryBook(Book book, Author author)
public record Library(LibraryBook[] books)

These simple inline statements replace 4 class definitions and can be easily declared in the LibraryClient instance itself, the like other parameters.

GetFromJsonAsync()

That ties nicely into the next improvement. If the external API we are querying returns a json record that we have described with our Library record above, we can now simply declare the following

var library = _httpClient.GetFromJsonAsync<Library>(url);

User Secrets

This helps manage your configuration. We don’t want to be exposing our API keys in source code or json config, especially when in source control! By setting up a user secret, we can inject they key from a secure location on our machine directly into our application 🔐

ServiceSettings: {
  "host": "openlibrary.org.uk"
}

The above could be an entry in our appsettings.json file. We can then set up a ServiceSettings class and populate it as usual for our Setup

public class ServiceSettings
{
  public string Host {get;set;}
  public string ApiKey {get;set;}
}

//...

services.Configure<ServiceSettings>(Configuration.GetSection(nameof(ServiceSettings)))

This will use the value from our config to populate the Host value in ServiceSettings that we can then inject into our LibraryClient. But what about the key? As part of the CLI, you can run the following

dotnet user-secrets init
dotnet user-secrets set ServiceSettings:ApiKey yourkeyhere

This will inject the key value into the ServiceSettings object in the same way it does the appsettings.json value without needing to store the value in source.

HttpContext injection

Finally, we can register our HttpClients via the service now using services.AddHttpClient<LibraryClient> This will allow us to inject the HttpClient class directly into our http clients like below

public class LibraryClient
{
   private readonly HttpClient _httpClient;
   private readonly ServiceSettings _serviceSettings;

   public record Book(string title, string author)
   public record Author(string firstName, string surname)
   public record LibraryBook(Book book, Author author)
   public record Library(LibraryBook[] books)

   public LibraryClient(HttpClient httpClient, ServiceSettings serviceSettings)
   {
      _httpClient = httpClient;
      _serviceSettings = serviceSettings;
   }

   public async Task<Library> GetLibrary()
   {
      return await _httpclient
          .GetFromJsonAsync<Library>($"https://{_serviceSettings.Host}?apikey={_serviceSettings.ApiKey});
   }
}

This allows us to configure a bunch of other useful things like failed request retries and circuit breaking using Polly in the Startup where we configure the LibraryClient

All of the above gets rid of a lot of the API boiler plate code, which is a huge relief and a much appreciated addition to Net 🙌

👩‍💻