How to create a Web API with ASP.NET and MongoDB

techwithpat

Patrick Tshibanda

Posted on December 19, 2021

How to create a Web API with ASP.NET and MongoDB

In this tutorial, you will learn how to create a Web API with ASP.NET and MongoDB. We will create an API that allows CRUD operations on a movie database.

What is MongoDB?

MongoDB is a document-based NoSQL database. Unlike a relational database, which stores data in tables, MongoDB stores data as documents that are organized into collections.

Tools

Creating the database

I’m going to work with MongoDB on my local computer. To install an instance of the MongoDB server follow the link below.

Install MongoDB

If you don't want to use MongoDB on your local machine, you can always use MongoDB Atlas. MongoDB Atlas is a database as a service, and you can try it for free.

  1. Launch MongoDB Compass.
  2. Click on the "Connect" button to connect to your local server.
  3. Once connected to the server, click on the Create Database button to create a new database.
  4. In the dialog, set the database name to MoviesDb and set the collection name to MoviesCollection.
  5. Click on Create Database button to generate the database.

Creating the ASP.NET Application

  1. Launch Visual Studio 2022.
  2. Go to file -> new -> Project.
  3. Select ASP.NET Empty template, then click on the Next button.
  4. Set the project's name to MoviesAPI.
  5. Select .NET 6 as the framework and unselect configure with HTTPS then click on the Create button to generate the project.

Installing the MongoDB .NET driver

This is the official .NET driver for MongoDB, it will help connect to MongoDB.

  1. Open the NuGet Package Manager UI in Visual Studio.
  2. Search for MongoDB.Driver, select and install.

Configuration

  1. To connect to MongoDB, we will need some details like the connection string, the database name, and the collection name. We will store these details in the application configuration file.

    "MoviesDatabaseSettings": {
      "ConnectionString": "Your connection string to MongoDB",
      "DatabaseName": "MoviesDb",
      "MoviesCollectionName": "Movies"
    }
    
    

💡 To get the connection string for your database, disconnect from MongoDB Compass, and the connection string will be displayed on the home window of the application.

  1. To read this section in the application, we will use the options pattern. Add a new class named MoviesDatabaseSettings.

    public class MoviesDatabaseSettings
    {
        public string ConnectionString { get; set; } = string.Empty;
        public string DatabaseName { get; set; } = string.Empty;
        public string MoviesCollectionName { get; set; } = string.Empty;
    }
    
    

    ASP.NET will map the section "MoviesDatabaseSettings" to this class.

  2. In program.cs, after a WebApplication is instantiated, we register the MoviesDatabaseSettings class with the dependency injection container.

    builder.Services.Configure<MoviesDatabaseSettings>(builder.Configuration.GetSection("MoviesDatabaseSettings"));
    
    

    Make sure, you install the following Nuget package: Microsoft.Extensions.Options

Creating the model

Add a new class like the one below:

 public class Movie
 {
     [BsonId]
     [BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]
     public string Id { get; set; }
     public string Title { get; set; }
     public int Year { get; set; }
     public string Summary { get; set; } = null;
     public List<string> Actors { get; set; }
 }

Enter fullscreen mode Exit fullscreen mode
  • The Id property is decorated with the BsonId attribute to mark it as the primary key.
  • MongoDB stores the primary key in an ObjectId structure, to tell MongoDB that it needs to convert from string to ObjectId, the Id property is also decorated with the attribute BsonRepresentation.

Creating CRUD operations in a service

  1. Add a new class, paste the following code:

    public class MoviesService
    {
        private readonly IMongoCollection<Movie> _movies;
    
        public MoviesService(IOptions<MoviesDatabaseSettings> options)
        {
            var mongoClient = new MongoClient(options.Value.ConnectionString);
    
            _movies = mongoClient.GetDatabase(options.Value.DatabaseName)
                .GetCollection<Movie>(options.Value.MoviesCollectionName);
        }
    
        public async Task<List<Movie>> Get() =>
            await _movies.Find(_ => true).ToListAsync();
    
        public async Task<Movie> Get(string id) =>
            await _movies.Find(m => m.Id == id).FirstOrDefaultAsync();
    
        public async Task Create(Movie newMovie) =>
            await _movies.InsertOneAsync(newMovie);
    
        public async Task Update(string id, Movie updateMovie) =>
            await _movies.ReplaceOneAsync(m => m.Id == id, updateMovie);
    
        public async Task Remove(string id) =>
            await _movies.DeleteOneAsync(m => m.Id == id);
    }
    
    

    MongoClient is responsible for running database operations.

  2. Register the service with the dependency injection container.

    builder.Services.AddSingleton<MoviesService>();
    
    

    MoviesService is registered as a singleton because the service depends on the MongoClient, it is recommended to use the MongoClient as a singleton.

Creating endpoints for CRUD operations

Update the program.cs to look like this:

using MoviesAPI.Data;

var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<MoviesDatabaseSettings>(builder.Configuration.GetSection("MoviesDatabaseSettings"));
builder.Services.AddSingleton<MoviesService>();
var app = builder.Build();

app.MapGet("/", () => "Movies API!");

app.MapGet("/api/movies", async(MoviesService moviesService) => await moviesService.Get());

app.MapGet("/api/movies/{id}", async(MoviesService moviesService, string id) =>
{
    var movie = await moviesService.Get(id);
    return movie is null ? Results.NotFound() : Results.Ok(movie);
});

app.MapPost("/api/movies", async (MoviesService moviesService, Movie movie) =>
{
    await moviesService.Create(movie);
    return Results.Ok();
});

app.MapPut("/api/movies/{id}", async(MoviesService moviesService, string id, Movie updatedMovie) =>
{
    var movie = await moviesService.Get(id);
    if (movie is null) return Results.NotFound();

    updatedMovie.Id = movie.Id;
    await moviesService.Update(id, updatedMovie);

    return Results.NoContent();
});

app.MapDelete("/api/movies/{id}", async (MoviesService moviesService, string id) =>
{
    var movie = await moviesService.Get(id);
    if (movie is null) return Results.NotFound();

    await moviesService.Remove(movie.Id);

    return Results.NoContent();
});

app.Run();

Enter fullscreen mode Exit fullscreen mode

Creating, Reading, Updating, and deleting actions will be mapped to HTTP verbs such as POST, GET, PUT, and DELETE.
I am using the Minimal API syntax to create each endpoint. For an HTTP verb, We need to declare a route and a route handler that will handle a request to the route. Because we registered the MoviesService with the dependency injection container, it can be injected in each route handler.

Testing the API

If you want to add a new movie for instance.

  1. Start Debugging the application or press F5.
  2. Copy the URL displayed in the web browser.
  3. Launch POSTMAN.
  4. Create a new request then select POST as HTTP verb.
  5. In the address bar, paste the URL then add "/api/movies".
  6. In the Body section, paste the following json as the payload.
    {
        "Title":  "The Shawshank Redemption",
        "Year":  1994,
        "Summary":  "Banker Andy Dufresne is arrested for killing his wife and her lover. After a hard adjustment, he tries to improve the conditions of the prison and to give hope to his companions.",
        "Actors":  ["tim robbins","morgan freeman"]
    }

Enter fullscreen mode Exit fullscreen mode
  1. Click on the SEND button.
  2. You should get a 200 status code as the response.

Happy coding !!!

Here's the tutorial in video:

💖 💪 🙅 🚩
techwithpat
Patrick Tshibanda

Posted on December 19, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related