Skip to content

Commit c774d90

Browse files
authoredApr 27, 2021
Added Fetching from REST documentation (#3601)
1 parent 1285f1c commit c774d90

File tree

1 file changed

+242
-5
lines changed

1 file changed

+242
-5
lines changed
 

‎website/src/docs/hotchocolate/fetching-data/fetching-from-rest.md

+242-5
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,249 @@
22
title: "Fetching from REST"
33
---
44

5-
Hi,
5+
import { ExampleTabs } from "../../../components/mdx/example-tabs"
66

7-
We're currently working on the version 11 documentation. Probably right now at this very moment. However, this is an open-source project, and we need any help we can get! You can jump in at any time and help us improve the documentation for hundreds or even thousands of developers!
7+
In this section, we will cover how you can easily integrate a REST API into your GraphQL API.
88

9-
In case you might need help, check out our slack channel and get immediate help from the core contributors or the community itself.
9+
GraphQL has a strongly-typed type system and therefore also has to know the dotnet runtime types of the data it returns in advance.
10+
The easiest way to integrate a REST API is, to define an OpenAPI specification for it.
11+
OpenAPI describes what data a REST endpoint returns.
12+
You can automatically generate a dotnet client for this API and integrate it into your schema.
1013

11-
Sorry for any inconvenience, and thank you for being patient!
14+
# OpenAPI in .NET
15+
If you do not have an OpenAPI specification for your REST endpoint yet, you can easily add it to your API.
16+
There are two major OpenAPI implementations in dotnet: [NSwag](http://nswag.org) and [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore).
17+
Head over to the [official ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-5.0) documentation to see how it is done.
18+
19+
In this example, we will use [the official example of Swashbuckle](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/tutorials/web-api-help-pages-using-swagger/samples/3.0/TodoApi.Swashbuckle).
20+
When you start this project, you can navigate to the [Swagger UI](http://localhost:5000/swagger).
1221

13-
The ChilliCream Team
22+
This REST API covers a simple Todo app.
23+
We will expose `todos` and `todoById` in our GraphQL API.
24+
# Generating a client
25+
Every REST endpoint that supports OpenAPI, can easily be wrapped with a fully typed client.
26+
Again, you have several options on how you generate your client.
27+
You can generate your client from the OpenAPI specification of your endpoint, during build or even with external tools with GUI.
28+
Have a look here and see what fits your use case the best:
29+
- [NSwag Code Generation](https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-nswag?view=aspnetcore-5.0&tabs=visual-studio#code-generation)
30+
31+
In this example, we will use the NSwag dotnet tool.
32+
First, we need to create a tool manifest.
33+
Switch to your GraphQL project and execute
34+
35+
```bash
36+
dotnet new tool-manifest
37+
```
38+
39+
Then we install the NSwag tool
40+
41+
```bash
42+
dotnet tool install NSwag.ConsoleCore --version 13.10.9
43+
```
44+
45+
You then have to get the `swagger.json` from your REST endpoint
46+
47+
```bash
48+
curl http://localhost:5000/swagger/v1/swagger.json > swagger.json
49+
```
50+
51+
Now you can generate the client from the `swagger.json`.
52+
53+
```bash
54+
dotnet nswag swagger2csclient /input:swagger.json /classname:TodoService /namespace:TodoReader /output:TodoService.cs
55+
```
56+
57+
The code generator generated a new file called `TodoService.cs`.
58+
In this file, you will find the client for your REST API.
59+
60+
The generated needs `Newtonsoft.Json`.
61+
Make sure to also add this package by executing:
62+
63+
```bash
64+
dotnet add package Newtonsoft.Json
65+
```
66+
67+
# Exposing the API
68+
You will have to register the client in the dependency injection of your GraphQL service.
69+
To expose the API you can inject the generated client into your resolvers.
70+
71+
<ExampleTabs>
72+
<ExampleTabs.Annotation>
73+
74+
```csharp
75+
// Query.cs
76+
public class Query
77+
{
78+
public Task<ICollection<TodoItem>> GetTodosAsync(
79+
[Service]TodoService service,
80+
CancellationToken cancellationToken)
81+
{
82+
return service.GetAllAsync(cancellationToken);
83+
}
84+
85+
public Task<TodoItem> GetTodoByIdAsync(
86+
[Service]TodoService service,
87+
long id,
88+
CancellationToken cancellationToken)
89+
{
90+
return service.GetByIdAsync(id, cancellationToken);
91+
}
92+
}
93+
94+
// Startup.cs
95+
public class Startup
96+
{
97+
public void ConfigureServices(IServiceCollection services)
98+
{
99+
services.AddHttpClient<TodoService>();
100+
services
101+
.AddRouting()
102+
.AddGraphQLServer()
103+
.AddQueryType<Query>();
104+
}
105+
106+
// Omitted code for brevity
107+
}
108+
```
109+
110+
</ExampleTabs.Annotation>
111+
<ExampleTabs.Code>
112+
113+
```csharp
114+
// Query.cs
115+
public class Query
116+
{
117+
public Task<ICollection<TodoItem>> GetTodosAsync(
118+
[Service]TodoService service,
119+
CancellationToken cancellationToken)
120+
{
121+
return service.GetAllAsync(cancellationToken);
122+
}
123+
124+
public Task<TodoItem> GetTodoByIdAsync(
125+
[Service]TodoService service,
126+
long id,
127+
CancellationToken cancellationToken)
128+
{
129+
return service.GetByIdAsync(id, cancellationToken);
130+
}
131+
}
132+
133+
// QueryType.cs
134+
public class QueryType : ObjectType<Query>
135+
{
136+
protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
137+
{
138+
descriptor
139+
.Field(f => f.GetTodoByIdAsync(default!, default!, default!))
140+
.Type<TodoType>();
141+
142+
descriptor
143+
.Field(f => f.GetTodosAsync(default!, default!))
144+
.Type<ListType<TodoType>>();
145+
}
146+
}
147+
148+
// TodoType.cs
149+
public class TodoType : ObjectType<Todo>
150+
{
151+
protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
152+
{
153+
descriptor
154+
.Field(f => f.Id)
155+
.Type<LongType>();
156+
157+
descriptor
158+
.Field(f => f.Name)
159+
.Type<StringType>();
160+
161+
descriptor
162+
.Field(f => f.IsComplete)
163+
.Type<BooleanType>();
164+
}
165+
}
166+
167+
168+
// Startup.cs
169+
public class Startup
170+
{
171+
public void ConfigureServices(IServiceCollection services)
172+
{
173+
services
174+
.AddRouting()
175+
.AddGraphQLServer()
176+
.AddQueryType<QueryType>();
177+
}
178+
179+
// Omitted code for brevity
180+
}
181+
```
182+
183+
</ExampleTabs.Code>
184+
<ExampleTabs.Schema>
185+
186+
```csharp
187+
// Query.cs
188+
public class Query
189+
{
190+
public Task<ICollection<TodoItem>> GetTodosAsync(
191+
[Service]TodoService service,
192+
CancellationToken cancellationToken)
193+
{
194+
return service.GetAllAsync(cancellationToken);
195+
}
196+
197+
public Task<TodoItem> GetTodoByIdAsync(
198+
[Service]TodoService service,
199+
long id,
200+
CancellationToken cancellationToken)
201+
{
202+
return service.GetByIdAsync(id, cancellationToken);
203+
}
204+
}
205+
206+
// Startup.cs
207+
public class Startup
208+
{
209+
public void ConfigureServices(IServiceCollection services)
210+
{
211+
services
212+
.AddRouting()
213+
.AddGraphQLServer()
214+
.AddDocumentFromString(@"
215+
type Query {
216+
todos: [TodoItem!]!
217+
todoById(id: Uuid): TodoItem
218+
}
219+
220+
type TodoItem {
221+
id: Long
222+
name: String
223+
isCompleted: Boolean
224+
}
225+
")
226+
.BindComplexType<Query>();
227+
}
228+
229+
// Omitted code for brevity
230+
}
231+
```
232+
233+
</ExampleTabs.Schema>
234+
</ExampleTabs>
235+
236+
You can now head over to your Banana Cake Pop on your GraphQL Server (/graphql) and query todos:
237+
```graphql
238+
{
239+
todoById(id:1){
240+
id
241+
isComplete
242+
name
243+
}
244+
todos {
245+
id
246+
isComplete
247+
name
248+
}
249+
}
250+
```

0 commit comments

Comments
 (0)
Please sign in to comment.