{"id":92678,"date":"2021-10-20T14:29:44","date_gmt":"2021-10-20T14:29:44","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=92678"},"modified":"2021-10-20T14:30:18","modified_gmt":"2021-10-20T14:30:18","slug":"building-and-consuming-graphql-api-in-asp-net-core-5","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/building-and-consuming-graphql-api-in-asp-net-core-5\/","title":{"rendered":"Building and consuming GraphQL API in ASP.NET Core 5"},"content":{"rendered":"<p>Since Roy Fielding coined REST in 2000, many applications have been built worldwide by adhering to the REST architectural constraints. REST has become widely popular primarily because of its simplicity and improved performance.<\/p>\n<p>However, APIs today have become much more complex, and you need efficient data retrieval from a data store that might contain vast amounts of structured and unstructured data. Hence an alternative to REST was imperative.<\/p>\n<p>Facebook chose to revamp its applications in 2012 to improve performance and efficiency. It was a time when Facebook&#8217;s mobile strategy didn&#8217;t work due to high network usage. While caching may have helped improve the app&#8217;s performance, the need of the hour was changing the data fetching strategy altogether. Here&#8217;s why GraphQL came in, and it has since grown in popularity by leaps and bounds within the development community.<\/p>\n<p>GraphQL is a platform-independent, language-neutral query language that has been around for a while and may be used to run queries and retrieve data. GraphQL, like REST, is a standard that offers an easy and flexible method to query your data. GraphQL Foundation is now responsible for maintaining GraphQL.<\/p>\n<p>This article talks about the characteristics and benefits of GraphQL before demonstrating how to use GraphQL with ASP.NET Core 5.<\/p>\n<h2>Pre-requisites<\/h2>\n<p>To work with the code examples illustrated in this article, you should have Visual Studio 2019 installed on your computer. If you don\u2019t have a copy of it yet, you can grab one from <a href=\"https:\/\/visualstudio.microsoft.com\/downloads\/\">here<\/a>. If you don\u2019t have .NET Core installed in your system, you can <a href=\"https:\/\/dotnet.microsoft.com\/download\/archives\">download a copy<\/a>.<\/p>\n<p>You can also find the complete code for the example in this article in <a href=\"https:\/\/github.com\/joydipkanjilal\/simple-graphql-demo\">GitHub repository<\/a>.<\/p>\n<h2>What is GraphQL?<\/h2>\n<p>GraphQL is an open-source, flexible query language (&#8220;QL&#8221; stands for query language) for APIs, as well as a runtime for query execution on existing data. It was initially developed internally by Facebook in 2012 and then made public in 2015. GraphQL can make APIs more responsive, flexible, and developer friendly. It prioritizes providing clients with only the information they need. A REST alternative, GraphQL allows developers to create requests that pull data from multiple data sources in a single API call.<\/p>\n<p>In GraphQL, you would typically send a declarative request in JSON format to get the data you need. The developer can\u00a0define the requests and the responses using a strongly typed query language, enabling the application to determine what data it needs from an API.<\/p>\n<p>One of the significant differences between REST and GraphQL is that the API determines the request and response in REST, whereas, in GraphQL, the client decides the data that the API should return to the client.<\/p>\n<p>If you develop an application that uses RESTful architecture, the number of endpoints may grow over time, making maintenance a nightmare. If you&#8217;re using GraphQL, you might be able to get all the data you need using just one endpoint: API\/Graphql.<\/p>\n<h2>Why do you need GraphQL?<\/h2>\n<p>Fewer roundtrips to the server &#8211; GraphQL requires fewer roundtrips, i.e., fewer back-and-forth calls to the server to get all the data you need.<\/p>\n<p>No over-fetching or under-fetching &#8211; Unlike REST, you will never have too little or too much data when using GraphQL since you can specify all the information you need from the API upfront.<\/p>\n<p>No versioning problems &#8211; GraphQL does not need versioning, and if you do not remove fields from the types, the API clients or consumers will not break.<\/p>\n<p>Reduced bandwidth &#8211; GraphQL usually requires fewer requests and less bandwidth. You can get all the data you need using a single API call to the API endpoint. Since you can specify the data you need, rather than retrieving all fields for a type, you may retrieve only the ones you need, thus reducing bandwidth and resource usage.<\/p>\n<p>Documentation &#8211; GraphQL is adept at creating GraphQL endpoints documentation, much like Swagger does for REST endpoints.<\/p>\n<p>Despite all the advantages GraphQL has to offer, there are a few downsides as well. GraphQL is complex, and it is difficult to implement caching or rate-limiting in GraphQL than in REST.<\/p>\n<h2>How does a GraphQL query work?<\/h2>\n<p>Each GraphQL query passes through three phases: parse, validate and execute. In the parse phase, the GraphQL query is tokenized and parsed into a representation known as an abstract syntax tree. In the validation phase, the graphical query is validated against the schema as shown in Figure 1.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92679\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-4.png\" alt=\"Image showing the GraphQL execution engine\" width=\"1183\" height=\"419\" \/><\/p>\n<p><strong>Figure 1: GraphQL execution<\/strong><\/p>\n<p>Finally, in the execute phase, the GraphQL runtime walks through the abstract syntax tree from the tree&#8217;s root, retrieves and aggregates the results, and sends the data back to the GraphQL client as JSON.<\/p>\n<h2>GraphQL vs. REST<\/h2>\n<p>Take a quick look at the differences between GraphQL and REST:<\/p>\n<ul>\n<li>Unlike REST, which may need multiple API calls to obtain the data you want, GraphQL exposes just one endpoint you can use to get the information you need.<\/li>\n<li>REST only works with HTTP, while GraphQL does not need HTTP.<\/li>\n<li>Unlike REST, which allows you to use any HTTP verb, GraphQL enables you to use only the HTTP POST verb.<\/li>\n<li>In REST, the API specifies the request and response. On the contrary, in GraphQL, the API defines the resources accessible, and the clients or consumers can request exactly the data they need from the API.<\/li>\n<li>When working with REST, the server determines the size of the resource. On the contrary, with GraphQL, the API specifies the accessible resources, and the client requests just what it needs.<\/li>\n<li>REST and GraphQL are both platform and language-neutral, and both can return JSON data.<\/li>\n<\/ul>\n<h2>Goals of GraphQL: What Problem Does It Solve?<\/h2>\n<p>There are several downsides of REST:<\/p>\n<ul>\n<li>Over-fetching &#8211; this implies your REST API sends you more data than you need<\/li>\n<li>Under-fetching &#8211; this implies your REST API sends you less data than you need<\/li>\n<li>Multiple requests &#8211; requiring multiple requests to get the data you need<\/li>\n<li>Multiple round trips &#8211; multiple requests required to complete an execution before you can proceed<\/li>\n<\/ul>\n<p>Over-fetching and under-fetching are two of the common problems you would often encounter when working with REST APIs. This is explained in more detail in the next section.<\/p>\n<h2>The Problem of Under-Fetching and Over-Fetching Explained<\/h2>\n<p>Here is a typical example of REST endpoints for a typical application that manages blog posts.<\/p>\n<pre class=\"lang:c# theme:vs2012\">GET \/blogposts\r\nGET \/blogposts\/{blogPostId}\r\nGET \/authors\r\nGET \/authors\/{authorId}<\/pre>\n<p>To aggregate the data, you will have to make several calls to the endpoints shown here. Note that a request to the \/blogposts endpoint would fetch the list of blogposts together with <code>authorId<\/code>, but it will not return author data. You need to make a call to <code>\/authors\/{authorId}<\/code> multiple times to get author details of the authors. This problem is known as under-fetching since your API payload contains less data than you need. You can take advantage of Backend for Frontend or the Gateway Aggregation pattern to solve this problem. Still, in either case, you will need multiple calls to the API endpoints.<\/p>\n<p>On the contrary, your API payload might be too verbose as well. For example, you might want to know only details of the blogposts by calling the \/blogposts endpoint, but your payload will also contain <code>authorId<\/code>. This problem is known as over-fetching, which implies that your API payload comprises more data than you need, hence consuming more network bandwidth. Here&#8217;s where GraphQL comes to the rescue.<\/p>\n<h2>Building Blocks of GraphQL<\/h2>\n<p>The main building blocks of GraphQL comprise schemas and types.<\/p>\n<h3>Schema<\/h3>\n<p>In GraphQL, there is just one endpoint. This endpoint provides a schema used to inform API consumers about the functionality available for clients to consume, i.e., what data they may expect and what actions they can perform. A Schema in GraphQL is a class that extends the Schema class of the <code>GraphQL.Types<\/code> namespace.<\/p>\n<p>GraphQL has three primary operations: Query for reading data, Mutation for writing data, and Subscription for receiving real-time updates. A schema contains Query, Mutation, and a Subscription..<\/p>\n<ul>\n<li>Query &#8211; In GraphQL, you can take advantage of queries for fetching or consuming data efficiently. The consumer or the client can mention the field or fields it needs instead of getting data for all the fields from a particular type. The client can only consume the fields that the API has exposed.<\/li>\n<li>Mutation &#8211; In GraphQL, mutations are used to add, modify, or delete data. The client can only take advantage of the mutations that the schema has exposed to modify the data. In other words, a GraphQL client cannot manipulate data exposed by the API unless there is an appropriate mutation available.<\/li>\n<li>Subscriptions &#8211; In GraphQL, subscriptions allow a server to send data to its clients, notifying them when events occur. Subscriptions support event-driven architectures, and they use WebSockets to provide real-time notifications.<\/li>\n<\/ul>\n<h3>GraphQL Object Types<\/h3>\n<p>One of the essential components of GraphQL schema is the object type, used to describe the kind of item that may be retrieved through your API. Object Types in GraphQL are represented using <code>GraphQL.Types.ObjectGraphType<\/code> class and contain fields and methods.<\/p>\n<h2>Implementing a GraphQL API in ASP.NET Core<\/h2>\n<p>Now leverage all learned thus far to build an application that uses GraphQL for performing CRUD operations.<\/p>\n<h3>Getting Started: The Solution Structure<\/h3>\n<p>Figure 2 below illustrates the solution structure of the completed application.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92680\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-5.png\" alt=\"Image showing the completed application\" width=\"510\" height=\"875\" \/><\/p>\n<p><strong>Figure 2: Application structure<\/strong><\/p>\n<p>As you can see, there is only one project in the Solution for the sake of simplicity. The DataAccess and GraphQL solution folders are under the root of the project. The Models solution folder is under the DataAccess solution folder. So, when this project is compiled, the following three libraries will be generated:<\/p>\n<ul>\n<li>BlogPostsmanagementSystem.dll<\/li>\n<li>BlogPostsManagementSystem.DataAccess.dll<\/li>\n<li>BlogPostsManagementSystem.DataAccess.Models.dll<\/li>\n<\/ul>\n<p>To help understand the organization of your code, including the dependencies, you can take advantage of CodeMaps in Visual Studio. Figure 3 below shows the CodeMap for this solution generated in Visual Studio 2019.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92681\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-6.png\" alt=\"Image showing the codemaps\" width=\"799\" height=\"429\" \/><\/p>\n<p><strong>Figure 3: Organization of Code and Dependencies as Viewed using CodeMaps<\/strong><\/p>\n<h3>Steps to build a GraphQL API in ASP.NET Core 5<\/h3>\n<p>To build the application discussed in this article, follow these steps:<\/p>\n<ol>\n<li>Create a new ASP.NET Core 5 application<\/li>\n<li>Install the NuGet Packages<\/li>\n<li>Create the Models<\/li>\n<li>Create the Data Context<\/li>\n<li>Register the Data Context<\/li>\n<li>Create the Repositories<\/li>\n<li>Add Services to the Container<\/li>\n<li>Build the GraphQL Schema<\/li>\n<li>Query<\/li>\n<li>Mutation<\/li>\n<li>Subscription<\/li>\n<li>Create the Resolvers<\/li>\n<li>Configure the GraphQL Middleware<\/li>\n<\/ol>\n<h3>Create a new ASP.NET Core 5 Application<\/h3>\n<p>First off, create a new ASP.NET Core 5 project. To do this, execute the following command at the shell:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">dotnet new web -f net5.0 --no-https --name BlogPostsManagementSystem<\/pre>\n<p>When you execute the above command, a new ASP.NET Core 5 project without HTTPS support will be created in the current directory.<\/p>\n<p>You can now take advantage of Visual Studio 2019 to open the project and make changes as needed. You\u2019ll use this project in the sections that follow.<\/p>\n<h3>Install the NuGet Packages<\/h3>\n<p>In this example, you\u2019ll take advantage of HotChocolate for working with GraphQL. Hot Chocolate is an open-source .NET GraphQL platform that adheres to the most current GraphQL specifications. It serves as a wrapper around the GraphQL library, making building a full-fledged GraphQL server easier.<\/p>\n<p>HotChocolate is very simple to set up and configure and removes the clutter from creating GraphQL schemas. You can take advantage of HotChocolate to create a GraphQL layer on top of your existing application layer.<\/p>\n<p>Since support for GraphQL is not in-built in ASP.NET Core, you\u2019ll need to install the necessary NuGet packages via the NuGet Package Manager or the NuGet Package Manager Console.<\/p>\n<p>You\u2019ll need to install the following packages:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">HotChocolate.AspNetCore\r\nHotChocolate.AspNetCore.Playground\r\nMicrosoft.EntityFrameworkCore.InMemory<\/pre>\n<p>To do this, run the following commands at the NuGet Package Manager Console Window:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">Install-Package HotChocolate.AspNetCore\r\nInstall-Package HotChocolate.AspNetCore.Playground\r\nInstall-Package Microsoft.EntityFrameworkCore.InMemory<\/pre>\n<p>Alternatively, you can install these packages by executing the following commands at the shell:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">dotnet add package HotChocolate.AspNetCore\r\ndotnet add package HotChocolate.AspNetCore.Playground\r\ndotnet add package Microsoft.EntityFrameworkCore.InMemory<\/pre>\n<p>Run the application now, then add <code>\/playground<\/code> to the URL to view the playground. . Here\u2019s how the output will look in the web browser.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92682\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/a-screenshot-of-a-computer-description-automatica.png\" alt=\"A screenshot of a running the application\" width=\"1376\" height=\"735\" \/><\/p>\n<p><strong>Figure 4: Output from web browser<\/strong><\/p>\n<h3>Create the Models<\/h3>\n<p>Create a solution folder called <em>DataAccess<\/em> at the root of the project. Create another solution folder inside the <em>DataAccess<\/em> folder called <em>Models<\/em>; this is where the entity classes will go.<\/p>\n<p>To make things simple, you\u2019ll use two model classes in this example named <em>Author<\/em> and <em>BlogPost<\/em>. Select your project in the <em>Solution Explorer Window<\/em>, right-click and select <em>Add -&gt; New Folder<\/em>. Inside this folder, create two .cs files named <em>Author.cs<\/em> and <em>BlogPost.cs<\/em> with the following content:<\/p>\n<p><strong>Author.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using HotChocolate;\r\nusing HotChocolate.Types;\r\nnamespace BlogPostsManagementSystem.DataAccess.Models\r\n{\r\n    public class Author\r\n    {\r\n        [GraphQLType(typeof(NonNullType&lt;IdType&gt;))]\r\n        public int Id { get; set; }\r\n        [GraphQLNonNullType]\r\n        public string FirstName { get; set; }\r\n        [GraphQLNonNullType]\r\n        public string LastName { get; set; }\r\n    }\r\n}<\/pre>\n<p><strong>BlogPost.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using HotChocolate;\r\nusing HotChocolate.Types;\r\nnamespace BlogPostsManagementSystem.DataAccess.Models\r\n{\r\n    public class BlogPost\r\n    {\r\n        public int Id { get; set; }\r\n        [GraphQLType(typeof(NonNullType&lt;StringType&gt;))]\r\n        public string Title { get; set; }\r\n        [GraphQLNonNullType]\r\n        public int AuthorId { get; set; }\r\n    }\r\n}<\/pre>\n<p>The <code>BlogPost<\/code> class contains a reference to the <code>Author<\/code> class. Hence a <code>BlogPost<\/code> can be written by only one author, but an author can write many blog posts.<\/p>\n<h3>Build the DataContext<\/h3>\n<p>This example takes advantage of Entity Framework Core (in-memory) to work with data. Create a class called <code>ApplicationDbContext<\/code> inside the <em>DataAccess<\/em> solution folder of your project and write the following code in it:<\/p>\n<p><strong>ApplicationDbContext.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess.Models;\r\nusing Microsoft.EntityFrameworkCore;\r\nnamespace BlogPostsManagementSystem.DataAccess\r\n{\r\n    public class ApplicationDbContext : DbContext\r\n    {\r\n        public ApplicationDbContext(DbContextOptions\r\n        &lt;ApplicationDbContext&gt; options) : base(options)\r\n        {\r\n        }\r\n        public DbSet&lt;Author&gt; Authors { get; set; }\r\n        public DbSet&lt;BlogPost&gt; BlogPosts { get; set; }\r\n        protected override void OnModelCreating\r\n        (ModelBuilder modelBuilder)\r\n        {\r\n            Author author1 = new Author\r\n            {\r\n                Id = 1,\r\n                FirstName = \"Joydip\",\r\n                LastName = \"Kanjilal\"\r\n            };\r\n            Author author2 = new Author\r\n            {\r\n                Id = 2,\r\n                FirstName = \"Steve\",\r\n                LastName = \"Smith\"\r\n            };\r\n            Author author3 = new Author\r\n            {\r\n                Id = 3,\r\n                FirstName = \"Anand\",\r\n                LastName = \"Narayanaswamy\"\r\n            };\r\n            modelBuilder.Entity&lt;Author&gt;().HasData(\r\n            author1, author2, author3);  \r\n            modelBuilder.Entity&lt;BlogPost&gt;().HasData(\r\n                new BlogPost\r\n                {\r\n                    Id = 1,\r\n                    Title = \"Introducing C# 10.0\",\r\n                    AuthorId = 1\r\n                },\r\n                new BlogPost\r\n                {\r\n                    Id = 2,\r\n                    Title = \"Introducing Entity Framework \r\n                    Core\",\r\n                    AuthorId = 2\r\n                },\r\n                new BlogPost\r\n                {\r\n                    Id = 3,\r\n                    Title = \"Introducing Kubernetes\",\r\n                    AuthorId = 1\r\n                },\r\n                new BlogPost\r\n                {\r\n                    Id = 4,\r\n                    Title = \"Introducing Machine Learning\",\r\n                    AuthorId = 2\r\n                },\r\n                new BlogPost\r\n                {\r\n                    Id = 5,\r\n                    Title = \"Introducing DevSecOps\",\r\n                    AuthorId = 3\r\n                }\r\n                );\r\n        }\r\n    }\r\n}<\/pre>\n<h3>Register a Data Context Factory<\/h3>\n<p>Now that the data context is ready, you should register it. However, you&#8217;ll register a <code>DbContextFactory<\/code> in lieu of registering a <code>DbContext<\/code> instance since it would allow for easy creation of <code>DbContext<\/code> instances in the application when needed.<\/p>\n<p>You might often want to perform multiple units-of-work within a single HTTP request. In such cases, you can use the <code>AddDbContextFactory<\/code> method to register a factory (in the <code>ConfigureServices<\/code> method of the <code>Startup<\/code> class) for creating <code>DbContext<\/code> instances. Then you can leverage constructor injection to access the factory in your application.<\/p>\n<p>The following code snippet illustrates how you can take advantage of the <code>AddDbContextFactory<\/code> method to register a <code>DbContextFactory<\/code> instance:<\/p>\n<pre class=\"lang:c# theme:vs2012\">services.AddDbContextFactory&lt;ApplicationDbContext&gt;(\r\noptions =&gt; options.UseInMemoryDatabase(\"BlogsManagement\"));<\/pre>\n<p>The above code informs Entity Framework Core to create an in-memory database named <em>BlogsManagement<\/em>.<\/p>\n<h3>Create the Repositories<\/h3>\n<p>Create an interface named <code>IAuthorRepository<\/code> in a file called <em>IAuthorRepository.cs<\/em> inside the <em>DataAccess<\/em> solution folder of your project with the following code in there. Make sure the interfaces are public.<\/p>\n<p><strong>IAuthorRepository.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">   public interface IAuthorRepository\r\n    {\r\n        public List&lt;Author&gt; GetAuthors();\r\n        public Author GetAuthorById(int id);\r\n        public Task&lt;Author&gt; CreateAuthor(Author author);\r\n    }<\/pre>\n<p>Create another interface named <code>IBlogPostRepository<\/code> in the same folder with the following code:<\/p>\n<p><strong>IBlogRepository.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">    public interface IBlogPostRepository\r\n    {\r\n        public List&lt;BlogPost&gt; GetBlogPosts();\r\n        public BlogPost GetBlogPostById(int id);\r\n    }<\/pre>\n<p>The <code>AuthorRepository<\/code> and <code>BlogPostRepository<\/code> classes will implement the interfaces <code>IAuthorRepository<\/code> and <code>IBlogPostRepository<\/code>, respectively.<\/p>\n<p>Create a file named <em>AuthorRepository.cs<\/em> in the <em>DataAccess<\/em> solution folder with the following code:<\/p>\n<p><strong>AuthorRepository.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess.Models;\r\nusing Microsoft.EntityFrameworkCore;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Threading.Tasks;\r\nnamespace BlogPostsManagementSystem.DataAccess\r\n{\r\n    public class AuthorRepository : IAuthorRepository\r\n    {\r\n        private readonly IDbContextFactory\r\n            &lt;ApplicationDbContext&gt; _dbContextFactory;\r\n        public AuthorRepository(IDbContextFactory\r\n            &lt;ApplicationDbContext&gt; dbContextFactory)\r\n        {\r\n            _dbContextFactory = dbContextFactory;\r\n            using (var _applicationDbContext = \r\n                _dbContextFactory.CreateDbContext())\r\n            {\r\n                _applicationDbContext.Database\r\n                .EnsureCreated();\r\n            }\r\n        }\r\n        public List&lt;Author&gt; GetAuthors()\r\n        {\r\n            using (var applicationDbContext = \r\n                _dbContextFactory.CreateDbContext())\r\n            {\r\n                return applicationDbContext.Authors.ToList();\r\n            }\r\n        }\r\n        public Author GetAuthorById(int id)\r\n        {\r\n            using (var applicationDbContext = \r\n                _dbContextFactory.CreateDbContext())\r\n            {\r\n                return applicationDbContext.Authors.\r\n                SingleOrDefault(x =&gt; x.Id == id);\r\n            }\r\n        }\r\n        public async Task&lt;Author&gt; CreateAuthor(Author author)\r\n        {\r\n            using (var applicationDbContext = \r\n                _dbContextFactory.CreateDbContext())\r\n            {\r\n                await applicationDbContext.Authors\r\n                .AddAsync(author);\r\n                await applicationDbContext.SaveChangesAsync();\r\n                return author;\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p>Inside the same solution folder, create a file named <em>BlogPostRepository.cs<\/em>. Replace the default generated code using the following code:<\/p>\n<p><strong>BlogPostRepository.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess.Models;\r\nusing Microsoft.EntityFrameworkCore;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nnamespace BlogPostsManagementSystem.DataAccess\r\n{\r\n    public class BlogPostRepository : IBlogPostRepository\r\n    {\r\n        private readonly IDbContextFactory\r\n            &lt;ApplicationDbContext&gt; _dbContextFactory;\r\n        public BlogPostRepository(IDbContextFactory\r\n            &lt;ApplicationDbContext&gt; dbContextFactory)\r\n        {\r\n            _dbContextFactory = dbContextFactory;\r\n            using (var applicationDbContext =\r\n                _dbContextFactory.CreateDbContext())\r\n            {\r\n                applicationDbContext.Database\r\n                .EnsureCreated();\r\n            }\r\n        }\r\n        public List&lt;BlogPost&gt; GetBlogPosts()\r\n        {\r\n            using (var applicationDbContext =\r\n                _dbContextFactory.CreateDbContext())\r\n            {\r\n                return applicationDbContext\r\n                .BlogPosts.ToList();\r\n            }\r\n        }\r\n        public BlogPost GetBlogPostById(int id)\r\n        {\r\n            using (var applicationDbContext =\r\n                _dbContextFactory.CreateDbContext())\r\n            {\r\n                return applicationDbContext.BlogPosts\r\n                    .SingleOrDefault(x =&gt; x.Id == id);\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<h3>Add Services to the Container<\/h3>\n<p>You should now add the following services in the <code>ConfigureServices<\/code> method of the <code>Startup<\/code> class so that you can take advantage of dependency injection to access instances of these types.<\/p>\n<pre class=\"lang:c# theme:vs2012\">services.AddScoped&lt;IAuthorRepository, AuthorRepository&gt;();\r\nservices.AddScoped&lt;IBlogPostRepository, BlogPostRepository&gt;();<\/pre>\n<h3>Build the GraphQL Schema<\/h3>\n<p>A GraphQL Schema comprises the following:<\/p>\n<ul>\n<li>Query<\/li>\n<li>Mutations<\/li>\n<li>Subscriptions<\/li>\n<\/ul>\n<p>Since GraphQL is not bound to any language or framework, it is not adept at understanding the CLR classes, i.e., C# POCO classes. In GraphQL, types are used to specify the fields of the domain classes you would like to expose. You&#8217;ll now create two classes, namely <code>AuthorType<\/code> in a file named <em>AuthorType.cs<\/em> and another class named <code>BlogPostType<\/code> in a file called <em>BlogPostType.cs<\/em>.<\/p>\n<p>To create a type in GraphQL, you should create a class that extends <code>ObjectGraphType&lt;T&gt;<\/code> and pass your entity type as an argument. You should also register the properties of the class as <em>Field<\/em> types so that GraphQL can recognize this type.<\/p>\n<p>Create your <em>GraphQL<\/em> folder, then create the following two classes in the files <em>AuthorType.cs<\/em> and <em>BlogPostType.cs<\/em> , respectively inside the folder.<\/p>\n<p><strong>AuthorType.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess.Models;\r\nusing HotChocolate.Types;\r\nnamespace BlogPostsManagementSystem.GraphQL\r\n{\r\n    public class AuthorType : ObjectType&lt;Author&gt;\r\n    {\r\n        protected override void Configure(IObjectTypeDescriptor&lt;Author&gt; descriptor)\r\n        {\r\n            descriptor.Field(a =&gt; a.Id).Type&lt;IdType&gt;();\r\n            descriptor.Field(a =&gt; \r\n            a.FirstName).Type&lt;StringType&gt;();\r\n            descriptor.Field(a =&gt; \r\n            a.LastName).Type&lt;StringType&gt;();\r\n            descriptor.Field&lt;BlogPostResolver&gt;(b =&gt; \r\n            b.GetBlogPosts(default, default));\r\n        }\r\n    }\r\n}<\/pre>\n<p><strong>BlogPostType.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess.Models;\r\nusing HotChocolate.Types;\r\nnamespace BlogPostsManagementSystem.GraphQL\r\n{\r\n    public class BlogPostType : ObjectType&lt;BlogPost&gt;\r\n    {\r\n        protected override void \r\n        Configure(IObjectTypeDescriptor&lt;BlogPost&gt; descriptor)\r\n        {\r\n            descriptor.Field(b =&gt; b.Id).Type&lt;IdType&gt;();\r\n            descriptor.Field(b =&gt; b.Title).Type&lt;StringType&gt;();\r\n            descriptor.Field(b =&gt; b.AuthorId).Type&lt;IntType&gt;();\r\n            descriptor.Field&lt;AuthorResolver&gt;(t =&gt; \r\n            t.GetAuthor(default, default));\r\n        }\r\n    }\r\n}<\/pre>\n<h3>Query<\/h3>\n<p>You also need a class that would fetch author and blog post-related data. To do this, create a file called <em>AuthorQuery.cs<\/em> with the following content inside.<\/p>\n<p><strong>Query.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess;\r\nusing BlogPostsManagementSystem.DataAccess.Models;\r\nusing HotChocolate;\r\nusing HotChocolate.Subscriptions;\r\nusing System.Collections.Generic;\r\nusing System.Threading.Tasks;\r\nnamespace BlogPostsManagementSystem.GraphQL\r\n{\r\n    public class Query\r\n    {\r\n        public async Task&lt;List&lt;Author&gt;&gt; \r\n        GetAllAuthors([Service] \r\n        IAuthorRepository authorRepository,\r\n        [Service] ITopicEventSender eventSender)\r\n        {\r\n            List&lt;Author&gt; authors = \r\n            authorRepository.GetAuthors();\r\n            await eventSender.SendAsync(\"ReturnedAuthors\", \r\n            authors);\r\n            return authors;\r\n        }\r\n        public async Task&lt;Author&gt; GetAuthorById([Service]\r\n        IAuthorRepository authorRepository,\r\n        [Service] ITopicEventSender eventSender, int id)\r\n        {\r\n            Author author = \r\n            authorRepository.GetAuthorById(id);\r\n            await eventSender.SendAsync(\"ReturnedAuthor\", \r\n            author);\r\n            return author;\r\n        }\r\n        public async Task&lt;List&lt;BlogPost&gt;&gt; \r\n        GetAllBlogPosts([Service] IBlogPostRepository \r\n        blogPostRepository,\r\n        [Service] ITopicEventSender eventSender)\r\n        {\r\n            List&lt;BlogPost&gt; blogPosts = \r\n            blogPostRepository.GetBlogPosts();\r\n            await eventSender.SendAsync(\"ReturnedBlogPosts\", \r\n            blogPosts);\r\n            return blogPosts;\r\n        }\r\n        public async Task&lt;BlogPost&gt; GetBlogPostById([Service] \r\n        IBlogPostRepository blogPostRepository,\r\n        [Service] ITopicEventSender eventSender, int id)\r\n        {\r\n            BlogPost blogPost = \r\n            blogPostRepository.GetBlogPostById(id);\r\n            await eventSender.SendAsync(\"ReturnedBlogPost\",\r\n            blogPost);\r\n            return blogPost;\r\n        }\r\n    }\r\n}<\/pre>\n<h3>Mutation<\/h3>\n<p>GraphQL uses mutation to allow the clients or consumers of an API to add, remove or modify data on the servers. You will need a query type to read data &#8211; this was discussed earlier.<\/p>\n<p>Create a class called <code>Mutation<\/code> in a file named <em>Mutation.cs<\/em> inside the GraphQL solution folder and add the following code:<\/p>\n<p><strong>Mutation.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess;\r\nusing BlogPostsManagementSystem.DataAccess.Models;\r\nusing HotChocolate;\r\nusing HotChocolate.Subscriptions;\r\nusing System.Threading.Tasks;\r\nnamespace BlogPostsManagementSystem.GraphQL\r\n{\r\n    public class Mutation\r\n    {\r\n        public async Task&lt;Author&gt; CreateAuthor([Service] \r\n        AuthorRepository authorRepository,\r\n        [Service] ITopicEventSender eventSender, int id,\r\n        string firstName,string lastName)\r\n        {\r\n            var data = new Author\r\n            {\r\n                Id = id,\r\n                FirstName = firstName,\r\n                LastName = lastName\r\n            };\r\n            var result = await \r\n            authorRepository.CreateAuthor(data);\r\n            await eventSender.SendAsync(\"AuthorCreated\", \r\n            result);\r\n            return result;\r\n        }\r\n    }\r\n}<\/pre>\n<h3>Subscription<\/h3>\n<p>You can take advantage of subscriptions in GraphQL to integrate real-time functionality in your GraphQL applications. Subscriptions enable servers to send data to subscribed clients to notify them when an event occurs. Subscriptions use <code>WebSockets<\/code> to allow clients to subscribe to notifications emails in real-time. The server executes the query again and then sends the updated results to the subscribed event.<\/p>\n<p>Now, create a class named <code>Subscription<\/code> in a file called <em>Subscription.cs<\/em> and replace the default code with the following:<\/p>\n<p><strong>Subscription.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess.Models;\r\nusing HotChocolate;\r\nusing HotChocolate.Execution;\r\nusing HotChocolate.Subscriptions;\r\nusing HotChocolate.Types;\r\nusing System.Collections.Generic;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\nnamespace BlogPostsManagementSystem.GraphQL\r\n{\r\n    public class Subscription\r\n    {\r\n        [SubscribeAndResolve]\r\n        public async ValueTask&lt;ISourceStream&lt;Author&gt;&gt; \r\n        OnAuthorCreated([Service] \r\n        ITopicEventReceiver eventReceiver,\r\n            CancellationToken cancellationToken)\r\n        {\r\n            return await eventReceiver.SubscribeAsync\r\n            &lt;string, Author&gt;(\"AuthorCreated\", \r\n            cancellationToken);\r\n        }\r\n        [SubscribeAndResolve]\r\n        public async ValueTask&lt;ISourceStream\r\n        &lt;List&lt;Author&gt;&gt;&gt; OnAuthorsGet([Service] \r\n        ITopicEventReceiver eventReceiver,\r\n           CancellationToken cancellationToken)\r\n        {\r\n            return await eventReceiver.SubscribeAsync&lt;string, \r\n            List&lt;Author&gt;&gt;(\"ReturnedAuthors\", \r\n            cancellationToken);\r\n        }\r\n        [SubscribeAndResolve]\r\n        public async ValueTask&lt;ISourceStream&lt;Author&gt;&gt; \r\n        OnAuthorGet([Service] ITopicEventReceiver \r\n        eventReceiver, CancellationToken cancellationToken)\r\n        {\r\n            return await eventReceiver.SubscribeAsync&lt;string, \r\n            Author&gt;(\"ReturnedAuthor\", cancellationToken);\r\n        }\r\n        [SubscribeAndResolve]\r\n        public async ValueTask&lt;ISourceStream&lt;BlogPost&gt;&gt; \r\n        OnBlogPostsGet([Service] ITopicEventReceiver \r\n        eventReceiver, CancellationToken cancellationToken)\r\n        {\r\n            return await eventReceiver.SubscribeAsync&lt;string, \r\n            BlogPost&gt;(\"ReturnedBlogPosts\", cancellationToken);\r\n        }\r\n        [SubscribeAndResolve]\r\n        public async ValueTask&lt;ISourceStream&lt;BlogPost&gt;&gt; \r\n        OnBlogPostGet([Service] ITopicEventReceiver \r\n        eventReceiver, CancellationToken cancellationToken)\r\n        {\r\n            return await eventReceiver.SubscribeAsync&lt;string, \r\n            BlogPost&gt;(\"ReturnedBlogPost\", cancellationToken);\r\n        }\r\n    }\r\n}<\/pre>\n<h3>Create the Resolvers<\/h3>\n<p>A resolver is a function responsible for populating data for one field of your schema. In other words, it is a function that resolves the value of a type of field within a schema. Resolvers can return objects and scalars such as Strings, Numbers, or Booleans. You can define how it populates the data, including fetching data from a third-party API or back-end database.<\/p>\n<p>Create a class called <code>AuthorResolver<\/code> in a file named <em>AuthorResolver.cs<\/em> inside the <em>GraphQL<\/em> solution folder with the following code:<\/p>\n<p><strong>AuthorResolver.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess;\r\nusing BlogPostsManagementSystem.DataAccess.Models;\r\nusing HotChocolate;\r\nusing HotChocolate.Resolvers;\r\nusing System.Linq;\r\nnamespace BlogPostsManagementSystem.GraphQL\r\n{\r\n    public class AuthorResolver\r\n    {\r\n        private readonly IAuthorRepository _authorRepository;\r\n        public AuthorResolver([Service] IAuthorRepository \r\n        authorService)\r\n        {\r\n            _authorRepository = authorService;\r\n        }\r\n        public Author GetAuthor(BlogPost blog, \r\n        IResolverContext ctx)\r\n        {\r\n            return _authorRepository.GetAuthors().Where\r\n            (a =&gt; a.Id == blog.AuthorId).FirstOrDefault();\r\n        }\r\n    }\r\n}<\/pre>\n<p>Create another class named <code>BlogPostResolver<\/code> in a file called <em>BlogPostResolver.cs<\/em> with the following code:<\/p>\n<p><strong>BlogPostResolver.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess;\r\nusing BlogPostsManagementSystem.DataAccess.Models;\r\nusing HotChocolate;\r\nusing HotChocolate.Resolvers;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nnamespace BlogPostsManagementSystem.GraphQL\r\n{\r\n    public class BlogPostResolver\r\n    {\r\n        private readonly IBlogPostRepository \r\n        _blogPostRepository;\r\n        public BlogPostResolver([Service] \r\n        IBlogPostRepository blogPostRepository)\r\n        {\r\n            _blogPostRepository = blogPostRepository;\r\n        }\r\n        public IEnumerable&lt;BlogPost&gt; GetBlogPosts(\r\n        Author author, IResolverContext ctx)\r\n        {\r\n            return _blogPostRepository.GetBlogPosts()\r\n            .Where(b =&gt; b.AuthorId == author.Id);\r\n        }\r\n    }\r\n}<\/pre>\n<h3>Configuring the GraphQL Middleware<\/h3>\n<p>Write the following code in the <code>ConfigureServices<\/code> method of the <code>Startup<\/code> class to add <code>GraphQLServer<\/code> to the container:<\/p>\n<pre class=\"lang:c# theme:vs2012\">services.AddGraphQLServer();<\/pre>\n<p>A GraphQL server can expose data via GraphQL API endpoints so that the same data can be consumed by the clients (mobile clients, web clients, etc.) or the consumers of the API.<\/p>\n<p>Next, write the following code in the <code>Configure<\/code> method of the <code>Startup<\/code> class to configure the <code>GraphQL<\/code> endpoint:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n        {\r\n            if (env.IsDevelopment())\r\n            {\r\n                app.UseDeveloperExceptionPage();\r\n                app.UsePlayground(new PlaygroundOptions\r\n                {\r\n                    QueryPath = \"\/graphql\",\r\n                    Path = \"\/playground\"\r\n                });\r\n            }\r\n            app.UseWebSockets();\r\n            app\r\n                .UseRouting()\r\n                .UseEndpoints(endpoints =&gt;\r\n                {\r\n                    endpoints.MapGraphQL();\r\n                });\r\n        }\r\n    }<\/pre>\n<p>At this moment, your <code>ConfigureServices<\/code> method should look like this:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddDbContextFactory&lt;ApplicationDbContext&gt;(\r\n            options =&gt; options.UseInMemoryDatabase(\"BlogsManagement\"));\r\n            services.AddInMemorySubscriptions();\r\n            services.AddScoped&lt;IAuthorRepository, \r\n                AuthorRepository&gt;();\r\n            services.AddScoped&lt;IBlogPostRepository, \r\n                BlogPostRepository&gt;();\r\n            services\r\n            .AddGraphQLServer()\r\n            .AddType&lt;AuthorType&gt;()\r\n            .AddType&lt;BlogPostType&gt;()\r\n            .AddQueryType&lt;Query&gt;()\r\n            .AddMutationType&lt;Mutation&gt;()\r\n            .AddSubscriptionType&lt;Subscription&gt;();\r\n        }<\/pre>\n<p>You should include the following namespaces in the <em>Startup.cs<\/em> file:<\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess;\r\nusing BlogPostsManagementSystem.GraphQL;\r\nusing HotChocolate.AspNetCore;\r\nusing HotChocolate.AspNetCore.Playground;\r\nusing Microsoft.AspNetCore.Builder;\r\nusing Microsoft.AspNetCore.Hosting;\r\nusing Microsoft.EntityFrameworkCore;\r\nusing Microsoft.Extensions.DependencyInjection;\r\nusing Microsoft.Extensions.Hosting;<\/pre>\n<p>Here\u2019s the complete source code of the <code>Startup<\/code> class for your reference:<\/p>\n<p><strong>Startup.cs<\/strong><\/p>\n<pre class=\"lang:c# theme:vs2012\">using BlogPostsManagementSystem.DataAccess;\r\nusing BlogPostsManagementSystem.GraphQL;\r\nusing HotChocolate.AspNetCore;\r\nusing HotChocolate.AspNetCore.Playground;\r\nusing Microsoft.AspNetCore.Builder;\r\nusing Microsoft.AspNetCore.Hosting;\r\nusing Microsoft.EntityFrameworkCore;\r\nusing Microsoft.Extensions.DependencyInjection;\r\nusing Microsoft.Extensions.Hosting;\r\nnamespace BlogPostsManagementSystem\r\n{\r\n    public class Startup\r\n    {\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddDbContextFactory&lt;ApplicationDbContext&gt;(\r\n            options =&gt; options.UseInMemoryDatabase(\"BlogsManagement\"));\r\n            services.AddInMemorySubscriptions();\r\n            services.AddScoped&lt;IAuthorRepository, \r\n                AuthorRepository&gt;();\r\n            services.AddScoped&lt;IBlogPostRepository, \r\n                BlogPostRepository&gt;();\r\n            services\r\n            .AddGraphQLServer()\r\n            .AddType&lt;AuthorType&gt;()\r\n            .AddType&lt;BlogPostType&gt;()\r\n            .AddQueryType&lt;Query&gt;()\r\n            .AddMutationType&lt;Mutation&gt;()\r\n            .AddSubscriptionType&lt;Subscription&gt;();\r\n        }\r\n        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n        {\r\n            if (env.IsDevelopment())\r\n            {\r\n                app.UseDeveloperExceptionPage();\r\n                app.UsePlayground(new PlaygroundOptions\r\n                {\r\n                    QueryPath = \"\/graphql\",\r\n                    Path = \"\/playground\"\r\n                });\r\n            }\r\n            app.UseWebSockets();\r\n            app\r\n                .UseRouting()\r\n                .UseEndpoints(endpoints =&gt;\r\n                {\r\n                    endpoints.MapGraphQL();\r\n                });\r\n        }\r\n    }\r\n}<\/pre>\n<h2>GraphQL in Action!<\/h2>\n<p>Now it\u2019s time to execute GraphQL queries using HotChocolate. Run the application, remembering to have <code>\/playground<\/code> in the URL.<\/p>\n<h3>Query<\/h3>\n<p>Here\u2019s an example of a GraphQL query you can use to get the data about all authors.<\/p>\n<pre class=\"lang:c# theme:vs2012\">query {\r\n  allAuthors{\r\n    id\r\n    firstName\r\n    lastName\r\n  }\r\n}<\/pre>\n<p>When you execute this query, here\u2019s how the output would look like:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92683\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-7.png\" alt=\"Image showing the query output\" width=\"1376\" height=\"633\" \/><\/p>\n<p><strong>Figure 5: Query output<\/strong><\/p>\n<p>If you would like to get the data about a particular author together with the blogs they have written, you can take advantage of the following query instead.<\/p>\n<pre class=\"lang:c# theme:vs2012\">query {\r\n  authorById (id: 1){\r\n    id\r\n    firstName\r\n    lastName\r\n    blogPosts\r\n    {\r\n      id\r\n      title\r\n    }\r\n  }\r\n}<\/pre>\n<p>Run the above query. Figure 6 below shows the output in the Playground tool.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92684\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-8.png\" alt=\"Image showing output of playground tool\" width=\"1379\" height=\"674\" \/><\/p>\n<p><strong>Figure 6: Output in Playground tool<\/strong><\/p>\n<h3>Mutation<\/h3>\n<p>Now write the following query to test mutation:<\/p>\n<pre class=\"lang:c# theme:vs2012\">mutation{\r\n  createAuthor(id: 4, firstName: \"Scott\", lastName: \"Miller\"){\r\n    id\r\n    firstName\r\n    lastName\r\n  }\r\n}<\/pre>\n<p>When you run it, you\u2019ll observe that the <code>CreateAuthor<\/code> method of your <code>Mutation<\/code> class is called. Note that the breakpoint is hit successfully.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92685\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-9.png\" alt=\"Image showing the CreateAuthor method\" width=\"1431\" height=\"600\" \/><\/p>\n<p><strong>Figure 7: CreateAuthor method<\/strong><\/p>\n<h3>Subscription<\/h3>\n<p>To test Subscription, execute the application, browse to the \/playground endpoint, and write the query shown below:<\/p>\n<pre class=\"lang:c# theme:vs2012\">subscription{\r\n  onAuthorsGet\r\n  {\r\n    id\r\n    firstName\r\n    lastName\r\n  }\r\n}<\/pre>\n<p>When you click the <em>Execute<\/em> button, the application subscribes to the <code>OnAuthorGet<\/code> event.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92686\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-10.png\" alt=\"Image showing execute\" width=\"1379\" height=\"741\" \/><\/p>\n<p><strong>Figure 8: Click Execute button<\/strong><\/p>\n<p>Next, launch the same URL in another browser window and write and execute the query shown in Figure 9.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92687\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-11.png\" alt=\"Image showing Launch and execute the query\" width=\"1377\" height=\"705\" \/><\/p>\n<p><strong>Figure 9: Launch and execute the query<\/strong><\/p>\n<p>This query will trigger the <code>OnAuthorsGet<\/code> event as shown in Figure 10.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-92688\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/10\/word-image-12.png\" alt=\"Image showing OnAuthors event\" width=\"1379\" height=\"736\" \/><\/p>\n<p><strong>Figure 10<\/strong>: <strong>The OnAuthorsGet event<\/strong><\/p>\n<h2>Summary<\/h2>\n<p>GraphQL is an open-source API standard developed by Facebook that provides a powerful, flexible, and versatile alternative to REST. GraphQL supports declarative data fetching, which allows the user to specify precisely the data it needs. HotChocolate, an implementation of GraphQL, can be used to create GraphQL servers in ASP.NET Core.<\/p>\n<p><em>If you liked this article, you might also like\u00a0<a href=\"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/building-and-consuming-graphql-api-in-asp-net-core-3-1\/\">Building and consuming GraphQL API in ASP.NET Core 3.1 &#8211; Simple Talk (red-gate.com)<\/a>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>GraphQL is a platform-independent, language-neutral query language and may be used to run queries and retrieve data. Joydip Kanjilal explains how to use GaphQI in an ASP.NET Core 5 app.&hellip;<\/p>\n","protected":false},"author":221905,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,53],"tags":[5134],"coauthors":[50381],"class_list":["post-92678","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-featured","tag-sql-prompt"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/92678","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221905"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=92678"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/92678\/revisions"}],"predecessor-version":[{"id":92691,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/92678\/revisions\/92691"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=92678"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=92678"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=92678"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=92678"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}