Sai A Sai A
Updated date May 02, 2023
This article provides an introduction to GraphQL with Hot Chocolate in .NET Core. It covers the basics of defining a schema, creating a GraphQL server, and implementing resolvers for fields. It also shows how to use the GraphQL Playground to test our API with queries, mutations, and subscriptions.

Introduction:

GraphQL is a query language for APIs that provides a more efficient, powerful, and flexible alternative to traditional REST APIs. It was developed by Facebook in 2012 and open-sourced in 2015. Since then, it has gained popularity in the development community, and many tools and libraries have been built around it. In this article, we will explore how to implement a GraphQL API using Hot Chocolate, a GraphQL server for .NET Core.

Hot Chocolate is an open-source library that provides a simple and fast way to build GraphQL APIs on top of .NET Core. It supports features like batching, caching, subscriptions, and more. It is also highly customizable and extensible, making it a great choice for building GraphQL APIs of any size.

Getting Started:

To get started, we will create a new .NET Core project using Visual Studio. We will name it "HotChocolateDemo". Once the project is created, we will add the Hot Chocolate NuGet package to our project. To do this, right-click on the project in the Solution Explorer, select "Manage NuGet Packages...", and search for "HotChocolate". Once found, click "Install" to add the package to the project.

Creating a GraphQL Schema:

The first step in creating a GraphQL API is to define the schema. A schema is a collection of types that define the data that can be queried, and the relationships between them. In Hot Chocolate, we define the schema using GraphQL SDL (Schema Definition Language). Here is an example schema for a simple blog API:

type Query {
  posts: [Post!]!
  post(id: ID!): Post
}

type Mutation {
  createPost(title: String!, content: String!): Post!
}

type Subscription {
  postCreated: Post!
}

type Post {
  id: ID!
  title: String!
  content: String!
  comments: [Comment!]!
}

type Comment {
  id: ID!
  text: String!
  author: String!
  post: Post!
}

This schema defines a Query type with two fields: "posts" and "post". The "posts" field returns a list of Post objects, and the "post" field takes an ID parameter and returns a single Post object. It also defines a Mutation type with one field: "createPost". This field takes two string parameters (title and content) and returns a new Post object. Finally, it defines a Subscription type with one field: "postCreated". This field is used for real-time updates whenever a new Post object is created.

Creating a GraphQL API:

Now that we have defined our schema, we can create a GraphQL API using Hot Chocolate. To do this, we need to create a GraphQL server and add our schema to it. Here is an example code for our GraphQL server:

using HotChocolate;
using HotChocolate.AspNetCore;
using HotChocolate.AspNetCore.Playground;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

namespace HotChocolateDemo
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddGraphQL(sp => SchemaBuilder.New()
                .AddQueryType<Query>()
                .AddMutationType<Mutation>()
                .AddSubscriptionType<Subscription>()
                .Create());
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UsePlayground(new PlaygroundOptions
                {
                    QueryPath = "/api/graphql",
                    Path = "/playground"
                });
            }

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGraphQL();
            });
        }
    }
}

This code defines a Startup class that configures our GraphQL server. In the ConfigureServices method, we use the AddGraphQL extension method to add a GraphQL server to the services collection. We pass a lambda that creates a new schema using the SchemaBuilder, and adds our Query, Mutation, and Subscription types to it.

In the Configure method, we check if the environment is Development. If it is, we enable the developer exception page and add a GraphQL Playground middleware to the pipeline. The GraphQL Playground is a web-based IDE for interacting with GraphQL APIs, and it provides a graphical interface for exploring the API schema, testing queries, and subscriptions. We configure the PlaygroundOptions to use the /api/graphql endpoint for queries, and the /playground endpoint for the Playground UI.

Next, we add the routing middleware and map the GraphQL endpoint to the /api/graphql URL. This is where our GraphQL API will be exposed.

Creating Resolvers:

Now that we have defined our schema and created our GraphQL server, we need to implement the resolvers for our fields. A resolver is a function that provides the data for a field. In Hot Chocolate, we can define resolvers as methods on our Query, Mutation, and Subscription types. Here is an example code for our resolvers:

public class Query
{
    private readonly List<Post> _posts = new List<Post>
    {
        new Post { Id = "1", Title = "First Post", Content = "Lorem ipsum dolor sit amet." },
        new Post { Id = "2", Title = "Second Post", Content = "Consectetur adipiscing elit." }
    };

    public IEnumerable<Post> GetPosts() => _posts;

    public Post GetPost(string id) => _posts.FirstOrDefault(p => p.Id == id);
}

public class Mutation
{
    private readonly List<Post> _posts = new List<Post>();

    public Post CreatePost(string title, string content)
    {
        var post = new Post
        {
            Id = Guid.NewGuid().ToString(),
            Title = title,
            Content = content
        };

        _posts.Add(post);

        return post;
    }
}

public class Subscription
{
    [Subscribe]
    [Topic]
    public Post OnPostCreated([EventMessage] Post post) => post;
}

This code defines the resolvers for our Query, Mutation, and Subscription types.

For the Query type, we define two methods: "GetPosts" and "GetPost". The "GetPosts" method returns the list of posts, and the "GetPost" method takes an ID parameter and returns the post with that ID. We use a private list of posts to store the data.

For the Mutation type, we define a single method: "CreatePost". This method takes two string parameters (title and content) and returns a new Post object. We generate a new ID using Guid.NewGuid(), create a new Post object with the provided title and content, add it to the list of posts, and return it.

For the Subscription type, we define a single method: "OnPostCreated". This method is decorated with the [Subscribe] and [Topic] attributes, which indicate that it should be used as a subscription resolver and that the topic for the subscription is a Post object. We also use the [EventMessage] attribute to indicate that the method should receive the Post object that triggered the subscription event.

Testing the GraphQL API:

With our schema, server, and resolvers in place, we can now test our GraphQL API using the Playground UI. When we navigate to the /playground endpoint, we will see the Playground UI with a sidebar containing our schema. We can expand the schema and explore our types, fields, and arguments. We can also write queries, mutations, and subscriptions using the editor on the right-hand side of the UI. Here are some example queries that we can run:

query {
  getPosts {
    id
    title
    content
  }
}

query {
  getPost(id: "1") {
    id
    title
    content
  }
}

mutation {
  createPost(title: "New Post", content: "Lorem ipsum dolor sit amet.") {
    id
    title
    content
  }
}

subscription {
  onPostCreated {
    id
    title
    content
  }
}

The first query retrieves all the posts from the server, including their ID, title, and content. The second query retrieves a single post with ID "1". The mutation creates a new post with the title "New Post" and the content "Lorem ipsum dolor sit amet.", and returns its ID, title, and content. The subscription listens for new posts, and returns their ID, title, and content as soon as they are created.

Conclusion:

In this article, we have introduced the basics of GraphQL with Hot Chocolate in .NET Core. We have covered how to define a schema, create a GraphQL server, and implement resolvers for our fields. We have also shown how to use GraphQL Playground to test our API with queries, mutations, and subscriptions. Hot Chocolate is a powerful and flexible GraphQL server for .NET Core, and it provides many features out of the box, such as middleware, batching, caching, and authorization. With Hot Chocolate, we can build robust and scalable APIs that meet the demands of modern applications.

Comments (0)

There are no comments. Be the first to comment!!!