.NET/C#
  • ASP.NET Core Overview
  • ASP.NET Core API tutorial
    • How to create ASP.NET Core C# API tutorial
      • launchSettings
      • Install swagger
        • Swagger best practices
      • Run the app
      • Fix CORS problem
      • Add AutoMapper
      • Add JWT reference
      • Add .gitignore
      • Basic structure & EF Core
      • AddSingleton
    • Loading Related Entities
  • Unit test controller logic in ASP.NET Core
    • Unit testing controllers
  • .NET Q&A
    • dotnet try
    • LINQ
      • LINQ Query Syntax
      • Lambda Expression
      • Standard Query Operators
  • .NET C# Interview questions
    • C# - .NET interview questions and answers [Part 1]
    • C# - .NET interview questions and answers [Part 2]
    • C# Interview questions [Part 3] General questions
  • C#
    • Object-Oriented Programming (Principles)
      • N-tier architecture style
      • Command and Query Responsibility Segregation (CQRS) pattern
      • Project architecture
    • C# Advanced review
      • Implicit typing
      • Generics
      • Attributes
      • Reflection
      • Delegates
      • Anonymous Methods and Lambda Expressions
      • Events
      • Ref vs Out
      • Task
        • TaskFactory Class
  • MySQL
    • MySQL Lerning
      • SELECT
      • ORDER BY
      • WHERE
      • DISTINCT
      • IN
      • BETWEEN
      • Join
      • INNER JOIN
      • LEFT JOIN
      • RIGHT JOIN
      • GROUP BY
      • Subquery
      • UNION
    • Stored Procedures
      • CREATE PROCEDURE
  • Versioning API, MongoDB and ci-cd
    • Create a web API with ASP.NET Core and MongoDB
    • REST API versioning with ASP.NET Core
    • Design a CI/CD pipeline using Azure DevOps
      • Create a CI/CD pipeline for GitHub repo using Azure DevOps Starter
  • TFS & TFCV
    • What is Team Foundation Version Control
      • Develop and share your code in TFVC using Visual Studio
      • Suspend your work and manage your shelvesets
    • Newtonsoft Json.NET
      • Serializing and Deserializing JSON
  • MS-SQL
    • Quick tutorial
      • Add new column to a table
      • LEFT/RIGHT Reverse operator
      • Dates (Transact-SQL)
      • CAST and CONVERT (Transact-SQL)
      • Types of JOIN
      • Our first Left Outer Join
      • CROSS JOIN
Powered by GitBook
On this page
  • Prerequisites
  • Configure MongoDB
  • Create the ASP.NET Core web API project
  • Add an entity model
  • Add a configuration model
  • Add a CRUD operations service
  • Add a controller
  • Test the web API
  • Configure JSON serialization options

Was this helpful?

  1. Versioning API, MongoDB and ci-cd

Create a web API with ASP.NET Core and MongoDB

PreviousVersioning API, MongoDB and ci-cdNextREST API versioning with ASP.NET Core

Last updated 4 years ago

Was this helpful?

Prerequisites

  • with the ASP.NET and web development workload

Configure MongoDB

If using 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. This change enables MongoDB access from anywhere on your development machine.

Use the mongo Shell in the following steps to create a database, make collections, and store documents. For more information on mongo Shell commands, see .

  1. Choose a directory on your development machine for storing the data. For example, C:\BooksData on Windows. Create the directory if it doesn't exist. The mongo Shell doesn't create new directories.

  2. Open a command shell. Run the following command to connect to MongoDB on default port 27017. Remember to replace <data_directory_path> with the directory you chose in the previous step.

mongod --dbpath <data_directory_path>

3.Open another command shell instance. Connect to the default test database by running the following command:

mongo

4.Run the following in a command shell:

use BookstoreDb

If it doesn't already exist, a database named BookstoreDb is created. If the database does exist, its connection is opened for transactions.

5.Create a Books collection using following command:

db.createCollection('Books')

The following result is displayed:

{ "ok" : 1 }

6.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'}])

The following result is displayed:

{
  "acknowledged" : true,
  "insertedIds" : [
    ObjectId("5bfd996f7b8e48dc15ff215d"),
    ObjectId("5bfd996f7b8e48dc15ff215e")
  ]
}

7.View the documents in the database using the following command:

db.Books.find({}).pretty()

The following result is displayed:

{
  "_id" : ObjectId("5bfd996f7b8e48dc15ff215d"),
  "Name" : "Design Patterns",
  "Price" : 54.93,
  "Category" : "Computers",
  "Author" : "Ralph Johnson"
}
{
  "_id" : ObjectId("5bfd996f7b8e48dc15ff215e"),
  "Name" : "Clean Code",
  "Price" : 43.15,
  "Category" : "Computers",
  "Author" : "Robert C. Martin"
}

