Skip to content

Commit d73608a

Browse files
Merge pull request #35221 from timdeschryver/issue/35180
Add testing options to the mongodb Web Api tutorial
2 parents 048177b + e5d02c5 commit d73608a

File tree

6 files changed

+251
-76
lines changed

6 files changed

+251
-76
lines changed

aspnetcore/tutorials/first-mongo-app.md

Lines changed: 225 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -263,69 +263,263 @@ The preceding web API controller:
263263
* Contains action methods to support GET, POST, PUT, and DELETE HTTP requests.
264264
* Calls <xref:Microsoft.AspNetCore.Mvc.ControllerBase.CreatedAtAction%2A> in the `Create` action method to return an [HTTP 201](https://www.rfc-editor.org/rfc/rfc9110#status.201) response. Status code 201 is the standard response for an HTTP POST method that creates a new resource on the server. `CreatedAtAction` also adds a `Location` header to the response. The `Location` header specifies the URI of the newly created book.
265265

266+
## Configure JSON serialization options
267+
268+
There are two details to change about the JSON responses returned in the [Test the web API](#test-the-web-api) section:
269+
270+
* The property names' default camel casing should be changed to match the Pascal casing of the CLR object's property names.
271+
* The `bookName` property should be returned as `Name`.
272+
273+
To satisfy the preceding requirements, make the following changes:
274+
275+
1. In `Program.cs`, chain the following highlighted code on to the `AddControllers` method call:
276+
277+
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Program.cs" id="snippet_AddControllers" highlight="10-11":::
278+
279+
With the preceding change, property names in the web API's serialized JSON response match their corresponding property names in the CLR object type. For example, the `Book` class's `Author` property serializes as `Author` instead of `author`.
280+
281+
1. In `Models/Book.cs`, annotate the `BookName` property with the [`[JsonPropertyName]`](xref:System.Text.Json.Serialization.JsonPropertyNameAttribute) attribute:
282+
283+
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/Book.cs" id="snippet_BookName" highlight="2":::
284+
285+
The `[JsonPropertyName]` attribute's value of `Name` represents the property name in the web API's serialized JSON response.
286+
287+
1. Add the following code to the top of `Models/Book.cs` to resolve the `[JsonProperty]` attribute reference:
288+
289+
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/Book.cs" id="snippet_UsingSystemTextJsonSerialization":::
290+
291+
1. Repeat the steps defined in the [Test the web API](#test-the-web-api) section. Notice the difference in JSON property names.
292+
266293
## Test the web API
267294

295+
# [Visual Studio](#tab/visual-studio)
296+
297+
This tutorial uses [Endpoints Explorer and .http files](xref:test/http-files#use-endpoints-explorer) to test the API.
298+
268299
1. Build and run the app.
269300

270-
1. Navigate to `https://localhost:<port>/api/books`, where `<port>` is the automatically assigned port number for the app, to test the controller's parameterless `Get` action method. A JSON response similar to the following is displayed:
301+
1. In **Endpoints Explorer**, right-click the first **GET** endpoint `/api/books`, and select **Generate request**.
302+
303+
The following content is added to the `BookStoreApi.http` file.
304+
If this is the first time that a request is generated, the file is created in the project root.
305+
306+
```
307+
@BookStoreApi_HostAddress = https://localhost:<port>
308+
309+
GET {{BookStoreApi_HostAddress}}/api/books
310+
311+
###
312+
```
313+
314+
The port number should already be set to the port used by the app, for example, `https://localhost:56874`.
315+
If that's not the case you can find your port number in the output window when you launch the app.
316+
317+
1. Select the **Send request** link above the new `GET` request line.
318+
319+
The GET request is sent to the app and the response is displayed in the **Response** pane.
320+
321+
1. The response body shows the JSON result containing the book entries similar to the following:
271322

272323
```json
273324
[
274325
{
275-
"id": "61a6058e6c43f32854e51f51",
276-
"bookName": "Design Patterns",
277-
"price": 54.93,
278-
"category": "Computers",
279-
"author": "Ralph Johnson"
326+
"Id": "61a6058e6c43f32854e51f51",
327+
"Name": "Design Patterns",
328+
"Price": 54.93,
329+
"Category": "Computers",
330+
"Author": "Ralph Johnson"
280331
},
281332
{
282-
"id": "61a6058e6c43f32854e51f52",
283-
"bookName": "Clean Code",
284-
"price": 43.15,
285-
"category": "Computers",
286-
"author": "Robert C. Martin"
333+
"Id": "61a6058e6c43f32854e51f52",
334+
"Name": "Clean Code",
335+
"Price": 43.15,
336+
"Category": "Computers",
337+
"Author": "Robert C. Martin"
287338
}
288339
]
289340
```
290341

291-
1. Navigate to `https://localhost:<port>/api/books/{id here}` to test the controller's overloaded `Get` action method. A JSON response similar to the following is displayed:
342+
1. To retrieve a single book, right-click the `/api/books/{id}, params (string id)` **GET** endpoint in the **Endpoints Explorer**, and select **Generate request**.
343+
344+
The following content is appended to the `BookStoreApi.http` file:
345+
346+
```
347+
@id=string
348+
GET {{BookStoreApi_HostAddress}}/api/books/{{id}}
349+
350+
###
351+
```
352+
353+
1. Replace `id` variable with one of the IDs returned from the earlier request, for example:
354+
355+
```
356+
@id="61a6058e6c43f32854e51f52"
357+
GET {{BookStoreApi_HostAddress}}/api/books/{{id}}
358+
359+
###
360+
```
361+
362+
1. Select the **Send request** link above the new `GET` request line.
363+
364+
The GET request is sent to the app and the response is displayed in the **Response** pane.
365+
366+
1. The response body shows JSON similar to the following:
292367

293368
```json
294369
{
295-
"id": "61a6058e6c43f32854e51f52",
296-
"bookName": "Clean Code",
297-
"price": 43.15,
298-
"category": "Computers",
299-
"author": "Robert C. Martin"
370+
"Id": "61a6058e6c43f32854e51f52",
371+
"Name": "Clean Code",
372+
"Price": 43.15,
373+
"Category": "Computers",
374+
"Author": "Robert C. Martin"
300375
}
301376
```
302377

303-
## Configure JSON serialization options
378+
1. To test the POST endpoint, right-click the `/api/books` **POST** endpoint and select **Generate request**.
304379

305-
There are two details to change about the JSON responses returned in the [Test the web API](#test-the-web-api) section:
380+
The following content is added to the `BookStoreApi.http` file:
306381

307-
* The property names' default camel casing should be changed to match the Pascal casing of the CLR object's property names.
308-
* The `bookName` property should be returned as `Name`.
382+
```
383+
POST {{BookStoreApi_HostAddress}}/api/books
384+
Content-Type: application/json
309385
310-
To satisfy the preceding requirements, make the following changes:
386+
{
387+
//Book
388+
}
389+
390+
###
391+
```
311392

312-
1. In `Program.cs`, chain the following highlighted code on to the `AddControllers` method call:
393+
1. Replace the Book comment with a book object as the JSON request body:
313394

314-
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Program.cs" id="snippet_AddControllers" highlight="10-11":::
395+
```
396+
POST {{BookStoreApi_HostAddress}}/api/books
397+
Content-Type: application/json
315398
316-
With the preceding change, property names in the web API's serialized JSON response match their corresponding property names in the CLR object type. For example, the `Book` class's `Author` property serializes as `Author` instead of `author`.
399+
{
400+
"Name": "The Pragmatic Programmer",
401+
"Price": 49.99,
402+
"Category": "Computers",
403+
"Author": "Andy Hunt"
404+
}
405+
406+
###
407+
```
317408

318-
1. In `Models/Book.cs`, annotate the `BookName` property with the [`[JsonPropertyName]`](xref:System.Text.Json.Serialization.JsonPropertyNameAttribute) attribute:
409+
1. Select the **Send request** link above the `POST` request line.
319410

320-
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/Book.cs" id="snippet_BookName" highlight="2":::
411+
The POST request is sent to the app, and the response is displayed in the **Response** pane. The response should include the newly created book with its assigned ID.
321412

322-
The `[JsonPropertyName]` attribute's value of `Name` represents the property name in the web API's serialized JSON response.
413+
1. Lastly, to delete a book, right-click the `/api/books/{id}, params (string id)` **DELETE** endpoint and select **Generate request**.
323414

324-
1. Add the following code to the top of `Models/Book.cs` to resolve the `[JsonProperty]` attribute reference:
415+
The following content is appended to the `BookStoreApi.http` file:
325416

326-
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/Book.cs" id="snippet_UsingSystemTextJsonSerialization":::
417+
```
418+
DELETE {{BookStoreApi_HostAddress}}/api/Books/{{id}}
419+
420+
###
421+
```
327422

328-
1. Repeat the steps defined in the [Test the web API](#test-the-web-api) section. Notice the difference in JSON property names.
423+
1. Replace the `id` variable with one of the IDs returned from the earlier request, and click **Send request**. For example:
424+
425+
```
426+
DELETE {{BookStoreApi_HostAddress}}/api/Books/67f417517ce1b36aeab71236
427+
428+
###
429+
```
430+
431+
# [Visual Studio Code](#tab/visual-studio-code)
432+
433+
This tutorial uses the [OpenAPI specification (openapi.json) and Swagger UI](xref:tutorials/web-api-help-pages-using-swagger) to test the API.
434+
435+
1. Install Swagger UI by running the following command:
436+
437+
```dotnetcli
438+
dotnet add package NSwag.AspNetCore
439+
```
440+
441+
The previous command adds the [NSwag.AspNetCore](https://www.nuget.org/packages/NSwag.AspNetCore/) package, which contains tools to generate Swagger documents and UI.
442+
Because our project is using OpenAPI, we only use the NSwag package to generate the Swagger UI.
443+
444+
1. Configure Swagger middleware
445+
446+
In `Program.cs`, add the following highlighted code:
447+
448+
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Program.cs" id="snippet_UseSwagger" highlight="6-9":::
449+
450+
The previous code enables the Swagger middleware for serving the generated JSON document using the Swagger UI. Swagger is only enabled in a development environment. Enabling Swagger in a production environment could expose potentially sensitive details about the API's structure and implementation.
451+
452+
The app uses the OpenAPI document generated by OpenApi, located at `/openapi/v1.json`, to generate the UI.
453+
View the generated OpenAPI specification for the `WeatherForecast` API while the project is running by navigating to `https://localhost:<port>/openapi/v1.json` in your browser.
454+
455+
The OpenAPI specification is a document in JSON format that describes the structure and capabilities of your API, including endpoints, request/response formats, parameters, and more. It's essentially a blueprint of your API that can be used by various tools to understand and interact with your API.
456+
457+
1. Build and run the app.
458+
459+
1. Navigate to `https://localhost:<port>/swagger` in your browser. Swagger provides a UI to test all the API endpoints based on the OpenAPI document.
460+
461+
1. Expand the **GET /api/books** endpoint and click the **Try it out** button.
462+
463+
1. Click the **Execute** button to send the request to the API.
464+
465+
1. The **Response body** section displays a JSON array with books similar to the following:
466+
467+
```json
468+
[
469+
{
470+
"Id": "61a6058e6c43f32854e51f51",
471+
"Name": "Design Patterns",
472+
"Price": 54.93,
473+
"Category": "Computers",
474+
"Author": "Ralph Johnson"
475+
},
476+
{
477+
"Id": "61a6058e6c43f32854e51f52",
478+
"Name": "Clean Code",
479+
"Price": 43.15,
480+
"Category": "Computers",
481+
"Author": "Robert C. Martin"
482+
}
483+
]
484+
```
485+
486+
1. Next, expand the **GET /api/books/{id}** endpoint and click **Try it out**.
487+
488+
1. Enter one of the book IDs from the previous response in the **id** field, then click **Execute**.
489+
490+
1. The **Response body** section displays the JSON object for the specified book. For example, the result for the ID `61a6058e6c43f32854e51f52` is similar to the following:
491+
492+
```json
493+
{
494+
"Id": "61a6058e6c43f32854e51f52",
495+
"Name": "Clean Code",
496+
"Price": 43.15,
497+
"Category": "Computers",
498+
"Author": "Robert C. Martin"
499+
}
500+
```
501+
502+
1. To test creating a new book, expand the **POST /api/books** endpoint and click **Try it out**.
503+
504+
1. Replace the default request body with a new book object:
505+
506+
```json
507+
{
508+
"Name": "The Pragmatic Programmer",
509+
"Price": 49.99,
510+
"Category": "Computers",
511+
"Author": "Andy Hunt"
512+
}
513+
```
514+
515+
1. Click **Execute** to send the request.
516+
517+
1. The response should have a status code of 201 (Created) and include the newly created book with its assigned ID in the response body.
518+
519+
1. Lastly, to delete a book record, expand the **DELETE /api/books/{id}** endpoint, click **Try it out**, and enter one of the book IDs from the previous response in the **id** field. Click **Execute** to send the request.
520+
521+
1. The response should have a status code of 204 (No Content), indicating that the book was successfully deleted.
522+
---
329523

330524
## Add authentication support to a web API
331525

aspnetcore/tutorials/first-mongo-app/samples/9.x/BookStoreApi/BookStoreApi.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<ItemGroup>
1010
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
1111
<PackageReference Include="MongoDB.Driver" Version="3.3.0" />
12+
<PackageReference Include="NSwag.AspNetCore" Version="14.3.0" />
1213
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
1314
</ItemGroup>
1415

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@BookStoreApi_HostAddress = https://localhost:56874
2+
3+
GET {{BookStoreApi_HostAddress}}/api/books
4+
5+
###
6+
7+
@id=string
8+
GET {{BookStoreApi_HostAddress}}/api/Books/{{id}}
9+
10+
###
11+
12+
POST {{BookStoreApi_HostAddress}}/api/books
13+
Content-Type: application/json
14+
15+
{
16+
//Book
17+
}
18+
19+
###
20+
21+
DELETE {{BookStoreApi_HostAddress}}/api/Books/{{id}}
22+
23+
###

aspnetcore/tutorials/first-mongo-app/samples/9.x/BookStoreApi/Controllers/WeatherForecastController.cs

Lines changed: 0 additions & 32 deletions
This file was deleted.

aspnetcore/tutorials/first-mongo-app/samples/9.x/BookStoreApi/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525

2626
builder.Services.AddOpenApi();
2727

28+
// <snippet_UseSwagger>
2829
var app = builder.Build();
2930

30-
// Configure the HTTP request pipeline.
3131
if (app.Environment.IsDevelopment())
3232
{
3333
app.MapOpenApi();
@@ -36,6 +36,7 @@
3636
options.SwaggerEndpoint("/openapi/v1.json", "v1");
3737
});
3838
}
39+
// </snippet_UseSwagger>
3940

4041
app.UseHttpsRedirection();
4142

aspnetcore/tutorials/first-mongo-app/samples/9.x/BookStoreApi/WeatherForecast.cs

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)