Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
30 changes: 15 additions & 15 deletions aspnetcore/tutorials/first-mongo-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: This tutorial demonstrates how to create an ASP.NET Core web API us
monikerRange: '>= aspnetcore-3.1'
ms.author: wpickett
ms.custom: mvc, engagement-fy23
ms.date: 04/17/2024
ms.date: 04/09/2025
uid: tutorials/first-mongo-app
---
# Create a web API with ASP.NET Core and MongoDB
Expand Down Expand Up @@ -182,7 +182,7 @@ Use the previously installed MongoDB Shell in the following steps to create a da
1. Add a *Models* directory to the project root.
1. Add a `Book` class to the *Models* directory with the following code:

:::code language="csharp" source="first-mongo-app/samples_snapshot/6.x/Book.cs":::
:::code language="csharp" source="first-mongo-app/samples_snapshot/9.x/Book.cs":::

In the preceding class, the `Id` property is:

Expand All @@ -196,48 +196,48 @@ Use the previously installed MongoDB Shell in the following steps to create a da

1. Add the following database configuration values to `appsettings.json`:

:::code language="json" source="first-mongo-app/samples/6.x/BookStoreApi/appsettings.json" highlight="2-6":::
:::code language="json" source="first-mongo-app/samples/9.x/BookStoreApi/appsettings.json" highlight="2-6":::

1. Add a `BookStoreDatabaseSettings` class to the *Models* directory with the following code:

:::code language="csharp" source="first-mongo-app/samples/6.x/BookStoreApi/Models/BookStoreDatabaseSettings.cs":::
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Models/BookStoreDatabaseSettings.cs":::

The preceding `BookStoreDatabaseSettings` class is used to store the `appsettings.json` file's `BookStoreDatabase` property values. The JSON and C# property names are named identically to ease the mapping process.

1. Add the following highlighted code to `Program.cs`:

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

In the preceding code, the configuration instance to which the `appsettings.json` file's `BookStoreDatabase` section binds is registered in the Dependency Injection (DI) container. For example, the `BookStoreDatabaseSettings` object's `ConnectionString` property is populated with the `BookStoreDatabase:ConnectionString` property in `appsettings.json`.

1. Add the following code to the top of `Program.cs` to resolve the `BookStoreDatabaseSettings` reference:

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

## Add a CRUD operations service

1. Add a *Services* directory to the project root.
1. Add a `BooksService` class to the *Services* directory with the following code:

:::code language="csharp" source="first-mongo-app/samples/6.x/BookStoreApi/Services/BooksService.cs" id="snippet_File":::
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Services/BooksService.cs" id="snippet_File":::