The schema adds an autogenerated _id property of type ObjectId for each document.

Create the ASP.NET Core web API project

  1. Go to File > New > Project.

  2. Select the ASP.NET Core Web Application project type, and select Next.

  3. Name the project BooksApi, and select Create.

  4. Select the .NET Core target framework and ASP.NET Core 3.0. Select the API project template, and select Create.

  5. Install-Package MongoDB.Driver -Version {VERSION}

Add an entity model

  1. Add a Models directory to the project root.

  2. Add a Book class to the Models directory with the following code:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace BooksApi.Models
{
    public class Book
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }

        [BsonElement("Name")]
        public string BookName { get; set; }

        public decimal Price { get; set; }

        public string Category { get; set; }

        public string Author { get; set; }
    }
}

In the preceding class, the Id property:

  • Is required for mapping the Common Language Runtime (CLR) object to the MongoDB collection.

Add a configuration model

Add the following database configuration values to appsettings.json:

{
  "BookstoreDatabaseSettings": {
    "BooksCollectionName": "Books",
    "ConnectionString": "mongodb://localhost:27017",
    "DatabaseName": "BookstoreDb"
  },
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}

Add a BookstoreDatabaseSettings.cs file to the Models directory with the following code:

namespace BooksApi.Models
{
    public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings
    {
        public string BooksCollectionName { get; set; }
        public string ConnectionString { get; set; }
        public string DatabaseName { get; set; }
    }

    public interface IBookstoreDatabaseSettings
    {
        string BooksCollectionName { get; set; }
        string ConnectionString { get; set; }
        string DatabaseName { get; set; }
    }
}

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

Add the following highlighted code to Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    // requires using Microsoft.Extensions.Options
    services.Configure<BookstoreDatabaseSettings>(
        Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

    services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
        sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

    services.AddControllers();
}

In the preceding code:

  • The configuration instance to which the appsettings.json file's BookstoreDatabaseSettings section binds is registered in the Dependency Injection (DI) container. For example, a BookstoreDatabaseSettings object's ConnectionString property is populated with the BookstoreDatabaseSettings:ConnectionString property in appsettings.json.

Add the following code to the top of Startup.cs to resolve the BookstoreDatabaseSettings and IBookstoreDatabaseSettings references:

using BooksApi.Models;

Add a CRUD operations service

  1. Add a Services directory to the project root.

  2. Add a BookService class to the Services directory with the following code:

using BooksApi.Models;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;

namespace BooksApi.Services
{
    public class BookService
    {
        private readonly IMongoCollection<Book> _books;

        public BookService(IBookstoreDatabaseSettings settings)
        {
            var client = new MongoClient(settings.ConnectionString);
            var database = client.GetDatabase(settings.DatabaseName);

            _books = database.GetCollection<Book>(settings.BooksCollectionName);
        }

        public List<Book> Get() =>
            _books.Find(book => true).ToList();

        public Book Get(string id) =>
            _books.Find<Book>(book => book.Id == id).FirstOrDefault();

        public Book Create(Book book)
        {
            _books.InsertOne(book);
            return book;
        }

        public void Update(string id, Book bookIn) =>
            _books.ReplaceOne(book => book.Id == id, bookIn);

        public void Remove(Book bookIn) =>
            _books.DeleteOne(book => book.Id == bookIn.Id);

        public void Remove(string id) => 
            _books.DeleteOne(book => book.Id == id);
    }
}

Add the following highlighted code to Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<BookstoreDatabaseSettings>(
        Configuration.GetSection(nameof(BookstoreDatabaseSettings)));

    services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
        sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);

    services.AddSingleton<BookService>();

    services.AddControllers();
}

Add the following code to the top of Startup.cs to resolve the BookService reference:

using BooksApi.Services;

The BookService class uses the following MongoDB.Driver members to perform CRUD operations against the database:

public BookService(IBookstoreDatabaseSettings settings)
{
    var client = new MongoClient(settings.ConnectionString);
    var database = client.GetDatabase(settings.DatabaseName);

    _books = database.GetCollection<Book>(settings.BooksCollectionName);
}
  • collection represents the collection name.

  • TDocument represents the CLR object type stored in the collection.

Add a controller

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

using BooksApi.Models;
using BooksApi.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace BooksApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BooksController : ControllerBase
    {
        private readonly BookService _bookService;

        public BooksController(BookService bookService)
        {
            _bookService = bookService;
        }

        [HttpGet]
        public ActionResult<List<Book>> Get() =>
            _bookService.Get();

        [HttpGet("{id:length(24)}", Name = "GetBook")]
        public ActionResult<Book> Get(string id)
        {
            var book = _bookService.Get(id);

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

            return book;
        }

        [HttpPost]
        public ActionResult<Book> Create(Book book)
        {
            _bookService.Create(book);

            return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);
        }

        [HttpPut("{id:length(24)}")]
        public IActionResult Update(string id, Book bookIn)
        {
            var book = _bookService.Get(id);

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

            _bookService.Update(id, bookIn);

            return NoContent();
        }

        [HttpDelete("{id:length(24)}")]
        public IActionResult Delete(string id)
        {
            var book = _bookService.Get(id);

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

            _bookService.Remove(book.Id);

            return NoContent();
        }
    }
}
  • Uses the BookService class to perform CRUD operations.

  • Contains action methods to support GET, POST, PUT, and DELETE HTTP requests.

