Code samples used in this blog series have been updated to latest version of .NET Core (5.0.4) and GraphQL-Dotnet (4.2.0). Follow this link to get the updated samples.
GraphiQL
(pronounced graphical
) is an in-browser IDE for exploring GraphQL. I think it's a must-have tool for any server running behind GraphQL. With GraphiQL
in place, you can easily give yourself or your team an in-depth insight into your API.
There are setups you have to do first. We need some packages installed. Create a package.json
file and paste the following snippet,
{
"dependencies": {
"graphiql": "^1.0.0-alpha.8",
"graphql": "^15.0.0",
"isomorphic-fetch": "^2.2.1",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"@babel/core": "^7.9.6",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.9.5",
"@babel/preset-react": "^7.9.4",
"babel-loader": "^8.1.0",
"cross-env": "^7.0.2",
"css-loader": "^3.5.1",
"html-webpack-plugin": "^4.2.0",
"react-dom": "^16.12.0",
"style-loader": "^1.1.3",
"webpack": "4.42.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3"
}
}
You might say, "Why do we need React!". GraphiQL
is really just a React component. In order to use this component, we need a basic app skeleton similar to any React app, you will find online.
At this point, you can either use yarn
or npm
to install the packages.
yarn install
Or
npm install
Next, create a folder ApiExplorer
and add the following two files with the code snippets,
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<title>GraphiQL</title>
</head>
<body>
<style>
body {
padding: 0;
margin: 0;
min-height: 100vh;
}
#root {
height: 100vh;
}
</style>
<div id="root"></div>
</body>
</html>
import React from "react";
import ReactDOM from "react-dom";
import GraphiQL from "graphiql";
import fetch from "isomorphic-fetch";
import "graphiql/graphiql.css";
const Logo = () => <span>{'Api Explorer'}</span>;
GraphiQL.Logo = Logo;
function graphQLFetcher(graphQLParams) {
return fetch(`${window.location.protocol}//${window.location.host}/graphql`, {
method: "post",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(graphQLParams),
credentials: "same-origin",
})
.then(function (response) {
return response.text();
})
.then(function (responseBody) {
try {
return JSON.parse(responseBody);
} catch (error) {
return responseBody;
}
});
}
ReactDOM.render(
<GraphiQL style={{ height: '100vh' }} fetcher={graphQLFetcher} />,
document.getElementById("root")
);
GraphiQL
is a client-side library which provides a React
component i.e. <GraphiQL/>
. It renders the whole graphical user interface of the IDE. The component has a fetcher
attribute which can be attached to a function. The attached function returns an HTTP promise object which just mimics the POST
requests that we have been making with Insomnia
/Postman
. All of these are done in the index.jsx
.
The final bits is to bundle up and ship them to a publicly available static files folder. The task of bundling up is done by webpack
. Add a webpack.config.js
file and paste the following piece of code,
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const isDev = process.env.NODE_ENV === "development";
module.exports = {
entry: isDev
? [
"react-hot-loader/patch",
"webpack-dev-server/client?http://localhost:8080",
"webpack/hot/only-dev-server",
"./index.jsx",
]
: "./index.jsx",
context: path.resolve(__dirname, "./ApiExplorer"),
output: {
path: __dirname + "/wwwroot",
filename: "bundle.js",
},
mode: "development",
devtool: "inline-source-map",
performance: {
hints: false,
},
module: {
rules: [
{
test: /\.html$/,
use: ["file?name=[name].[ext]"],
},
{
type: "javascript/auto",
test: /\.mjs$/,
use: [],
include: /node_modules/,
},
{
test: /\.(js|jsx)$/,
use: [
{
loader: "babel-loader",
options: {
presets: [
["@babel/preset-env", { modules: false }],
"@babel/preset-react",
],
},
},
],
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.svg$/,
use: [{ loader: "svg-inline-loader" }],
},
],
},
resolve: {
extensions: [".js", ".json", ".jsx", ".css", ".mjs"],
},
plugins: [new HtmlWebpackPlugin({ template: "index.html.ejs" })],
devServer: {
hot: true,
allowedHosts: ["localhost:5000"],
},
node: {
fs: "empty",
module: "empty",
},
};
The configuration is pretty much self-explanatory. It takes all the files under the ApiExplorer
folder, the dependencies from the node_modules
and compiles them into a single bundle.js
file. It also generates an index.html
file. Both of the compiled files are sent to the wwwroot
to make them publicly available.
All done! Now run the webpack
command in the terminal on the root of your project.
webpack --mode=development
On the server-side, in Startup.cs
files, add the middleware to serve static files, specifically the default index.html
file,
The Configure
method should look like the following,
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseGraphQL();
}
Now, run the application and you will be presented with the following interface,

If you get an error like the following,
System.InvalidOperationException: Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
ASP.NET 3.0+
throws this error when some synchronous call is made. It means that GraphQL Dotnet
library still depends on Newtonsoft.Json
. And that library does some synchronous code execution. But for the time being, we can also overcome this situation. We only have to add these lines of code in ConfigureServices
method.
services.AddGraphQL(options =>
{
options.EndPoint = "/graphql";
});
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
On the right-hand side is the documentation explorer pane, you can browse through different queries and have a deep understanding of what fields are available and what they are supposed to do
Some of the nice features this IDE has to offer are as follows,
- Syntax highlighting
- Intelligent type ahead of fields, arguments, types, and more.
- Real-time error highlighting and reporting.
- Automatic query completion.
- Run and inspect query results.
Comments