title | author | <!-- author | description | monikerRange | ms.author | ms.custom | ms.date | uid |
---|---|---|---|---|---|---|---|---|
Create a web API with ASP.NET Core and MongoDB |
wadepickett |
prkhandelwal --> |
This tutorial demonstrates how to create an ASP.NET Core web API using a MongoDB NoSQL database. |
>= aspnetcore-3.1 |
wpickett |
mvc, engagement-fy23 |
04/17/2024 |
tutorials/first-mongo-app |
By Pratik Khandelwal and Scott Addie
:::moniker range=">= aspnetcore-8.0"
This tutorial creates a web API that runs Create, Read, Update, and Delete (CRUD) operations on a MongoDB NoSQL database.
In this tutorial, you learn how to:
[!div class="checklist"]
- Configure MongoDB
- Create a MongoDB database
- Define a MongoDB collection and schema
- Perform MongoDB CRUD operations from a web API
- Customize JSON serialization
Enable MongoDB and MongoDB Shell access from anywhere on the development machine (Windows/Linux/macOS):
-
Download and Install MongoDB Shell:
- macOS/Linux: Choose a directory to extract the MongoDB Shell to. Add the resulting path for
mongosh
to thePATH
environment variable. - Windows: MongoDB Shell (mongosh.exe) is installed at C:\Users<user>\AppData\Local\Programs\mongosh. Add the resulting path for
mongosh.exe
to thePATH
environment variable.
- macOS/Linux: Choose a directory to extract the MongoDB Shell to. Add the resulting path for
-
Download and Install MongoDB:
- macOS/Linux: Verify the directory that MongoDB was installed at, usually in /usr/local/mongodb. Add the resulting path for
mongodb
to thePATH
environment variable. - Windows: MongoDB is installed at C:\Program Files\MongoDB by default. Add C:\Program Files\MongoDB\Server\<version_number>\bin to the
PATH
environment variable.
- macOS/Linux: Verify the directory that MongoDB was installed at, usually in /usr/local/mongodb. Add the resulting path for
-
Choose a Data Storage Directory: Select a directory on your development machine for storing data. Create the directory if it doesn't exist. The MongoDB Shell doesn't create new directories:
- macOS/Linux: For example,
/usr/local/var/mongodb
. - Windows: For example,
C:\\BooksData
.
- macOS/Linux: For example,
-
In the OS command shell (not the MongoDB Shell), use the following command to connect to MongoDB on default port 27017. Replace
<data_directory_path>
with the directory chosen in the previous step.mongod --dbpath <data_directory_path>
Use the previously installed MongoDB Shell in the following steps to create a database, make collections, and store documents. For more information on MongoDB Shell commands, see mongosh
.
-
Open a MongoDB command shell instance by launching
mongosh.exe
. -
In the command shell, connect to the default test database by running the following command:
mongosh
-
Run the following command in the command shell:
use BookStore
A database named BookStore is created if it doesn't already exist. If the database does exist, its connection is opened for transactions.
-
Create a
Books
collection using following command:db.createCollection('Books')
The following result is displayed:
{ "ok" : 1 }
-
Define a schema for the
Books
collection and insert two documents using the following command:db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
A result similar to the following is displayed:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
[!NOTE] The
ObjectId
s shown in the preceding result won't match those shown in the command shell. -
View the documents in the database using the following command:
db.Books.find().pretty()
A result similar to the following is displayed:
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
The schema adds an autogenerated
_id
property of typeObjectId
for each document.
-
Go to File > New > Project.
-
Select the ASP.NET Core Web API project type, and select Next.
-
Name the project BookStoreApi, and select Next.
-
Select the .NET 8.0 (Long Term support) framework and select Create.
-
In the Package Manager Console window, navigate to the project root. Run the following command to install the .NET driver for MongoDB:
Install-Package MongoDB.Driver
-
Run the following commands in a command shell:
dotnet new webapi -o BookStoreApi code BookStoreApi
The preceding commands generate a new ASP.NET Core web API project and then open the project in Visual Studio Code.
-
Once the OmniSharp server starts up, a dialog asks Required assets to build and debug are missing from 'BookStoreApi'. Add them?. Select Yes.
-
Open the Integrated Terminal and run the following command to install the .NET driver for MongoDB:
dotnet add package MongoDB.Driver
- Select File > New Project....
- Select Web and Console > App from the sidebar.
- Select the ASP.NET Core > API C# project template, and select Next.
- Select .NET 8.0 from the Target Framework drop-down list, and select Next.
- Enter BookStoreApi for the Project Name, and select Create.
- In the Solution pad, right-click the project's Dependencies node and select Manage NuGet Packages.
- Enter MongoDB.Driver in the search box, select the MongoDB.Driver package, and select Add Package.
- Select the Accept button in the License Acceptance dialog.
-
Add a Models directory to the project root.
-
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":::
In the preceding class, the
Id
property is:- Required for mapping the Common Language Runtime (CLR) object to the MongoDB collection.
- Annotated with
[BsonId]
to make this property the document's primary key. - Annotated with
[BsonRepresentation(BsonType.ObjectId)]
to allow passing the parameter as typestring
instead of an ObjectId structure. Mongo handles the conversion fromstring
toObjectId
.
The
BookName
property is annotated with the[BsonElement]
attribute. The attribute's value ofName
represents the property name in the MongoDB collection.
-
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":::
-
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":::
The preceding
BookStoreDatabaseSettings
class is used to store theappsettings.json
file'sBookStoreDatabase
property values. The JSON and C# property names are named identically to ease the mapping process. -
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":::
In the preceding code, the configuration instance to which the
appsettings.json
file'sBookStoreDatabase
section binds is registered in the Dependency Injection (DI) container. For example, theBookStoreDatabaseSettings
object'sConnectionString
property is populated with theBookStoreDatabase:ConnectionString
property inappsettings.json
. -
Add the following code to the top of
Program.cs
to resolve theBookStoreDatabaseSettings
reference::::code language="csharp" source="first-mongo-app/samples/6.x/BookStoreApi/Program.cs" id="snippet_UsingModels":::
-
Add a Services directory to the project root.
-
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":::
In the preceding code, a
BookStoreDatabaseSettings
instance is retrieved from DI via constructor injection. This technique provides access to theappsettings.json
configuration values that were added in the Add a configuration model section. -
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":::
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 becauseBooksService
takes a direct dependency onMongoClient
. Per the official Mongo Client reuse guidelines,MongoClient
should be registered in DI with a singleton service lifetime. -
Add the following code to the top of
Program.cs
to resolve theBooksService
reference::::code language="csharp" source="first-mongo-app/samples/6.x/BookStoreApi/Program.cs" id="snippet_UsingServices":::
The BooksService
class uses the following MongoDB.Driver
members to run CRUD operations against the database:
-
MongoClient: 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":::
-
IMongoDatabase: Represents the Mongo database for running operations. This tutorial uses the generic GetCollection<TDocument>(collection) 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:collection
represents the collection name.TDocument
represents the CLR object type stored in the collection.
GetCollection<TDocument>(collection)
returns a MongoCollection object representing the collection. In this tutorial, the following methods are invoked on the collection:
- DeleteOneAsync: Deletes a single document matching the provided search criteria.
- Find<TDocument>: Returns all documents in the collection matching the provided search criteria.
- InsertOneAsync: Inserts the provided object as a new document in the collection.
- ReplaceOneAsync: Replaces the single document matching the provided search criteria with the provided object.
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":::
The preceding web API controller:
- Uses the
BooksService
class to run CRUD operations. - 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 response. Status code 201 is the standard response for an HTTP POST method that creates a new resource on the server.CreatedAtAction
also adds aLocation
header to the response. TheLocation
header specifies the URI of the newly created book.
-
Build and run the app.
-
Navigate to
https://localhost:<port>/api/books
, where<port>
is the automatically assigned port number for the app, to test the controller's parameterlessGet
action method, select Try it out > Execute. A JSON response similar to the following is displayed:[ { "id": "61a6058e6c43f32854e51f51", "bookName": "Design Patterns", "price": 54.93, "category": "Computers", "author": "Ralph Johnson" }, { "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" } ]
-
Navigate to
https://localhost:<port>/api/books/{id here}
to test the controller's overloadedGet
action method. A JSON response similar to the following is displayed:{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
There are two details to change about the JSON responses returned in the 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 asName
.
To satisfy the preceding requirements, make the following changes:
-
In
Program.cs
, chain the following highlighted code on to theAddControllers
method call::::code language="csharp" source="first-mongo-app/samples/6.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'sAuthor
property serializes asAuthor
instead ofauthor
. -
In
Models/Book.cs
, annotate theBookName
property with the[JsonPropertyName]
attribute::::code language="csharp" source="first-mongo-app/samples/6.x/BookStoreApi/Models/Book.cs" id="snippet_BookName" highlight="2":::
The
[JsonPropertyName]
attribute's value ofName
represents the property name in the web API's serialized JSON response. -
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":::
-
Repeat the steps defined in the Test the web API section. Notice the difference in JSON property names.
- View or download sample code (how to download)
- xref:web-api/index
- xref:web-api/action-return-types
- Create a web API with ASP.NET Core
:::moniker-end