Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 225 additions & 31 deletions aspnetcore/tutorials/first-mongo-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,69 +263,263 @@ The preceding web API controller:
* Contains action methods to support GET, POST, PUT, and DELETE HTTP requests.
* 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.

## Configure JSON serialization options
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this section before the testing section, because the testing section uses the configured JSON serialization options, e.g. bookName is mapped to Name.


There are two details to change about the JSON responses returned in the [Test the web API](#test-the-web-api) section:

* The property names' default camel casing should be changed to match the Pascal casing of the CLR object's property names.
* The `bookName` property should be returned as `Name`.

To satisfy the preceding requirements, make the following changes:

1. In `Program.cs`, chain the following highlighted code on to the `AddControllers` method call:

:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Program.cs" id="snippet_AddControllers" highlight="10-11":::

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`.

1. In `Models/Book.cs`, annotate the `BookName` property with the [`[JsonPropertyName]`](xref:System.Text.Json.Serialization.JsonPropertyNameAttribute) attribute:

:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/Book.cs" id="snippet_BookName" highlight="2":::

The `[JsonPropertyName]` attribute's value of `Name` represents the property name in the web API's serialized JSON response.

1. Add the following code to the top of `Models/Book.cs` to resolve the `[JsonProperty]` attribute reference:

:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/Book.cs" id="snippet_UsingSystemTextJsonSerialization":::

1. Repeat the steps defined in the [Test the web API](#test-the-web-api) section. Notice the difference in JSON property names.

## Test the web API

# [Visual Studio](#tab/visual-studio)

This tutorial uses [Endpoints Explorer and .http files](xref:test/http-files#use-endpoints-explorer) to test the API.

1. Build and run the app.

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:
1. In **Endpoints Explorer**, right-click the first **GET** endpoint `/api/books`, and select **Generate request**.

The following content is added to the `BookStoreApi.http` file.
If this is the first time that a request is generated, the file is created in the project root.

```
@BookStoreApi_HostAddress = https://localhost:<port>

GET {{BookStoreApi_HostAddress}}/api/books

###
```

The port number should already be set to the port used by the app, for example, `https://localhost:56874`.
If that's not the case you can find your port number in the output window when you launch the app.

1. Select the **Send request** link above the new `GET` request line.

The GET request is sent to the app and the response is displayed in the **Response** pane.

1. The response body shows the JSON result containing the book entries similar to the following:

```json
[
{
"id": "61a6058e6c43f32854e51f51",
"bookName": "Design Patterns",
"price": 54.93,
"category": "Computers",
"author": "Ralph Johnson"
"Id": "61a6058e6c43f32854e51f51",
"Name": "Design Patterns",
"Price": 54.93,
"Category": "Computers",
"Author": "Ralph Johnson"
},
{
"id": "61a6058e6c43f32854e51f52",
"bookName": "Clean Code",
"price": 43.15,
"category": "Computers",
"author": "Robert C. Martin"
"Id": "61a6058e6c43f32854e51f52",
"Name": "Clean Code",
"Price": 43.15,
"Category": "Computers",
"Author": "Robert C. Martin"
}
]
```

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:
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**.

The following content is appended to the `BookStoreApi.http` file:

```
@id=string
GET {{BookStoreApi_HostAddress}}/api/books/{{id}}

###
```

1. Replace `id` variable with one of the IDs returned from the earlier request, for example:

```
@id="61a6058e6c43f32854e51f52"
GET {{BookStoreApi_HostAddress}}/api/books/{{id}}

###
```

1. Select the **Send request** link above the new `GET` request line.

The GET request is sent to the app and the response is displayed in the **Response** pane.

1. The response body shows JSON similar to the following:

```json
{
"id": "61a6058e6c43f32854e51f52",
"bookName": "Clean Code",
"price": 43.15,
"category": "Computers",
"author": "Robert C. Martin"
"Id": "61a6058e6c43f32854e51f52",
"Name": "Clean Code",
"Price": 43.15,
"Category": "Computers",
"Author": "Robert C. Martin"
}
```

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

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

* The property names' default camel casing should be changed to match the Pascal casing of the CLR object's property names.
* The `bookName` property should be returned as `Name`.
```
POST {{BookStoreApi_HostAddress}}/api/books
Content-Type: application/json

To satisfy the preceding requirements, make the following changes:
{
//Book
}

###
```

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

:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Program.cs" id="snippet_AddControllers" highlight="10-11":::
```
POST {{BookStoreApi_HostAddress}}/api/books
Content-Type: application/json

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`.
{
"Name": "The Pragmatic Programmer",
"Price": 49.99,
"Category": "Computers",
"Author": "Andy Hunt"
}

###
```

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

:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/Book.cs" id="snippet_BookName" highlight="2":::
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.

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

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

:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/Book.cs" id="snippet_UsingSystemTextJsonSerialization":::
```
DELETE {{BookStoreApi_HostAddress}}/api/Books/{{id}}

###
```

1. Repeat the steps defined in the [Test the web API](#test-the-web-api) section. Notice the difference in JSON property names.
1. Replace the `id` variable with one of the IDs returned from the earlier request, and click **Send request**. For example:

```
DELETE {{BookStoreApi_HostAddress}}/api/Books/67f417517ce1b36aeab71236

###
```

# [Visual Studio Code](#tab/visual-studio-code)

This tutorial uses the [OpenAPI specification (openapi.json) and Swagger UI](xref:tutorials/web-api-help-pages-using-swagger) to test the API.

1. Install Swagger UI by running the following command:

```dotnetcli
dotnet add package NSwag.AspNetCore
```

The previous command adds the [NSwag.AspNetCore](https://www.nuget.org/packages/NSwag.AspNetCore/) package, which contains tools to generate Swagger documents and UI.
Because our project is using OpenAPI, we only use the NSwag package to generate the Swagger UI.

1. Configure Swagger middleware

In `Program.cs`, add the following highlighted code:

:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Program.cs" id="snippet_UseSwagger" highlight="6-9":::

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.

The app uses the OpenAPI document generated by OpenApi, located at `/openapi/v1.json`, to generate the UI.
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.

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.

1. Build and run the app.

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.

1. Expand the **GET /api/books** endpoint and click the **Try it out** button.

1. Click the **Execute** button to send the request to the API.

1. The **Response body** section displays a JSON array with books similar to the following:

```json
[
{
"Id": "61a6058e6c43f32854e51f51",
"Name": "Design Patterns",
"Price": 54.93,
"Category": "Computers",
"Author": "Ralph Johnson"
},
{
"Id": "61a6058e6c43f32854e51f52",
"Name": "Clean Code",
"Price": 43.15,
"Category": "Computers",
"Author": "Robert C. Martin"
}
]
```

1. Next, expand the **GET /api/books/{id}** endpoint and click **Try it out**.

1. Enter one of the book IDs from the previous response in the **id** field, then click **Execute**.

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:

```json
{
"Id": "61a6058e6c43f32854e51f52",
"Name": "Clean Code",
"Price": 43.15,
"Category": "Computers",
"Author": "Robert C. Martin"
}
```

1. To test creating a new book, expand the **POST /api/books** endpoint and click **Try it out**.

1. Replace the default request body with a new book object:

```json
{
"Name": "The Pragmatic Programmer",
"Price": 49.99,
"Category": "Computers",
"Author": "Andy Hunt"
}
```

1. Click **Execute** to send the request.

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.

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.

1. The response should have a status code of 204 (No Content), indicating that the book was successfully deleted.
---

## Add authentication support to a web API

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
<PackageReference Include="MongoDB.Driver" Version="3.3.0" />
<PackageReference Include="NSwag.AspNetCore" Version="14.3.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@BookStoreApi_HostAddress = https://localhost:56874

GET {{BookStoreApi_HostAddress}}/api/books

###

@id=string
GET {{BookStoreApi_HostAddress}}/api/Books/{{id}}

###

POST {{BookStoreApi_HostAddress}}/api/books
Content-Type: application/json

{
//Book
}

###

DELETE {{BookStoreApi_HostAddress}}/api/Books/{{id}}

###

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@

builder.Services.AddOpenApi();

// <snippet_UseSwagger>
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
Expand All @@ -36,6 +36,7 @@
options.SwaggerEndpoint("/openapi/v1.json", "v1");
});
}
// </snippet_UseSwagger>

app.UseHttpsRedirection();

Expand Down

This file was deleted.