How to build GraphQL APIs with ASP.NET Core & HotChocolate – Part 1 – Setup

Getting started with GraphQL as a .NET developer is much simpler than you would think. Let me show you why.

Coming from a REST or MVC background GraphQL looks scary.

I know.

It is very different from what we are used to, especially in the .NET (Core) ecosystem.

There’s no (built-in) template. With traditional RESTful APIs (or MVC apps for that matter) you select your template and you get a ready-to-run solution right away. Not with GraphQL. This makes it look like GraphQL on ASP.NET Core is complicated and a pain to get started with.

I am here to show you, it is not.

In this article I will show you how to:

  • Set up HotChocolate and GraphiQL for your ASP.NET Core application.
  • Define types from your GraphQL schema using C#.
  • Create your resolvers to wire up real data to those types. (Part 2)
  • Implement pagination. (Part 2)

Who is this article for?

This series of articles focuses on authoring GraphQL APIs using the ASP.NET Core platform.

I am going to assume you have already acquired a solid understanding of the fundamental principles of GraphQL itself. If not, I would suggest heading over to https://graphql.org/ and going through the documentation first.

We will not go into advanced topics – such as directives, fragments, custom scalars, etc, not even mutations – but you are expected to understand the basics of the type system, queries, lists, nullability, and enums.

The API you are going to build by the end of this article

I don’t like overly simplified tutorials, they usually miss out on the most important architectural problems.

Instead, here we are going to pretend we’re in charge of building a real-world API of an airline travel company: The dataset consists of airlines, airports, and routes between them. The dataset that we are going to use is a full-scale real-world snapshot of said data.

I built a NuGet package that contains all our data, so we don’t have to worry about a database now, we can instead focus on the important part: GraphQL.

I strongly believe APIs should be built design-first so that’s what we are going to do.

Let’s pretend this is the schema our architects built and was given to us for implementation:

type Query{
    routes(offset: Int, limit: Int): [Route!]!
    airlines(offset: Int, limit: Int): [Airline!]!
}

type Route{
    airline: Airline!
    source: Airport!
    destination: Airport!
    codeshare: Boolean!
    stops: Int!
}

type Airline{
    id: ID!
    name: String!
    iata: String
    origin: Country!
    destinations: [Airport!]!
    routes: [Route!]!
}

type Airport{
    id: ID!
    name: String!
    city: String!
    country: Country!
    iata: String
    timezone: Float!
    airlines: [Airline!]!
    routes: [Route!]!
}

type Country{
    name: String!
    isoCode: String!
    dafifCode: String!
}

schema{
    query: Query
}

We have the schema, we have the "database", so let’s get started.

Project setup (very simple)

I promised you this is going to be very simple. So here it is:

We are going to start with an Empty ASP.NET Core 3.1 project template. We can even get rid of the UseEndpoints call, so our method looks like this:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

        app.UseRouting();
    }
}

Can’t get much simpler, right?

Adding HotChocolate from NuGet

As you might have noticed, ASP.NET Core does not include GraphQL support by default. This isn’t going to stop us though, there are two great GraphQL server implementations for ASP.NET Core: graphql-dotnet and HotChocolate. I am not going to talk about the differences here, but my choice is HotChocolate which we’re going to use for this tutorial. Having said that, all I am going to show you here could just as well be achieved with graphql-dotnet.

Let’s install 3 HotChocolate NuGet packages:

  • HotChocolate – contains the core GraphQL server logic
  • HotChocolate.AspNetCore – contains the AspNetCore bindings
  • HotChocolate.AspNetCore.GraphiQL – this one is optional, contains graphiql an amazing GraphQL playground we can use to test-drive our server.

Configuring the GraphQL middleware

Let’s add these two lines at the end of Configure:

      app.UseGraphiQL();
      app.UseGraphQL();

This wires up both HotChocolate and GraphiQL to our application.

Configuring your GraphQL schema

If you tried to run the above, it crashes on startup with some cryptic error message. That is because we haven’t told HotChocolate what schema we’d like to use for our endpoint. So let’s do that.

Step 1: the schema file

A wonderful feature of HotChocolate is that it can read our schema from the .graphql file directly, without us having to transform it into C# syntax.

To do that, we have to add the schema file to our project (I am going to call it "schema.graphql") and make sure to set the CopyToOutputDirectory property on it, so it gets placed right next to our output dll.

Step 2: ConfigureServices

Now that we have our file in the project let’s tell HotChocolate to load it. This is done inside ConfigureServices, like so:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGraphQL(
            SchemaBuilder.New()
                .AddDocumentFromFile("./schema.graphql")
                .Create()
        );
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

        app.UseRouting();

        app.UseGraphiQL();
        app.UseGraphQL();
    }
}

If you run your app again, you should now be facing a new error message:

Schema errors

This is great. It means the schema is recognized and HotChocolate doesn’t know how to serve it yet – because we haven’t written the logic for it yet. It is like a series of NotImplementedExceptions.

The setup part is complete here.

Our goal for the next part of this article will be to add all backing Type and Resolver classes for all these GraphQL types until all the error messages are gone.

Conclusion

In just a few minutes, you set up a GraphQL server configuration in your ASP.NET Core application.

Thank you for reading this first part of the article, feel free to share if you liked it.

In the second part of the series, we will cover implementing the actual GraphQL types for this airline example: Query, Route, Airport, et cetera.

In the meanwhile, you can check out the Github Repository containing the final source code of our sample API.