Explore Developer Center's New Chatbot! MongoDB AI Chatbot can be accessed at the top of your navigation to answer all your MongoDB questions.

Learn why MongoDB was selected as a leader in the 2024 Gartner® Magic Quadrant™
MongoDB Developer
C#
plus
Sign in to follow topics
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Languageschevron-right
C#chevron-right

Create a RESTful API With .NET Core and MongoDB

Nic Raboy8 min read • Published Feb 08, 2022 • Updated Sep 11, 2024
.NETMongoDBC#
Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
If you've been keeping up with my development content, you'll remember that I recently wrote Build Your First .NET Core Application with MongoDB Atlas, which focused on building a console application that integrated with MongoDB. While there is a fit for MongoDB in console applications, many developers are going to find it more valuable in web applications.
In this tutorial, we're going to expand upon the previous and create a RESTful API with endpoints that perform basic create, read, update, and delete (CRUD) operations against MongoDB Atlas.

The Requirements

To be successful with this tutorial, you'll need to have a few things taken care of first:
  • A deployed and configured MongoDB Atlas cluster, M0 or higher
  • .NET Core 6+
We won't go through the steps of deploying a MongoDB Atlas cluster or configuring it with user and network rules. If this is something you need help with, check out a previous tutorial that was published on the topic.
We'll be using .NET Core 6.0 in this tutorial, but other versions may still work. Just take the version into consideration before continuing.

Create a Web API Project with the .NET Core CLI

To kick things off, we're going to create a fresh .NET Core project using the web application template that Microsoft offers. To do this, execute the following commands from the CLI:
1dotnet new webapi -o MongoExample
2cd MongoExample
3dotnet add package MongoDB.Driver
The above commands will create a new web application project for .NET Core and install the latest MongoDB driver. We'll be left with some boilerplate files as part of the template, but we can remove them.
Inside the project, delete any file related to WeatherForecast and similar.

Designing a Document Model and Database Service within .NET Core

Before we start designing each of the RESTful API endpoints with .NET Core, we need to create and configure our MongoDB service and define the data model for our API.
We'll start by working on our MongoDB service, which will be responsible for establishing our connection and directly working with documents within MongoDB. Within the project, create "Models/MongoDBSettings.cs" and add the following C# code:
1namespace MongoExample.Models;
2
3public class MongoDBSettings {
4
5 public string ConnectionURI { get; set; } = null!;
6 public string DatabaseName { get; set; } = null!;
7 public string CollectionName { get; set; } = null!;
8
9}
The above MongoDBSettings class will hold information about our connection, the database name, and the collection name. The data we plan to store in these class fields will be found in the project's "appsettings.json" file. Open it and add the following:
1{
2 "Logging": {
3 "LogLevel": {
4 "Default": "Information",
5 "Microsoft.AspNetCore": "Warning"
6 }
7 },
8 "AllowedHosts": "*",
9 "MongoDB": {
10 "ConnectionURI": "ATLAS_URI_HERE",
11 "DatabaseName": "sample_mflix",
12 "CollectionName": "playlist"
13 }
14}
Specifically take note of the MongoDB field. Just like with the previous example project, we'll be using the "sample_mflix" database and the "playlist" collection. You'll need to grab the ConnectionURI string from your MongoDB Atlas Dashboard.
MongoDB Atlas Connection String
MongoDB Atlas Connection String
With the settings in place, we can move onto creating the service.
Create "Services/MongoDBService.cs" within your project and add the following:
1using MongoExample.Models;
2using Microsoft.Extensions.Options;
3using MongoDB.Driver;
4using MongoDB.Bson;
5
6namespace MongoExample.Services;
7
8public class MongoDBService {
9
10 private readonly IMongoCollection<Playlist> _playlistCollection;
11
12 public MongoDBService(IOptions<MongoDBSettings> mongoDBSettings) {
13 MongoClient client = new MongoClient(mongoDBSettings.Value.ConnectionURI);
14 IMongoDatabase database = client.GetDatabase(mongoDBSettings.Value.DatabaseName);
15 _playlistCollection = database.GetCollection<Playlist>(mongoDBSettings.Value.CollectionName);
16 }
17
18 public async Task<List<Playlist>> GetAsync() { }
19 public async Task CreateAsync(Playlist playlist) { }
20 public async Task AddToPlaylistAsync(string id, string movieId) {}
21 public async Task DeleteAsync(string id) { }
22
23}
In the above code, each of the asynchronous functions were left blank on purpose. We'll be populating those functions as we create our endpoints. Instead, make note of the constructor method and how we're taking the passed settings that we saw in our "appsettings.json" file and setting them to variables. In the end, the only variable we'll ever interact with for this example is the _playlistCollection variable.
With the service available, we need to connect it to the application. Open the project's "Program.cs" file and add the following at the top:
1using MongoExample.Models;
2using MongoExample.Services;
3
4var builder = WebApplication.CreateBuilder(args);
5
6builder.Services.Configure<MongoDBSettings>(builder.Configuration.GetSection("MongoDB"));
7builder.Services.AddSingleton<MongoDBService>();
You'll likely already have the builder variable in your code because it was part of the boilerplate project, so don't add it twice. What you'll need to add near the top is an import to your custom models and services as well as configuring the service.
Remember the MongoDB field in the "appsettings.json" file? That is the section that the GetSection function is pulling from. That information is passed into the singleton service that we created.
With the service created and working, with the exception of the incomplete asynchronous functions, we can focus on creating a data model for our collection.
Create "Models/Playlist.cs" and add the following C# code:
1using MongoDB.Bson;
2using MongoDB.Bson.Serialization.Attributes;
3using System.Text.Json.Serialization;
4
5namespace MongoExample.Models;
6
7public class Playlist {
8
9 [BsonId]
10 [BsonRepresentation(BsonType.ObjectId)]
11 public string? Id { get; set; }
12
13 public string username { get; set; } = null!;
14
15 [BsonElement("items")]
16 [JsonPropertyName("items")]
17 public List<string> movieIds { get; set; } = null!;
18
19}
There are a few things happening in the above class that take it from a standard C# class to something that can integrate seamlessly into a MongoDB document.
First, you might notice the following:
1[BsonId]
2[BsonRepresentation(BsonType.ObjectId)]
3public string? Id { get; set; }
We're saying that the Id field is to be represented as an ObjectId in BSON and the _id field within MongoDB. However, when we work with it locally in our application, it will be a string.
The next thing you'll notice is the following:
1[BsonElement("items")]
2[JsonPropertyName("items")]
3public List<string> movieIds { get; set; } = null!;
Even though we plan to work with movieIds within our C# application, in MongoDB, the field will be known as items and when sending or receiving JSON, the field will also be known as items instead of movieIds.
You don't need to define custom mappings if you plan to have your local class field match the document field directly. Take the username field in our example. It has no custom mappings, so it will be username in C#, username in JSON, and username in MongoDB.
Just like that, we have a MongoDB service and document model for our collection to work with for .NET Core.

