8. REST as a data source


The data that our retrieve can come from all kinds of places: a database, a third-party API, webhooks, and so on. These are called data sources. The beauty of is that you can mix any number of to create an API that serves the needs of your client applications and graph consumers.

In this lesson, we will:

  • Examine the existing Spotify REST API, the perfect for MusicMatcher
  • Generate a C# HttpClient using an OpenAPI specification to handle our HTTP requests, responses and types
  • Register the HttpClient with our

The Spotify Web API

MusicMatcher needs music, and for this course, we're going to be using a lite, pared down version of the official Spotify Web API. We can access that version here: https://spotify-demo-api-fe224840a08c.herokuapp.com/v1/docs/


Spotify REST API docs

Let's explore the documentation. We've got a few endpoints available for us centered around playlists– in fact, it's all we need to implement the features we covered earlier!

Diving into the /browse/featured-playlists endpoint, let's click "Try it out", then "Execute" a request.


Spotify REST API featured playlists endpoint


Spotify REST API featured playlists endpoint

We get a JSON object back with two top-level properties: message and playlists. Inside the playlists property, we have an items property, which contains a list, as well as a few other properties that seem to be related to pagination (like limit, next, previous, offset). And then the items list contains objects with its own properties. These objects represent a playlist!

That's a lot of nested properties just to get to what we want – the list of featured playlists!

The shape of the response from our HTTP endpoints often doesn't exactly match what we want to return from our 's types and . And that's okay! One of the benefits of GraphQL is that we only expose what the client may need. In this iteration of the schema for example, we only need to expose the name, description and ID of a playlist.

The HTTP responses also come back in JSON (JavaScript Object Notation) format, whereas in .NET we're dealing with classes. For these reasons, we'll need to do some conversions, serializing, and deserializing our HTTP response types to our C# types.

A common way to make HTTP requests and handle responses is with the built-in HttpClient class, as well as the built-in System.Text.Json package, or the Newtonsoft Json.NET package.

In this course, we want to focus on the concepts, not fiddling around manually writing types from a REST API. To help make our work go faster, we're going to auto-generate the code for our HTTP Client handler.

Auto-generating an HTTP Client

We'll use a tool called nswag to generate a C# client based on an OpenAPI specification.

We've already included a swagger.json file in your project inside the Data folder. This OpenAPI file defines the endpoints, expected responses, and schemas for response objects.

We'll use nswag from the command line so let's install it as a local .NET tool.

First, we'll create a manifest file. From the terminal, run:

dotnet new tool-manifest

We should get this message as a result:

The template "Dotnet local tool manifest file" was created successfully.

Then, install the nswag tool.

dotnet tool install NSwag.ConsoleCore --version 14.0.1

With a successful install, we'll see this message:

You can invoke the tool from this directory using the following commands: 'dotnet tool run nswag' or 'dotnet nswag'.
Tool 'nswag.consolecore' (version '14.0.1') was successfully installed. Entry is added to the manifest file [/path/to/dotnet-tools.json].

Finally, we'll run the command to use nswag.

dotnet nswag openapi2csclient \
/input:Data/swagger.json \
/classname:SpotifyService \
/namespace:SpotifyWeb \

This command:

  1. Takes the swagger.json file as an input
  2. Generates a C# client with the classname SpotifyService
  3. Outputs it into Data/SpotifyService.cs under the new namespace SpotifyWeb

Note that we've specified a different namespace from where our and types are defined (which is Odyssey.MusicMatcher). This is to avoid type naming collisions from our HTTP response and our types.

The terminal output should look something like this:

NSwag command line tool for .NET Core Net70, toolchain v13.20.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0))
Visit http://NSwag.org for more information.
NSwag bin directory: /Users/apollo/.nuget/packages/nswag.consolecore/13.20.0/tools/net7.0/any
Code has been successfully written to file.

Let's take a look at that newly created file SpotifyService.cs, in the Data folder!

Right off the top, we see a comment that the file contents have been autogenerated. Scrolling down to the constructor, we can see that this class is using HttpClient.

If we try to run our project now, we'll see a list of errors complaining about the namespace called Newtonsoft. We'll need to install this package for our SpotifyService to work.

dotnet add package Newtonsoft.Json

With that, all our errors should disappear!

Feel free to examine the SpotifyService class more thoroughly if you're curious. We won't be diving into the details of every single method and line here. However, we can rest assured that this service will manage the specifics of sending HTTP requests to the Spotify REST API and translating requests into C# classes and types that we'll be able to work with. Handy!

Adding to our GraphQL server

Let's connect this service to our , back in Program.cs.

At the top, we'll import the namespace for SpotifyWeb.

using SpotifyWeb;

We'll see an error pop up under the AddType<Playlist> symbol.

'Playlist' is an ambiguous reference between 'Odyssey.MusicMatcher.Playlist' and 'SpotifyWeb.Playlist'CS0104

Remember the Playlist class we defined earlier on in the Types folder? The autogenerated SpotifyService class has defined the same type, with the same name! This is why we specified a different namespace when we ran the nswag command, to avoid naming collisions.

But now, AddType<Playlist> is ambiguous; are we referring to SpotifyWeb.Playlist or Odyssey.MusicMatcher.Playlist? We're referring to the latter, so we should change it to AddType<Odyssey.MusicMatcher.Playlist>.

However, we can also remove that method altogether, since it's not needed. We added it earlier on when we had no way of reaching the Playlist object through the Query type, just to see what it would look like in our reference. But now that the Playlist object is reachable from the Query.featuredPlaylists , we don't need it anymore!

Let's go ahead and remove it. Don't forget to leave that ; to end the statement just after the AddQueryType call.

- .AddType<Playlist>;

Let's connect our SpotifyService with the server. We'll use the AddHttpClient method for this, just above the methods.


Note that this line is separate from the AddGraphQLServer() methods.

Our functions should now have access to the SpotifyService using dependency injection. Before moving on, we'll tidy up our functions with one more configuration. Chaining onto our methods, we'll use the RegisterService method and pass in the SpotifyService class.


We'll see how exactly this affects our functions (and keeps them tidier!) in the next lesson.


What is the purpose of the SpotifyService class generated by nswag?
What does the AddHttpClient<SpotifyService>() configuration in the GraphQL server setup accomplish?
Why is the namespace for SpotifyService specified differently from the GraphQL server's namespace?

Key takeaways

  • allows the use of various , such as databases, REST APIs, and webhooks, to create a flexible API that caters to client application needs.
  • A does not need to follow the shape, pattern, or naming of the it uses.
  • We can use the nswag tool to auto-generate a C# HTTP Client based on an OpenAPI specification, simplifying the handling of HTTP requests and responses.
  • The SpotifyService is registered with the using the AddHttpClient and RegisterService methods, making it available via dependency injection in functions.

Up next

Let's put our SpotifyService to work and get that list of featured playlists!


Share your questions and comments about this lesson

This course is currently in

. Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.