In the preceding code, a `BookStoreDatabaseSettings` instance is retrieved from DI via constructor injection. This technique provides access to the `appsettings.json` configuration values that were added in the [Add a configuration model](#add-a-configuration-model) section.

1. Add the following highlighted code to `Program.cs`:

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

In the preceding code, the `BooksService` class is registered with DI to support constructor injection in consuming classes. The singleton service lifetime is most appropriate because `BooksService` takes a direct dependency on `MongoClient`. Per the official [Mongo Client reuse guidelines](https://mongodb.github.io/mongo-csharp-driver/2.14/reference/driver/connecting/#re-use), `MongoClient` should be registered in DI with a singleton service lifetime.

1. Add the following code to the top of `Program.cs` to resolve the `BooksService` reference:

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

The `BooksService` class uses the following `MongoDB.Driver` members to run CRUD operations against the database:

* [MongoClient](https://mongodb.github.io/mongo-csharp-driver/2.14/apidocs/html/T_MongoDB_Driver_MongoClient.htm): Reads the server instance for running database operations. The constructor of this class is provided in the MongoDB connection string:

:::code language="csharp" source="first-mongo-app/samples/6.x/BookStoreApi/Services/BooksService.cs" id="snippet_ctor" highlight="4-5":::
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Services/BooksService.cs" id="snippet_ctor" highlight="4-5":::

* [IMongoDatabase](https://mongodb.github.io/mongo-csharp-driver/2.14/apidocs/html/T_MongoDB_Driver_IMongoDatabase.htm): Represents the Mongo database for running operations. This tutorial uses the generic [GetCollection\<TDocument>(collection)](https://mongodb.github.io/mongo-csharp-driver/2.14/apidocs/html/M_MongoDB_Driver_IMongoDatabase_GetCollection__1.htm) method on the interface to gain access to data in a specific collection. Run CRUD operations against the collection after this method is called. In the `GetCollection<TDocument>(collection)` method call:

Expand All @@ -255,7 +255,7 @@ The `BooksService` class uses the following `MongoDB.Driver` members to run CRUD

Add a `BooksController` class to the *Controllers* directory with the following code:

:::code language="csharp" source="first-mongo-app/samples/6.x/BookStoreApi/Controllers/BooksController.cs":::
:::code language="csharp" source="first-mongo-app/samples/9.x/BookStoreApi/Controllers/BooksController.cs":::

The preceding web API controller:

Expand Down Expand Up @@ -311,19 +311,19 @@ 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/6.x/BookStoreApi/Program.cs" id="snippet_AddControllers" highlight="10-11":::
:::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/6.x/BookStoreApi/Models/Book.cs" id="snippet_BookName" highlight="2":::
:::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/6.x/BookStoreApi/Models/Book.cs" id="snippet_UsingSystemTextJsonSerialization":::
:::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.

Expand All @@ -333,7 +333,7 @@ To satisfy the preceding requirements, make the following changes:

## Additional resources

* [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/tutorials/first-mongo-app/samples/8.x/BookStoreApi) ([how to download](xref:index#how-to-download-a-sample))
* [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/tutorials/first-mongo-app/samples/9.x/BookStoreApi) ([how to download](xref:index#how-to-download-a-sample))
* <xref:web-api/index>
* <xref:web-api/action-return-types>
* [Create a web API with ASP.NET Core](/training/modules/build-web-api-aspnet-core/)
Expand Down
26 changes: 13 additions & 13 deletions aspnetcore/tutorials/first-mongo-app/includes/first-mongo-app8.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ Use the previously installed MongoDB Shell in the following steps to create a da
1. Add a *Models* directory to the project root.
1. Add a `Book` class to the *Models* directory with the following code:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples_snapshot/6.x/Book.cs":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples_snapshot/8.x/Book.cs":::

In the preceding class, the `Id` property is:

Expand All @@ -189,48 +189,48 @@ Use the previously installed MongoDB Shell in the following steps to create a da

1. Add the following database configuration values to `appsettings.json`:

:::code language="json" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/appsettings.json" highlight="2-6":::
:::code language="json" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/appsettings.json" highlight="2-6":::

1. Add a `BookStoreDatabaseSettings` class to the *Models* directory with the following code:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Models/BookStoreDatabaseSettings.cs":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/Models/BookStoreDatabaseSettings.cs":::

The preceding `BookStoreDatabaseSettings` class is used to store the `appsettings.json` file's `BookStoreDatabase` property values. The JSON and C# property names are named identically to ease the mapping process.

1. Add the following highlighted code to `Program.cs`:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Program.cs" id="snippet_BookStoreDatabaseSettings" highlight="4-5":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/Program.cs" id="snippet_BookStoreDatabaseSettings" highlight="4-5":::

In the preceding code, the configuration instance to which the `appsettings.json` file's `BookStoreDatabase` section binds is registered in the Dependency Injection (DI) container. For example, the `BookStoreDatabaseSettings` object's `ConnectionString` property is populated with the `BookStoreDatabase:ConnectionString` property in `appsettings.json`.

1. Add the following code to the top of `Program.cs` to resolve the `BookStoreDatabaseSettings` reference:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Program.cs" id="snippet_UsingModels":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/Program.cs" id="snippet_UsingModels":::

## Add a CRUD operations service

1. Add a *Services* directory to the project root.
1. Add a `BooksService` class to the *Services* directory with the following code:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Services/BooksService.cs" id="snippet_File":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/Services/BooksService.cs" id="snippet_File":::

In the preceding code, a `BookStoreDatabaseSettings` instance is retrieved from DI via constructor injection. This technique provides access to the `appsettings.json` configuration values that were added in the [Add a configuration model](#add-a-configuration-model) section.

1. Add the following highlighted code to `Program.cs`:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Program.cs" id="snippet_BooksService" highlight="7":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/Program.cs" id="snippet_BooksService" highlight="7":::

In the preceding code, the `BooksService` class is registered with DI to support constructor injection in consuming classes. The singleton service lifetime is most appropriate because `BooksService` takes a direct dependency on `MongoClient`. Per the official [Mongo Client reuse guidelines](https://mongodb.github.io/mongo-csharp-driver/2.14/reference/driver/connecting/#re-use), `MongoClient` should be registered in DI with a singleton service lifetime.

1. Add the following code to the top of `Program.cs` to resolve the `BooksService` reference:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Program.cs" id="snippet_UsingServices":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/Program.cs" id="snippet_UsingServices":::

The `BooksService` class uses the following `MongoDB.Driver` members to run CRUD operations against the database:

* [MongoClient](https://mongodb.github.io/mongo-csharp-driver/2.14/apidocs/html/T_MongoDB_Driver_MongoClient.htm): Reads the server instance for running database operations. The constructor of this class is provided in the MongoDB connection string:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Services/BooksService.cs" id="snippet_ctor" highlight="4-5":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/Services/BooksService.cs" id="snippet_ctor" highlight="4-5":::

* [IMongoDatabase](https://mongodb.github.io/mongo-csharp-driver/2.14/apidocs/html/T_MongoDB_Driver_IMongoDatabase.htm): Represents the Mongo database for running operations. This tutorial uses the generic [GetCollection\<TDocument>(collection)](https://mongodb.github.io/mongo-csharp-driver/2.14/apidocs/html/M_MongoDB_Driver_IMongoDatabase_GetCollection__1.htm) method on the interface to gain access to data in a specific collection. Run CRUD operations against the collection after this method is called. In the `GetCollection<TDocument>(collection)` method call:

Expand All @@ -248,7 +248,7 @@ The `BooksService` class uses the following `MongoDB.Driver` members to run CRUD

Add a `BooksController` class to the *Controllers* directory with the following code:

:::code language="csharp" source="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Controllers/BooksController.cs":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.x/BookStoreApi/Controllers/BooksController.cs":::

The preceding web API controller:

Expand Down Expand Up @@ -304,19 +304,19 @@ 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="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Program.cs" id="snippet_AddControllers" highlight="10-11":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.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="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Models/Book.cs" id="snippet_BookName" highlight="2":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.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="~/tutorials/first-mongo-app/samples/6.x/BookStoreApi/Models/Book.cs" id="snippet_UsingSystemTextJsonSerialization":::
:::code language="csharp" source="~/tutorials/first-mongo-app/samples/8.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.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
<PackageReference Include="MongoDB.Driver" Version="3.3.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace BookStoreApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;

public BooksController(BooksService booksService) =>
_booksService = booksService;

[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();

[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);

if (book is null)
{
return NotFound();
}

return book;
}

[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);

return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}

[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);

if (book is null)
{
return NotFound();
}

updatedBook.Id = book.Id;

await _booksService.UpdateAsync(id, updatedBook);

return NoContent();
}

[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);

if (book is null)
{
return NotFound();
}

await _booksService.RemoveAsync(id);

return NoContent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Microsoft.AspNetCore.Mvc;

namespace BookStoreApi.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

private readonly ILogger<WeatherForecastController> _logger;

public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}

[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
Loading