Building CRUD Endpoints that Interact with MongoDB Using .NET Core

When building CRUD endpoints for this project, we'll need to bounce between two different locations within our project. We'll need to define the endpoint within a controller and do the work within our service.
Create "Controllers/PlaylistController.cs" and add the following code:
1using System;
2using Microsoft.AspNetCore.Mvc;
3using MongoExample.Services;
4using MongoExample.Models;
5
6namespace MongoExample.Controllers;
7
8[Controller]
9[Route("api/[controller]")]
10public class PlaylistController: Controller {
11
12 private readonly MongoDBService _mongoDBService;
13
14 public PlaylistController(MongoDBService mongoDBService) {
15 _mongoDBService = mongoDBService;
16 }
17
18 [HttpGet]
19 public async Task<List<Playlist>> Get() {}
20
21 [HttpPost]
22 public async Task<IActionResult> Post([FromBody] Playlist playlist) {}
23
24 [HttpPut("{id}")]
25 public async Task<IActionResult> AddToPlaylist(string id, [FromBody] string movieId) {}
26
27 [HttpDelete("{id}")]
28 public async Task<IActionResult> Delete(string id) {}
29
30}
In the above PlaylistController class, we have a constructor method that gains access to our singleton service class. Then we have a series of endpoints for this particular controller. We could add far more endpoints than this to our controller, but it's not necessary for this example.
Let's start with creating data through the POST endpoint. To do this, it's best to start in the "Services/MongoDBService.cs" file:
1public async Task CreateAsync(Playlist playlist) {
2 await _playlistCollection.InsertOneAsync(playlist);
3 return;
4}
We had set the _playlistCollection in the constructor method of the service, so we can now use the InsertOneAsync method, taking a passed Playlist variable and inserting it. Jumping back into the "Controllers/PlaylistController.cs," we can add the following:
1[HttpPost]
2public async Task<IActionResult> Post([FromBody] Playlist playlist) {
3 await _mongoDBService.CreateAsync(playlist);
4 return CreatedAtAction(nameof(Get), new { id = playlist.Id }, playlist);
5}
What we're saying is that when the endpoint is executed, we take the Playlist object from the request, something that .NET Core parses for us, and pass it to the CreateAsync function that we saw in the service. After the insert, we return some information about the interaction.
It's important to note that in this example project, we won't be validating any data flowing from HTTP requests.
Let's jump to the read operations.
Head back into the "Services/MongoDBService.cs" file and add the following function:
1public async Task<List<Playlist>> GetAsync() {
2 return await _playlistCollection.Find(new BsonDocument()).ToListAsync();
3}
The above Find operation will return all documents that exist in the collection. If you wanted to, you could make use of the FindOne or provide filter criteria to return only the data that you want. We'll explore filters shortly.
With the service function ready, add the following endpoint to the "Controllers/PlaylistController.cs" file:
1[HttpGet]
2public async Task<List<Playlist>> Get() {
3 return await _mongoDBService.GetAsync();
4}
Not so bad, right? We'll be doing the same thing for the other endpoints, more or less.
The next CRUD stage to take care of is the updating of data. Within the "Services/MongoDBService.cs" file, add the following function:
1public async Task AddToPlaylistAsync(string id, string movieId) {
2 FilterDefinition<Playlist> filter = Builders<Playlist>.Filter.Eq("Id", id);
3 UpdateDefinition<Playlist> update = Builders<Playlist>.Update.AddToSet<string>("movieIds", movieId);
4 await _playlistCollection.UpdateOneAsync(filter, update);
5 return;
6}
Rather than making changes to the entire document, we're planning on adding an item to our playlist and nothing more. To do this, we set up a match filter to determine which document or documents should receive the update. In this case, we're matching on the id which is going to be unique. Next, we're defining the update criteria, which is an AddToSet operation that will only add an item to the array if it doesn't already exist in the array.
The UpdateOneAsync method will only update one document even if the match filter returned more than one match.
In the "Controllers/PlaylistController.cs" file, add the following endpoint to pair with the AddToPlayListAsync function:
1[HttpPut("{id}")]
2public async Task<IActionResult> AddToPlaylist(string id, [FromBody] string movieId) {
3 await _mongoDBService.AddToPlaylistAsync(id, movieId);
4 return NoContent();
5}
In the above PUT endpoint, we are taking the id from the route parameters and the movieId from the request body and using them with the AddToPlaylistAsync function.
This brings us to our final part of the CRUD spectrum. We're going to handle deleting of data.
In the "Services/MongoDBService.cs" file, add the following function:
1public async Task DeleteAsync(string id) {
2 FilterDefinition<Playlist> filter = Builders<Playlist>.Filter.Eq("Id", id);
3 await _playlistCollection.DeleteOneAsync(filter);
4 return;
5}
The above function will delete a single document based on the filter criteria. The filter criteria, in this circumstance, is a match on the id which is always going to be unique. Your filters could be more extravagant if you wanted.
To bring it to an end, the endpoint for this function would look like the following in the "Controllers/PlaylistController.cs" file:
1[HttpDelete("{id}")]
2public async Task<IActionResult> Delete(string id) {
3 await _mongoDBService.DeleteAsync(id);
4 return NoContent();
5}
We only created four endpoints, but you could take everything we did and create 100 more if you wanted to. They would all use a similar strategy and can leverage everything that MongoDB has to offer.

