{"id":506779,"date":"2024-09-17T15:16:24","date_gmt":"2024-09-17T14:16:24","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=dotnet&#038;p=506779"},"modified":"2024-10-15T19:24:51","modified_gmt":"2024-10-15T18:24:51","slug":"building-a-graphql-client-in-net-with-jetbrains-rider-and-strawberryshake","status":"publish","type":"dotnet","link":"https:\/\/blog.jetbrains.com\/en\/dotnet\/2024\/09\/17\/building-a-graphql-client-in-net-with-jetbrains-rider-and-strawberryshake","title":{"rendered":"Building a GraphQL Client in .NET with JetBrains Rider and StrawberryShake"},"content":{"rendered":"\n<p>Many teams are using GraphQL for their API needs, thanks to its powerful query language and flexibility. Unlike traditional REST APIs, GraphQL lets you fetch the data you need in a single request, making your applications more efficient and responsive.<\/p>\n\n\n\n<p>However, it can be daunting getting started creating schemas, writing queries, and integrating GraphQL into your .NET application. Using JetBrains Rider\u2019s GraphQL plugin and the <a href=\"https:\/\/chillicream.com\/docs\/strawberryshake\/v13\" target=\"_blank\" rel=\"noopener\">StrawberryShake<\/a> framework, building an application that consumes a GraphQL API is not that hard.&nbsp;<\/p>\n\n\n\n<p>In this blog post, we\u2019ll discuss setting up your environment, defining schemas, generating client code, and seamlessly integrating it all into a sample project. Here we go!<\/p>\n\n\n    <div class=\"buttons\">\n        <div class=\"buttons__row\">\n                                                <a href=\"https:\/\/www.jetbrains.com\/rider\/\" class=\"btn\" target=\"\" rel=\"noopener\">Download JetBrains Rider<\/a>\n                                                    <\/div>\n    <\/div>\n\n\n\n\n\n\n\n<h2 class=\"wp-block-heading\">What is GraphQL?<\/h2>\n\n\n\n<p>Before we dig into building a sample application, let\u2019s quickly recap GraphQL and its benefits. <a href=\"https:\/\/graphql.org\/\" target=\"_blank\" rel=\"noopener\">GraphQL<\/a>, developed by Facebook in 2012 and open-sourced in 2015, is a query language for APIs and a runtime for executing queries based on a user-defined type system.<\/p>\n\n\n\n<p>If you have been a .NET developer for a while, you may have already worked with <a href=\"https:\/\/www.odata.org\/\" target=\"_blank\" rel=\"noopener\">OData<\/a>. Conceptually, GraphQL is similar in that it lets you request exactly the data you need from an API, eliminating the typical over-fetching or under-fetching issues you may see in REST APIs. For example, in a typical REST API, you may want to retrieve customer data and either need to make a second request to get their address details or always get the address details in the response, even when they\u2019re not always required..<\/p>\n\n\n\n<p>Unlike most REST APIs, a GraphQL API exposes a single endpoint you can query for any data you need. The endpoint can define several operations, all of which are self-documenting through a schema. A schema provides a comprehensive and queryable description of the API structure, types, and available operations. The schema also defines types and relationships between them, ensuring clients know exactly what data is available and receive helpful error messages when things go wrong.<\/p>\n\n\n\n<p>There are a few concepts to keep in mind throughout this post:<\/p>\n\n\n\n<ul>\n<li><strong>Queries <\/strong>\u2013 These are used to fetch data from the server, similar to GET requests in REST, but much more powerful thanks to their flexibility in fetching nested and related data in a single request.<\/li>\n\n\n\n<li><strong>Subscriptions<\/strong> \u2013 These are used to subscribe to data from the server, and return new data or updates from the server when new data is available.<\/li>\n\n\n\n<li><strong>Mutations<\/strong> \u2013 Used to modify data on the server (e.g., creating, updating, deleting records), similar to <code>POST<\/code>, <code>PUT<\/code>, or <code>DELETE<\/code> in <code>REST<\/code>.<\/li>\n\n\n\n<li><strong>Schema <\/strong>\u2013 defines the types and relationships in your API, specifying what queries and mutations are available. It ensures both the client and the server agree on the data structure and types.<\/li>\n<\/ul>\n\n\n\n<p>One more thing to cover: when implementing a GraphQL API, you have two transport protocols to consider for data exchange: HTTP and WebSockets. HTTP is typically used for traditional query and mutation operations, where clients send HTTP <code>GET<\/code> and <code>POST<\/code> requests to the GraphQL server and receive responses containing the requested data. This method is straightforward and works well for most cases where data changes are infrequent or do not need to be immediately reflected on the client.<\/p>\n\n\n\n<p>On the other hand, WebSockets are used for real-time applications requiring instant updates, such as live chat, online gaming, or real-time dashboards. GraphQL subscriptions use WebSockets to maintain a persistent connection between the client and the server, enabling the server to push updates to the client as soon as data changes occur. This reduces latency and provides a more responsive user experience compared to polling mechanisms often used with HTTP.<\/p>\n\n\n\n<p>Choosing between HTTP and WebSockets depends on your application&#8217;s specific requirements. For most standard operations, HTTP is sufficient and simpler to implement. However, for real-time data updates, integrating WebSockets with GraphQL subscriptions can significantly enhance your application\u2019s interactivity and responsiveness. Also, both transports can be used in conjunction when building solutions. In this post, we\u2019ll use an HTTP endpoint as our example to work with.<\/p>\n\n\n                    <div class=\"alert \">\n            <p><strong>Note:<\/strong> If you want to learn more about how REST, GraphQL, and gRPC compare, check out this <a href=\"https:\/\/www.youtube.com\/watch?v=y7_gJXrVzLk\" target=\"_blank\" rel=\"noopener\">talk from JetBrains .NET Days Online by Poornima Nayar<\/a>.<\/p>\n        <\/div>\n    \n\n\n\n\n\n\n<h2 class=\"wp-block-heading\">What is StrawberryShake?<\/h2>\n\n\n\n<p>Now, let\u2019s talk about <a href=\"https:\/\/chillicream.com\/docs\/strawberryshake\/v13\" target=\"_blank\" rel=\"noopener\">StrawberryShake<\/a>. This open-source .NET library simplifies building GraphQL clients by generating strongly-typed client-side code from your GraphQL schema and queries. This means less boilerplate and more focus on what matters \u2013 your application logic.<\/p>\n\n\n\n<p>It uses source generators to generate all the client-side code based on the GraphQL schema you define or introspect from a GraphQL API.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Let\u2019s transition into a practical example. First, let\u2019s make sure you have the <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/8097-graphql\" target=\"_blank\" rel=\"noopener\">GraphQL plugin installed in JetBrains Rider<\/a>. This plugin is necessary for providing syntax highlighting, validation, and auto-completion for GraphQL schemas and queries, streamlining your development process.<\/p>\n\n\n\n<p>Open JetBrains Rider and bring up the <strong>Settings\/Preferences<\/strong> menu. Go to <strong>Plugins<\/strong> in the left-hand sidebar, and search for &#8220;GraphQL&#8221; in the <strong>Marketplace<\/strong> tab. Click <strong>Install<\/strong> to add the plugin to your Rider setup. You may need to restart Rider to activate the plugin.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"1176\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/08\/image-67.png\" alt=\"\" class=\"wp-image-506780\"\/><\/figure>\n\n\n\n<p>We\u2019re ready to jump into creating our project and setting everything up in JetBrains Rider. Let&#8217;s get to work!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the project in Rider<\/h2>\n\n\n\n<p>Let\u2019s look at what we\u2019ll build first. Since we\u2019re focusing on building a GraphQL <em>client<\/em>, we\u2019ll need an API to interact with. We\u2019re in luck, because there are <a href=\"https:\/\/github.com\/graphql-kit\/graphql-apis\" target=\"_blank\" rel=\"noopener\">plenty of GraphQL APIs available<\/a>. In this blog post, we\u2019ll use <a href=\"https:\/\/github.com\/trevorblades\/countries\" target=\"_blank\" rel=\"noopener\">Trevor Blades\u2019 Countries GraphQL API<\/a>, which provides data about countries around the world. The sample application will be a page that shows information about the countries included in that API, and a way to get more details for each.<\/p>\n\n\n\n<p>The countries API endpoint is available at <a href=\"https:\/\/countries.trevorblades.com\/\" target=\"_blank\" rel=\"noopener\">https:\/\/countries.trevorblades.com\/<\/a>, which exposes a playground where you can test your queries against it.<\/p>\n\n\n                    <div class=\"alert \">\n            <p><strong>Note:<\/strong> Michael Staib, founder of ChilliCream (the company that also builds the StrawberryShake project we use in this blog post) was a guest in one of our livestreams to talk about <a href=\"https:\/\/www.youtube.com\/watch?v=Yy9wOhiWBJg\" target=\"_blank\" rel=\"noopener\">building a GraphQL server with ASP.NET Core and HotChocolate<\/a>.<\/p>\n        <\/div>\n    \n\n\n\n\n\n\n<p>In JetBrains Rider, create a new Web App project using the Razor Pages template. Give it a name, such as the very original \u201cCountries\u201d I used here:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"1209\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/08\/image-68.png\" alt=\"\" class=\"wp-image-506791\"\/><\/figure>\n\n\n\n<p>While not required, for this sample, I removed some of the default CSS in the project and included <a href=\"https:\/\/picocss.com\/\" target=\"_blank\" rel=\"noopener\">PicoCSS<\/a> \u2013 a great small CSS framework that makes any web page look nice. Here\u2019s my updated <code>_Layout.cshtml<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;!doctype html>\n&lt;html lang=\"en\">\n&lt;head>\n   &lt;meta charset=\"utf-8\">\n   &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n   &lt;meta name=\"color-scheme\" content=\"light dark\">\n   &lt;link rel=\"stylesheet\" href=\"https:\/\/cdn.jsdelivr.net\/npm\/@@picocss\/pico@2\/css\/pico.min.css\" \/>\n   &lt;link rel=\"stylesheet\" href=\"~\/css\/site.css\" asp-append-version=\"true\" \/>\n   &lt;title>@ViewData[\"Title\"] - Countries&lt;\/title>\n&lt;\/head>\n&lt;body>\n&lt;main class=\"container\">\n   &lt;header>\n       &lt;nav>\n           &lt;ul>\n               &lt;li>&lt;strong>Countries&lt;\/strong>&lt;\/li>\n           &lt;\/ul>\n           &lt;ul>\n               &lt;li>&lt;a href=\"\/\">Index&lt;\/a>&lt;\/li>\n           &lt;\/ul>\n       &lt;\/nav>\n   &lt;\/header>\n   @RenderBody()\n&lt;\/main>\n\n\n&lt;script src=\"~\/js\/site.js\" asp-append-version=\"true\">&lt;\/script>\n\n\n@await RenderSectionAsync(\"Scripts\", required: false)\n&lt;script type=\"module\" defer>\n import { polyfillCountryFlagEmojis } from \"https:\/\/cdn.skypack.dev\/country-flag-emoji-polyfill\";\n polyfillCountryFlagEmojis();\n&lt;\/script>\n&lt;\/body>\n&lt;\/html><\/pre>\n\n\n\n<p>You can also <a href=\"https:\/\/github.com\/maartenba\/GraphQLCountries\" target=\"_blank\" rel=\"noopener\">clone a copy of this project from GitHub<\/a>, and explore individual commits if you want to follow along.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Working with GraphQL in Rider<\/h2>\n\n\n\n<p>Time for GraphQL! In your C# project, use the context menu to add a new <strong>GraphQL Config<\/strong> file and paste the following contents into it:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">schema: schema.graphql\nextensions:\n endpoints:\n   production:\n     url: https:\/\/countries.trevorblades.com\/graphql\/\n     headers:\n       Authorization: Bearer ${TOKEN}\ndocuments: '**\/*.graphql'<\/pre>\n\n\n\n<p>This <code>graphql.config.yml<\/code> file will be used by Rider to access the schema for the countries API, and generate queries that can be executed inside the IDE. This configuration file also defines one or more endpoints, and potential headers required to access an endpoint, such as authorization headers. The countries API doesn\u2019t require authentication, but we\u2019ll see in a second why I added it here anyways.<\/p>\n\n\n\n<p>In the left-hand gutter, right next to the production endpoint, you\u2019ll see a <strong>Run<\/strong> icon:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1212\" height=\"502\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/08\/image-69.png\" alt=\"\" class=\"wp-image-506802\"\/><\/figure>\n\n\n\n<p>Click it to run an introspection of the remote schema. When you do, you\u2019ll see a popup that lets you enter an authorization token. You can skip it, but this is why I added the <code>${TOKEN}<\/code> placeholder earlier: to show you how to add variables into the GraphQL configuration.<\/p>\n\n\n\n<p>When finished, a <code>schema.graphql<\/code> file is automatically added to your project, listing all the types, fields, and operations exposed by the countries API. Note the toolbar at the top of the editor: you can switch to a different endpoint if you have e.g. a staging and production GraphQL API to work with, and there\u2019s a <strong>Refresh<\/strong> button to re-run schema introspection and update the types, fields, and operations in the API.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"933\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/08\/image-70.png\" alt=\"\" class=\"wp-image-506813\"\/><\/figure>\n\n\n\n<p>The toolbar also contains a <strong>Run<\/strong> button, which is not very useful yet. Let\u2019s change that! In our application, I\u2019d like to show a list of all countries with their country code, name, and flag image. Add a new file called <code>listcountries.graphql<\/code>, and paste the following query into it:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">query ListCountries {\n   countries {\n       code\n       name\n       emoji\n   }\n}<\/pre>\n\n\n\n<p>This snippet defines a GraphQL query (named \u201cListCountries\u201d) that retrieves information from a collection on the API endpoint called \u201ccountries\u201d. This query returns an array of Country elements, and each contains the code, name, and emoji. Note that you can <kbd>Cmd+Click<\/kbd> or <kbd>Ctrl+Click<\/kbd> on the name to navigate to the schema\u2019s definition of available data and collections.<\/p>\n\n\n\n<p>Now is a good time to try the <strong>Run<\/strong> button in the editor. You\u2019ll see Rider opens a tool window showing the query result:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"1276\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/08\/image-71.png\" alt=\"\" class=\"wp-image-506824\"\/><\/figure>\n\n\n\n<p>While we\u2019re creating queries in Rider, let\u2019s add one more file: <code>getcountry.graphql<\/code>, and paste the following contents into it:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">uery GetCountry($countryCode: ID!) {\n   country(code: $countryCode) {\n       code\n       name\n       emoji\n       capital\n       currency\n       languages {\n           code\n           name\n       }\n       ...Continent\n   }\n}\n\n\nfragment Continent on Country {\n   continent {\n       code\n       name\n   }\n}<\/pre>\n\n\n\n<p>This query will be used in our sample application to display details for a specific country. The query is named <code>GetCountry<\/code>, and requires a parameter <code>$countryCode<\/code>. It then requests data from the GraphQL API, requesting a country (by <code>$countryCode<\/code>) and returning various fields of information from it.<\/p>\n\n\n\n<p>Another interesting bit in this query is that we\u2019re not only fetching the country data but also its related continent. If you do not need that data, you can keep it out of the query and get a smaller response payload size. You will also see the fields queried for a continent are defined as a <code>fragment<\/code>. This is a way to make your GraphQL queries a bit more maintainable, as including the <code>Continent<\/code> on any query that works with <code>Country<\/code> now only means adding <code>...Continent<\/code> and not the complete list of fields. This is not a requirement, and you can also write the entire query like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">query GetCountry($countryCode: ID!) {\n   country(code: $countryCode) {\n       code\n       name\n       emoji\n       capital\n       currency\n       languages {\n           code\n           name\n       }\n       continent {\n           code\n           name\n       }\n   }\n}<\/pre>\n\n\n\n<p>With those two queries defined, let\u2019s continue building our ASP.NET Core application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Adding StrawberryShake GraphQL source generation<\/h2>\n\n\n\n<p>To start generating the C# client for the countries GraphQL schema we just queried, you will need to add a NuGet package reference to <code><a href=\"https:\/\/www.nuget.org\/packages\/StrawberryShake.Server\/\" target=\"_blank\" rel=\"noopener\">StrawberryShake.Server<\/a><\/code>. While named \u201cserver\u201d, this package includes additional dependencies. to get you started with creating a GraphQL client.<\/p>\n\n\n\n<p>StrawberryShake also <a href=\"https:\/\/chillicream.com\/docs\/strawberryshake\/v13\/get-started\/console\" target=\"_blank\" rel=\"noopener\">has a command line tool that can help set up code generation<\/a>, but we&#8217;re not going to use that in this blog post.<\/p>\n\n\n\n<p>Next, add a file named <code>.graphqlrc.json<\/code> next to your <code>graphql.config.yml<\/code>. Paste the following contents into it:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n \"schema\": \"schema.graphql\",\n \"documents\": \"**\/*.graphql\",\n \"extensions\": {\n   \"strawberryShake\": {\n     \"name\": \"CountriesClient\",\n     \"namespace\": \"Countries.GraphQL\",\n     \"url\": \"https:\/\/countries.trevorblades.com\/graphql\/\",\n     \"dependencyInjection\": true,\n     \"strictSchemaValidation\": true,\n     \"emitGeneratedCode\": true,\n     \"records\": {\n       \"inputs\": false,\n       \"entities\": false\n     },\n     \"transportProfiles\": [\n       {\n         \"default\": \"Http\",\n         \"subscription\": \"WebSocket\"\n       }\n     ]\n   }\n }\n}<\/pre>\n\n\n\n<p>This file looks similar to the <code>graphql.config.yml<\/code> file created earlier, but this time, it configures how StrawberryShake should generate C# code from the GraphQL API. It includes the API endpoint URL, the name of the generated client class (<code>CountriesClient<\/code>), its namespace, and whether to generate convenience extension methods to register the GraphQL client with ASP.NET Core\u2019s service collection.<\/p>\n\n\n\n<p>If you now build your solution, you should see a new type <code>ICountriesClient<\/code> you can work with, as well as an <code>AddCountriesClient()<\/code> extension method on <code>IServiceCollection<\/code>.&nbsp;<\/p>\n\n\n\n<p>In <code>Program.cs<\/code>, you can use this extension method to wire up the generated GraphQL client:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ ...\n\nvar builder = WebApplication.CreateBuilder(args);\n\n\/\/ Add services to the container.\nbuilder.Services.AddRazorPages();\nbuilder.Services.AddHttpClient();\nbuilder.Services\n   .AddCountriesClient()\n   .ConfigureHttpClient(\n       configureClient: client =>\n       {\n           client.BaseAddress = new Uri(\"https:\/\/countries.trevorblades.com\/graphql\/\");\n           \/\/ client.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue.Parse($\"Bearer {Constants.ApiKey}\");\n       });\n\nvar app = builder.Build();\n\n\/\/ ...<\/pre>\n\n\n\n<p>The call to <code>AddCountriesClient()<\/code> will register all necessary services with ASP.NET Core. You will also need a call to <code>ConfigureApiClient()<\/code> to configure the GraphQL API endpoint URL. I left a comment in the code here showing how you would add bearer token authorization headers for authentication.<\/p>\n\n\n\n<p>We\u2019re ready to consume the GraphQL queries we defined earlier! In <code>Index.cshtml.cs<\/code>, add a constructor parameter that accepts an <code>ICountriesClient<\/code> and assign it to a field, or use a primary constructor.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class IndexModel(ICountriesClient countriesClient) : PageModel\n{\n   \/\/ ...\n}<\/pre>\n\n\n\n<p>In the <code>OnGet<\/code> method, you can query the GraphQL endpoint and retrieve a list of countries. Here\u2019s the full code for the <code>IndexModel<\/code> class that is used to render the page:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class IndexModel(ICountriesClient countriesClient) : PageModel\n{\n   public IReadOnlyCollection&lt;IListCountries_Countries> Countries { get; set; }\n\n   public async Task OnGet()\n   {\n       var countries = await countriesClient.ListCountries.ExecuteAsync();\n       if (countries.IsErrorResult())\n       {\n           \/\/ ...\n       }\n\n       Countries = countries.Data?.Countries ?? new List&lt;IListCountries_Countries>(0);\n   }\n}<\/pre>\n\n\n\n<p>You\u2019ll notice the <code>countriesClient<\/code> has a <code>ListCountries<\/code> property on which you can call <code>ExecuteAsync()<\/code> to fetch data. StrawberryShake generates this method, and the method may accept parameters as well. If you try calling the <code>GetCountry<\/code> method (which is generated based on the <code>GetCountry<\/code> query we defined in the previous section of this post), you\u2019ll see the <code>countryCode<\/code> parameter can be passed in:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"196\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/08\/image-72.png\" alt=\"\" class=\"wp-image-506838\"\/><\/figure>\n\n\n\n<p>The <code>ExecuteAsync()<\/code> method always returns an object that contains information about the response. If an error is returned, you can check for it and log or otherwise handle the exception. If the response is successful, the <code>Data<\/code> property will contain an object representing the object defined in the <code>*.graphql<\/code> file earlier. In this example application, you can pass the data on to the Razor view.<\/p>\n\n\n\n<p>In the <code>Index.cshtml<\/code> view, you can now consume the list of countries, and display each in a table:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@page\n@model IndexModel\n@{\n   ViewData[\"Title\"] = \"Countries\";\n}\n\n\n&lt;h1>Countries&lt;\/h1>\n&lt;table>\n   &lt;thead>\n   &lt;tr>\n       &lt;th scope=\"col\">Country code&lt;\/th>\n       &lt;th scope=\"col\">Name&lt;\/th>\n       &lt;th scope=\"col\">Emoji&lt;\/th>\n   &lt;\/tr>\n   &lt;\/thead>\n   &lt;tbody>\n   @foreach (var country in Model.Countries)\n   {\n       &lt;tr>\n           &lt;td>@country.Code&lt;\/td>\n           &lt;td>&lt;a asp-page=\"Country\" asp-route-countryCode=\"@country.Code\">@country.Name&lt;\/a>&lt;\/td>\n           &lt;td>@country.Emoji&lt;\/td>\n       &lt;\/tr>\n   }\n   &lt;\/tbody>\n&lt;\/table><\/pre>\n\n\n\n<p>Try running it in your browser, and you should see a similar page to this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"630\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/08\/image-73.png\" alt=\"\" class=\"wp-image-506850\"\/><\/figure>\n\n\n\n<p>Congratulations! You have successfully built an application that fetches data from a GraphQL API in C#. As a next step, try implementing the <code>Details.cshtml<\/code> page yourself (or <a href=\"https:\/\/github.com\/maartenba\/GraphQLCountries\" target=\"_blank\" rel=\"noopener\">check out the GitHub repository<\/a> for this sample application to look at implementation details).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>In this post, we\u2019ve covered how to build a GraphQL client in .NET using JetBrains Rider and StrawberryShake. We&#8217;ve covered quite a bit of ground \u2013 from setting up your development environment and understanding the fundamentals of GraphQL, to defining schemas and queries, and finally integrating everything into a sample project.<\/p>\n\n\n\n<p>Using JetBrains Rider\u2019s GraphQL plugin and the StrawberryShake framework, we\u2019ve seen how to create strongly-typed GraphQL clients and how to work with them in your C# projects.<\/p>\n\n\n\n<p>I encourage you to try this out on your projects. Experiment with different schemas and queries, and see how you can integrate GraphQL to make your applications more efficient and responsive. JetBrains Rider, with its rich set of features and plugins, is a fantastic IDE for .NET development, and combined with StrawberryShake, you have a powerful GraphQL toolkit.<\/p>\n\n\n\n<p>Feel free to share your experiences and any cool projects you build. And if you run into any issues or have questions, let us know in the comments. Happy coding!<\/p>\n","protected":false},"author":118,"featured_media":506861,"comment_status":"closed","ping_status":"closed","template":"","categories":[4992,1401],"tags":[2865,1978],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/dotnet\/506779"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/dotnet"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/types\/dotnet"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/users\/118"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/comments?post=506779"}],"version-history":[{"count":10,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/dotnet\/506779\/revisions"}],"predecessor-version":[{"id":510728,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/dotnet\/506779\/revisions\/510728"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/media\/506861"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/media?parent=506779"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/categories?post=506779"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/tags?post=506779"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/cross-post-tag?post=506779"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}