Test the web API

  1. Build and run the app.

  2. Navigate to http://localhost:<port>/api/books to test the controller's parameterless Get action method. The following JSON response is displayed:

[
  {
    "id":"5bfd996f7b8e48dc15ff215d",
    "bookName":"Design Patterns",
    "price":54.93,
    "category":"Computers",
    "author":"Ralph Johnson"
  },
  {
    "id":"5bfd996f7b8e48dc15ff215e",
    "bookName":"Clean Code",
    "price":43.15,
    "category":"Computers",
    "author":"Robert C. Martin"
  }
]

Navigate to http://localhost:<port>/api/books/{id here} to test the controller's overloaded Get action method. The following JSON response is displayed:

{
  "id":"{ID}",
  "bookName":"Clean Code",
  "price":43.15,
  "category":"Computers",
  "author":"Robert C. Martin"
}

Configure JSON serialization options

  • 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 Startup.ConfigureServices, chain the following highlighted code on to the AddControllers method call:

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<BookstoreDatabaseSettings>(
            Configuration.GetSection(nameof(BookstoreDatabaseSettings)));
    
        services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
            sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);
    
        services.AddSingleton<BookService>();
    
        services.AddControllers()
            .AddNewtonsoftJson(options => options.UseMemberCasing());
    }

    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.

  2. [BsonElement("Name")]
    [JsonProperty("Name")]
    public string BookName { get; set; }

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

  3. Add the following code to the top of Models/Book.cs to resolve the [JsonProperty] attribute reference:C#Copy

    using Newtonsoft.Json;

Visit the to determine the latest stable version of the .NET driver for MongoDB. In the Package Manager Console window, navigate to the project root. Run the following command to install the .NET driver for MongoDB

Is annotated with to designate this property as the document's primary key.

Is annotated with to allow passing the parameter as type string instead of an structure. Mongo handles the conversion from string to ObjectId.

The BookName property is annotated with the attribute. The attribute's value of Name represents the property name in the MongoDB collection.

The IBookstoreDatabaseSettings interface is registered in DI with a singleton . When injected, the interface instance resolves to a BookstoreDatabaseSettings object.

In the preceding code, an IBookstoreDatabaseSettings instance is retrieved from DI via constructor injection. This technique provides access to the appsettings.json configuration values that were added in the section.

In the preceding code, the BookService class is registered with DI to support constructor injection in consuming classes. The singleton service lifetime is most appropriate because BookService takes a direct dependency on MongoClient. Per the official , MongoClient should be registered in DI with a singleton service lifetime.

: Reads the server instance for performing database operations. The constructor of this class is provided the MongoDB connection string:

: Represents the Mongo database for performing operations. This tutorial uses the generic method on the interface to gain access to data in a specific collection. Perform CRUD operations against the collection after this method is called. In the GetCollection<TDocument>(collection) method call:

GetCollection<TDocument>(collection) returns a object representing the collection. In this tutorial, the following methods are invoked on the collection:

: Deletes a single document matching the provided search criteria.

: Returns all documents in the collection matching the provided search criteria.

: Inserts the provided object as a new document in the collection.

: Replaces the single document matching the provided search criteria with the provided object.

Calls in the Create action method to return an response. Status code 201 is the standard response for an HTTP POST method that creates a new resource on the server. CreatedAtRoute also adds a Location header to the response. The Location header specifies the URI of the newly created book.

There are two details to change about the JSON responses returned in the section:

JSON.NET has been removed from ASP.NET shared framework. Add a package reference to .

In Models/Book.cs, annotate the BookName property with the following attribute:C#Copy

Repeat the steps defined in the section. Notice the difference in JSON property names.

.NET Core SDK 3.0 or later
Visual Studio 2019
MongoDB
Working with the mongo Shell
NuGet Gallery: MongoDB.Driver
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
ObjectId
[BsonElement]
service lifetime
Add a configuration model
Mongo Client reuse guidelines
MongoClient
IMongoDatabase
GetCollection<TDocument>(collection)
MongoCollection
DeleteOne
Find<TDocument>
InsertOne
ReplaceOne
CreatedAtRoute
HTTP 201
Test the web API
Microsoft.AspNetCore.Mvc.NewtonsoftJson
[JsonProperty]
Test the web API