Trying out the endpoints

Now you have the code implemented, you can now play around with the four RESTful API endpoints.
When you run the application, you should see a Swagger UI as below: Swagger page listing the CRUD endpoints from Playlist Controller
You can test this by clicking the "Try it out" button on each endpoint. It is easier to start with the /api/Playlist/ POST endpoint, to add some data to the database. The following can be used as dummy data:
1{
2 "username": "nraboy",
3 "items": [
4 "1234",
5 "5678"
6 ]
7}
Running this will insert that data and allow you to fetch that from the GET and use the generated id value to test the other endpoints.

Conclusion

You just saw how to create a simple four endpoint RESTful API using .NET Core and MongoDB. This was an expansion to the previous tutorial, which went over the same usage of MongoDB, but in a console application format rather than web application.
Like I mentioned, you can take the same strategy used here and apply it towards more endpoints, each doing something critical for your web application.
Got a question about the driver for .NET? Swing by the MongoDB Community Forums!

Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Tutorial

Using LINQ to Query MongoDB in a .NET Core Application


Jun 10, 2024 | 6 min read
Tutorial

Getting Started with Unity for Creating a 2D Game


Apr 02, 2024 | 9 min read
Tutorial

Sending and Requesting Data from MongoDB in a Unity Game


Sep 09, 2024 | 8 min read
Article

How to Set Up MongoDB Class Maps for C# for Optimal Query Performance and Storage Size


Aug 05, 2024 | 8 min read
Table of Contents