You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: client/101/index.md
+45-8Lines changed: 45 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -4,6 +4,8 @@ Let's say we want to call an external HTTP API. Let's also say the API doesn't p
4
4
5
5
## Spacing Things Up!
6
6
7
+
We'll use SpaceX API for our little experiment. Let's set up our project - it will have a `SpaceX.Protocol` class library, containing our strongly-typed client and `SpaceX.Tests` to test our efforts. Here are the console commands for setting up our solution:
8
+
7
9
```sh
8
10
dotnet new sln --name SpaceX
9
11
dotnet new classlib --name SpaceX.Protocol
@@ -14,7 +16,7 @@ cd SpaceX.Tests
14
16
dotnet add reference ../SpaceX.Protocol
15
17
```
16
18
17
-
`LaunchesShould`
19
+
For a start, let's just see what we can get from the API. We'll create a new HttpClient, make a GET request for the latest launches, and print the results. Let's call our test class `LaunchesShould` and add the method below:
18
20
19
21
```csharp
20
22
[TestMethod]
@@ -29,6 +31,8 @@ public async Task ReturnLatestAsRawString()
29
31
}
30
32
```
31
33
34
+
Running the method should print a json object similar to the one below:
35
+
32
36
```json
33
37
{
34
38
"fairings": null,
@@ -102,8 +106,12 @@ public async Task ReturnLatestAsRawString()
102
106
}
103
107
```
104
108
109
+
With that in place, let's carry on to getting a real object from our request.
110
+
105
111
## Making It Strongly-Typed
106
112
113
+
In the `SpaceX.Protocol` let's define a `Launch` model. We'll minify it for having just the launch `Name` and `Success` flag. We should also make our path statically represented. Here's the code we will get:
114
+
107
115
```cs
108
116
namespaceSpaceX;
109
117
@@ -117,17 +125,31 @@ public class Uris {
117
125
}
118
126
```
119
127
120
-
from the `SpaceX.Protocol` folder
128
+
Now, we'll need a method converting our `HttpResponseMessage` to the model of our choice. We'll use a package called `Nist.Responses`. Let's install it in the `SpaceX.Protocol`:
121
129
122
130
```sh
123
131
dotnet add package Nist.Responses
124
132
```
125
133
134
+
Now, we should be able to use the `Read` extension method on our response to get the actual model:
135
+
126
136
```cs
127
137
varlaunch=awaitresponse.Read<Launch>();
128
138
Console.WriteLine(launch);
129
139
```
130
140
141
+
With that in place, our test should print something like this:
142
+
143
+
```log
144
+
Launch { Name = Crew-5, Success = True }
145
+
```
146
+
147
+
Perhaps the most important part is done now, but we will still need to take care of a few things.
148
+
149
+
## Logging It Up!
150
+
151
+
Besides, deserializing the response body the `Read` method ensures the response was successful and logs information about the request and response. Here's an approximation of what the logic of the `Read` method looks like:
@@ -154,16 +176,17 @@ var result = Deserialize.Json<T>(body, serializerOptions);
154
176
returnresult;
155
177
```
156
178
157
-
## Logging It Up!
179
+
For now, we haven't ripped the benefits of the built-in logging, because we haven't passed an `ILogger` to the method, so `NullLogger.Instance` was used instead. Let's fix it! First, we'll need a package with an actual logger and a package allowing us a simple logging configuration. Here's how we can install them in our test project:
Now, let's create the logger in our test class constructor. Here's the code:
187
+
164
188
```cs
165
189
readonlyILoggerlogger;
166
-
readonlyClientclient;
167
190
168
191
publicLaunchesShould()
169
192
{
@@ -175,18 +198,26 @@ public LaunchesShould()
175
198
}
176
199
```
177
200
201
+
Finally, let's pass the logger to the `Read` method:
202
+
178
203
```cs
179
204
varlaunch=awaitresponse.Read<Launch>(logger);
180
205
Console.WriteLine(launch);
181
206
```
182
207
208
+
With that, we will get information about the requests written in our console like this:
209
+
183
210
```log
184
211
info: SpaceX.Tests.LaunchesShould[0] GET /v4/launches/latest > OK {"fairings":null,"links":{"patch":{"small":"https://images2.imgbox.com/eb/d8/D1Yywp0w_o.png","large":"https://images2.imgbox.com/33/2e/k6VE4iYl_o.png"},"reddit":{"campaign":null,"launch":"https://www.reddit.com/r/spacex/comments/xvm76j/rspacex_crew5_launchcoast_docking_discussion_and/","media":null,"recovery":null},"flickr":{"small":[],"original":[]},"presskit":null,"webcast":"https://youtu.be/5EwW8ZkArL4","youtube_id":"5EwW8ZkArL4","article":null,"wikipedia":"https://en.wikipedia.org/wiki/SpaceX_Crew-5"},"static_fire_date_utc":null,"static_fire_date_unix":null,"net":false,"window":null,"rocket":"5e9d0d95eda69973a809d1ec","success":true,"failures":[],"details":null,"crew":["62dd7196202306255024d13c","62dd71c9202306255024d13d","62dd7210202306255024d13e","62dd7253202306255024d13f"],"ships":[],"capsules":["617c05591bad2c661a6e2909"],"payloads":["62dd73ed202306255024d145"],"launchpad":"5e9e4502f509094188566f88","flight_number":187,"name":"Crew-5","date_utc":"2022-10-05T16:00:00.000Z","date_unix":1664985600,"date_local":"2022-10-05T12:00:00-04:00","date_precision":"hour","upcoming":false,"cores":[{"core":"633d9da635a71d1d9c66797b","flight":1,"gridfins":true,"legs":true,"reused":false,"landing_attempt":true,"landing_success":true,"landing_type":"ASDS","landpad":"5e9e3033383ecbb9e534e7cc"}],"auto_update":true,"tbd":false,"launch_library_id":"f33d5ece-e825-4cd8-809f-1d4c72a2e0d3","id":"62dd70d5202306255024d139"}
185
212
Launch { Name = Crew-5, Success = True }
186
213
```
187
214
215
+
Now, when we've utilized the `Read` method to its fullest let's get to the next part of our journey - creating a strongly-typed client!
216
+
188
217
## Create the Client
189
218
219
+
That shouldn't take us too long, as we just need to assemble a class having `HttpClient` and `ILogger` at its disposal and wrap endpoints in a method. Here's how it might look:
@@ -195,10 +226,14 @@ public class Client(HttpClient http, ILogger<Client> logger) {
195
226
}
196
227
```
197
228
229
+
There's not much left - just to use the client. Let's simplify its registration by utilizing a `Microsoft.Extensions.Http` package:
230
+
198
231
```sh
199
232
dotnet add package Microsoft.Extensions.Http
200
233
```
201
234
235
+
And here's how our test class can register our client:
236
+
202
237
```cs
203
238
readonlyILoggerlogger;
204
239
readonlyClientclient;
@@ -215,15 +250,17 @@ public LaunchesShould()
215
250
}
216
251
```
217
252
253
+
Now, getting the latest launch will be just a single strongly typed call to the client:
254
+
218
255
```cs
219
256
varlaunch=awaitclient.GetLatestLaunch();
220
257
Console.WriteLine(launch);
221
258
```
222
259
223
-
## Wrapping Up!
224
-
225
-
Having a strongly typed SpaceX API client is nice, but what's more important is that the setup can be used as a base for any other setup. Utilizing NIST packages we were able to do it in no time.
260
+
There's not much to improve there, so let's wrap this up!
226
261
227
-
You can check out the [nist repository](https://github.com/astorDev/nist) for more http-related tooling. And you can also ... clap to this article ππ
262
+
## Wrapping Up!
228
263
264
+
Having a strongly typed SpaceX API client is nice, but what's more important is that the setup can be used as a base for more complicated scenarios. For example, the `Read` method also supports the custom `JsonSerializerSettings` and you can use `PostAsJsonAsync` from `System.Net.Http.Json` to submit information to an API, `Nist.Queries` package allows you to convert objects to query strings. All of this doesn't require you to change anything in the fundamental setup introduced in this article.
229
265
266
+
As you may see, nist packages help us to make a strongly typed http client in no time. You can check out the [nist repository](https://github.com/astorDev/nist), there are many more HTTP-related tools. And you can also ... clap to this article ππ
0 commit comments