This is a project implementing GraphQL in .NET 6+ using the Hot Chocolate library. This project integrates with the Spotify Web API and serves as a sandbox for exploring advanced GraphQL patterns, from schema design to resolver chains and performance optimization.
Odyssey.MusicMatcher/
├── Types/
│ ├── Query.cs # Top-level query definitions
│ ├── Mutation.cs # GraphQL mutations (write operations)
│ ├── Playlist.cs # GraphQL object type for Playlists
│ ├── Track.cs # Track type (songs)
│ ├── Artist.cs # Artist type (if extended)
│ ├── AddItemsToPlaylistInput.cs
│ ├── AddItemsToPlaylistPayload.cs
├── Program.cs # Entry point and service setup
Using attributes like [GraphQLDescription]
and [ID]
, each C# class (like Playlist
, Track
) is mapped to a GraphQL object type.
All read operations are exposed via Query.cs
. Example:
{
featuredPlaylists {
id
name
description
}
}
This triggers the FeaturedPlaylists()
method which calls Spotify’s REST API, transforms the data, and returns a list of Playlist
objects.
Write operations are defined in Mutation.cs
. Example:
mutation {
addItemsToPlaylist(input: {
playlistId: "xyz",
uris: ["spotify:track:abc", "spotify:track:def"]
}) {
success
message
playlist {
name
}
}
}
This triggers a REST API call to Spotify to add items to a playlist.
In GraphQL, each nested field can trigger its own resolver. For example:
{
featuredPlaylists {
name
tracks {
name
uri
}
}
}
- The top-level resolver fetches simplified playlist data.
- When
tracks
is requested, the resolver methodTracks()
is called on eachPlaylist
instance. - This is where resolver chaining happens — each level pulls data only if requested.
This app doesn't use a backing database — it uses Spotify’s REST API as the data source, wrapped in GraphQL. For instance:
GetFeaturedPlaylistsAsync()
GetPlaylistAsync(id)
GetPlaylistsTracksAsync(id)
These are mapped to GraphQL queries using model transformation inside resolvers.
If a query requests playlists and their tracks, and each tracks
resolver fetches data individually, this results in:
- 1 request to fetch playlists
- N requests (one per playlist) to fetch tracks
This is inefficient, especially with large datasets.
Use Hot Chocolate's DataLoader
to batch requests for tracks:
public Task<List<Track>> Tracks(
[Service] PlaylistTracksDataLoader dataLoader
)
{
return dataLoader.LoadAsync(Id);
}
The DataLoader
batches all calls to Tracks()
and performs a single REST call to fetch all track data at once — solving the N+1 problem efficiently.
- How to design intuitive and descriptive GraphQL schemas.
- Difference between
properties
andmethods
as GraphQL resolvers. - How resolver chaining works and why it matters for performance.
- Best practices for exposing a REST API through GraphQL.
- Importance of error handling using
GraphQLException
and custom error codes. - How mutations work and return standardized payloads with
code
,success
, andmessage
.
- .NET 6
- Hot Chocolate (GraphQL for .NET)
- Spotify Web API
- C# 10
- Apollo Studio (used for running GraphQL queries)
- Add your Spotify API credentials to a
.env
file:
CLIENT_ID=your_client_id
CLIENT_SECRET=your_client_secret
- Run the app:
dotnet run
- Open Apollo Studio Explorer or Postman and hit:
http://localhost:5059/graphql
- Add
DataLoader
to batch track fetching. - Explore authorization and user-specific data.
- Add pagination and filtering to queries.
- Create a frontend UI to consume this API.