TRUNGTQ

Think Big, Act Small, Fail Fast and Learn Rapidly

NAVIGATION - SEARCH

MongoDB Admin UIs

Trang này giới thiệu rất nhiều về các tool quản trị UI cho MongoDB, tuy nhiên hiện tại mình chỉ quan tâm tới chú adminMongo.

adminMongo

adminMongo is an open source Web based administration user interface written with Node.js.

https://raw.githubusercontent.com/mrvautin/mrvautin.github.io/master/images/adminMongo/adminMongo_collectionview.png

 

adminMongo is a cross platform user interface (GUI) to handle all your MongoDB connections/databases needs. adminMongo is fully responsive and should work on a range of devices.

adminMongo connection information (including username/password) is stored unencrypted in a config file, it is not recommended to run this application on a production or public facing server without proper security considerations.

Installation

  1. Navigate to folder & install adminMongo: git clone https://github.com/mrvautin/adminMongo.git && cd adminMongo
  2. Install dependencies: npm install
  3. Start application: npm start or node app
  4. Visit http://127.0.0.1:1234 in your browser

Note: Node.js version 4.x or above is required

Electron App

adminMongo can also be used as a cross platform Electron application. Due to the size of Electron it will need to be built manually.

To build for Mac:

$ npm run-script packageOsx

To build for Windows:

$ npm run-script packageWin32

To build for Linux:

$ npm run-script packageLinux

Once built, the executable will be in the /releases folder.

Prebuilt binaries

Prebuilt binaries can be downloaded here:

Mac 64bit

Windows 32bit

Windows 64bit

The Electron builds have been tested on Mac and Windows 10. Linux has not been tested. Please report any issues.

Deploy on Heroku

Deploy

Demo (read only)

A read only demo can be seen here

Features

  • Manage from a connection level for easy access to multiple databases
  • Create/Delete databases
  • Backup/Restore databases
  • Create/Delete/Edit collection
  • Create/Delete/Edit documents
  • Create/Delete indexes
  • Query documents
  • Collection statistics
  • Export collections in JSON format
  • Server monitoring

Current limitations

  • Documents need to have an "_id" value which is a string, integer, or MongoDB ObjectId. Documents using Composite ID indexing is currently not supported.
  • Connection strings with multiple hosts for replica sets are currently not supported.

Configuration

adminMongo will listen on host: localhost and port: 1234 by default. This can be overwritten by adding a config file in /config/app.json. For example:

{
    "app": {
        "host": "10.0.0.1",
        "port": 4321,
        "password": "secureadminpassword",
        "locale": "de",
        "context": "dbApp",
        "monitoring": false
    }
}

Note: Any changes to the config file requires a restart of the application

All above parameters are usable through the environment which makes it very handy to when using adminMongo as a docker container! just run docker run -e HOST=yourchoice -e PORT=1234 ...

The config file (optional) options are:

OptionEnv-variableDefinition
hostHOSTThe IP address adminMongo will listen on
portPORTThe Port adminMongo will listen on
passwordPASSWORDAn application level password to add simply authentication
localeLOCALEThe locale is automatically set to the detected locale of Nodejs. If there is not a translation, adminMongo will default to English. This setting overrides the default/detected value
contextCONTEXTSetting a context of "dbApp" is like changing the base URL of the app and will mean the app will listen on http://10.0.0.1:4321/dbApp. Ommiting a context will mean the application will listen on root. Eg: http://10.0.0.1:4321. This setting can be useful when running adminMongo behind Nginx etc.
monitoringMONITORINGWhether to run monitoring at regular intervals. Defaults to true or on

Setting a context path

Setting a context of "dbApp" is like changing the base URL of the app and will mean the app will listen on http://10.0.0.1:4321/dbApp. Ommiting a context will mean the application will listen on root. Eg: http://10.0.0.1:4321. This setting can be useful when running adminMongo behind Nginx etc.

An example Nginx server block. Note the location /dbApp { and proxy_pass http://10.0.0.1:4321/dbApp; lines match the context set in the /config/app.json file.

server {
    listen 80;

    server_name mydomain.com www.mydomain.com;

    location /dbApp {
        proxy_pass http://10.0.0.1:4321/dbApp;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Language locale

Looking for people to translate into other languages. If you can help, grab the /locale/en.js file, translate to your language and submit a pull request.

The locale is automatically set to the detected locale of Nodejs. If there is not a translation, adminMongo will default to English. To override the detected locale a setting can be added to the app.json file. See Configuration section for a "German" example.

Authentication

By default adminMongo is not password protected. You can add password authentication by adding a password value to the /config/app.json file (See the Configuration section). Once added you will need to restart adminMongo and all routes will be protected until the correct password is added. You will then be authenticated for the life of the session (60 mins by default) or if the "Logout" link is clicked.

Usage

Create a connection

After visiting http://127.0.0.1:1234 you will be presented with a connection screen. You need to give your connection a unique name as a reference when using adminMongo and a MongoDB formatted connection string. The format of a MongoDB connection string can form: mongodb://<user>:<password>@127.0.0.1:<port>/<db> where specifying to the <db> level is optional. For more information on MongoDB connection strings, see the official MongoDB documentation.

You can supply a connection options object (see docs) with each connection.

For example:

{
    "poolSize": 10,
    "autoReconnect": false,
    "ssl": false
}

Note: The connection can be either local or remote hosted on VPS or MongoDB service such as mLab.

The connection can also be automatically initiated through the environment (or with the docker -e parameters)

Env-variableDescription
CONN_NAMEThe name of the connection to create on boot
DB_USERNAMEThe username for the database connection
DB_PASSWORDThe password for the database user
DB_HOSTThe host IP address or DNS name without the port!
DB_PORTThe port of the mongoDB database, if not provided the default 27017 will be used
DB_NAMEThe name of the database

The Connection setup screen adminMongo connections screen

Connection/Database admin

After opening your newly created connection, you are able to see all database objects associated with your connection. Here you can create/delete collections, create/delete users and see various stats for your database.

The connections/database screen adminMongo database screen

Collections

After selecting your collection from the "Database Objects" menu, you will be presented with the collections screen. Here you can see documents in pagination form, create new documents, search documents, delete, edit documents and view/add indexes to your collection.

The collections screen adminMongo collections screen

Searching/Querying documents

You can perform searches of documents using the Search documents button on the collections screen. You will need to enter the key (field name) and value. Eg: key = "_id" and value = "569ff81e0077663d78a114ce" (Only works on string "_id" fields - Use "Query Documents" for ObjectID's).

You can clear your search by clicking the Reset button on the collections screen.

Simple search documents adminMongo search documents

Complex querying of documents is done through the "Query documents" button. This allows a query Object to be passed to MongoDB to return results. Queries can be written in full BSON format or EJSON format. For example these queries should return the same results:

{ 
    ObjectId("56a97ed3f718fe9a4f599489")
}

is equivalent to:

{
    "$oid": "56a97ed3f718fe9a4f599489"
}

Query documents adminMongo search documents

Documents

Adding and editing documents is done using a JSON syntax highlighting control.

Editing a document adminMongo documents

Documents with Media embedded show previews

Documents with media adminMongo media

Server Monitoring

Functionality currently in Beta

Selected server monitoring is done at regular intervals and stored in local database store for 24hrs.

New connections require an app restart for monitoring to commence

Server monitoring adminMongo server monitoring

Indexes

Indexes can be added from the collection screen. Please see the official MongoDB documentation on adding indexes.

Viewing/Adding indexes adminMongo documents

Tests

The adminMongo API tests include:

  • Add and remove a connection
  • Add and remove a database
  • Add, remove and rename a collection
  • Create and delete a user
  • Add, query and delete a document

To run tests, simply run:

npm test

Note: You will need to ensure there is no password protection setup in the /config/app.json.

You may need to edit the variables and connection string in /tests/tests.js for your MongoDB instance.

If you see any missing tests, please submit a PR.

Contributing

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

Future plans

Please make any suggestions.

LINK: adminMongo

LINK: https://docs.mongodb.com/ecosystem/tools/administration-interfaces/

LINK tác giả: https://markmoffat.com/

Using MongoDB .NET Driver with .NET Core WebAPI

How to build step by step an ASP.NET Core WebAPI with latest MongoDB driver. The project supports all requests to MongoDB asynchronously. This is first part of building an Angular Notebook WebApp, presenting the backend.

Source could be also accessed from GitHub -> https://github.com/fpetru/WebApiMongoDB.

Update 14 Dec 2016

Following Marcello's comment, I have added a basic level of exception management.

Update 07 Dec 2016

  • I have extended the update function, making possible to modify full MongoDB documents at once, not just to some of the properties. There is a new section at the end of the article, describing this change.
  • I have updated the project to .NET Core 1.1 as well to MongoDB .NET Driver 2.4.

Update 25 Nov 2016

Trying to consume the service from Angular 2.0, see here the CodeProject article, I have ran into CORS problems: "No 'Access-Control-Allow-Origin' header is present on the requested resource."

How could this happened ?

Being different applications, running on seperate domains, all calls back to ASP.NET WebAPI site are effectively cross domain calls. With Angular 2, there is first a preflight request, before the actual request, which is an OPTIONS request. Doing this pre-check, we verify first that cross domain calls are allowed (CORS).

How I have enabled them ?

To do this I have made 2 changes:

  • Registered CORS functionality in ConfigureServices() of Startup.cs:
 public void ConfigureServices(IServiceCollection services) 
 {
      // Add service and create Policy with options 
      services.AddCors(options => { options.AddPolicy("CorsPolicy", 
                                      builder => builder.AllowAnyOrigin() 
                                                        .AllowAnyMethod() 
                                                        .AllowAnyHeader() 
                                                        .AllowCredentials()); 
                                  }); 
      // .... 

      services.AddMvc(); 
 }
  • And then enabled the policy globally to every request in the application by call app.useCors() in the Configure()method of Startup, before UseMVC.
 public void Configure(IApplicationBuilder app) 
 { 
    // ... 

    // global policy, if assigned here (it could be defined indvidually for each controller) 
    app.UseCors("CorsPolicy"); 

    // ... 

    // We define UseCors() BEFORE UseMvc, below just a partial call
    app.UseMvc(routes => {
 }

Does this have any impact to the other parts of solution ?

No, this refers just to this security policy. Even if this could be further and more selective applied, the rest of the article remains unchanged.

There is still one more update...

I have added a new article, which focuses more on client side using Angular 2, and how we effectively connect to this WebAPI. See here the article: Angular 2 with ASP.NET Core Web API – Build a simple Notebook app – Part 1.

Original article

Problem / solution format brings an easier understanding on how to build things, giving an immediate feedback. Starting from this idea, the blog post will present step by step how to build

a web application to store your ideas in an easy way, adding text notes, either from desktop or mobile, with few characteristics: run fast, save on the fly whatever you write, and be reasonably reliable and secure.

This blog post will implement just the backend, WebApi and the database access, in the most simple way. Next blog post, covers the front end, using Angular 2: Angular 2 with ASP.NET Core Web API – Build a simple Notebook app – Part 1

Topics covered

  • Technology stack
  • Configuration model
  • Options model
  • Dependency injection
  • MongoDb – Installation and configuration using MongoDB C# Driver v.2
  • Make a full ASP.NET WebApi project, connected async to MongoDB

Technology stack

The ASP.NET Core Web API has the big advantage that it can be used as HTTP service and it can be subscribed by any client application, ranging from desktop to mobiles, and also be installed on Windows, macOS or Linux.

MongoDB is a popular NoSQL database that makes a great backend for Web APIs. These lend themselves more to document store type, rather than to relational databases. This blog will present how to build a .NET Core Web API connected asynchronously to MongoDB, with full support for HTTP GET, PUT, POST, and DELETE.

To install

Here are all the things needed to be installed:

Creating the ASP.NET WebApi project

Launch Visual Studio and then access File > New Project > .Net Core > ASP.NET Core Web Application.

and then

Configuration

There are multiple file formats, supported out of the box for the configuration (JSON, XML, or INI). By default, the WebApi project template comes with JSON format enabled. Inside the setting file, order matters, and include complex structures. Here is an example with a 2 level settings structure for database connection.
AppSettings.json – update the file:

{
  "MongoConnection": {
    "ConnectionString": "mongodb://admin:abc123!@localhost",
    "Database": "NotesDb"
  },

  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

 

Dependency injection and Options model

Constructor injection is one of the most common approach to implementing Dependency Injection (DI), though not the only one. ASP.NET Core uses constructor injection in its solution, so we will also use it. ASP.NET Coreproject has a Startup.cs file, which configures the environment in which our application will run. The Startup.cs file also places services into ASP.NET Core’s Services layer, which is what enables dependency injection.

To map the custom database connection settings, we will add a new Settings class.

namespace NotebookAppApi.Model
{
    public class Settings
    {
        public string ConnectionString;
        public string Database;
    }

Here is how we modify Startup.cs to inject Settings in the Options accessor model:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.Configure<Settings>(options =>
    {
        options.ConnectionString = Configuration.GetSection("MongoConnection:ConnectionString").Value;
        options.Database = Configuration.GetSection("MongoConnection:Database").Value;
    });

Further in the project, settings will be access via IOptions interface:

IOptions<Settings>

 

MongoDB configuration

Once you have installed MongoDB, you would need to configure the access, as well as where the data is located.

To do this, create a file locally, named mongod.cfg. This will include setting path to the data folder for MongoDB server, as well as to the MongoDB log file. Please update these local paths, with your own settings:

systemLog:
  destination: file
  path: "C:\\tools\\mongodb\\db\\log\\mongo.log"
  logAppend: true
storage:
  dbPath: "C:\\tools\\mongodb\\db\\data"
security:
  authorization: enable

Run in command prompt next line. This will start the MongoDB server, pointing to the configuration file already created (in case the server is installed in a custom folder, please update first the command)

"C:\Program Files\MongoDB\Server\3.2\bin\mongod.exe" --config C:\Dev\Data.Config\mongod.cf

Once the server is started (and you could see the details in the log file), run mongo.exe in command prompt. The next step is to add the administrator user to the database. Run mongodb with the full path (ex: “C:\Program Files\MongoDB\Server\3.2\bin\mongo.exe”).

and then copy paste the next code in the console:

use admin
db.createUser(
  {
	user: "admin",
	pwd: "abc123!",
	roles: [ { role: "root", db: "admin" } ]
  }
);
exit;

 

MongoDB .NET Driver

To connect to MongoDB, add via Nuget the package named MongoDB.Driver. This is the new official driver for .NET, fully supporting the ASP.NET Core applications.

Model

The model class (POCO) associated with each entry in the notebook is included below:

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

namespace NotebookAppApi.Model
{
    public class Note
    {
        [BsonId]
        public string Id { get; set; }
        public string Body { get; set; } = string.Empty;
        public DateTime UpdatedOn { get; set; } = DateTime.Now;
        public DateTime CreatedOn { get; set; } = DateTime.Now;
        public int UserId { get; set; } = 0;
    }
}

 

Defining the database context

In order to keep the functions for accessing the database in a distinct place, we will add a NoteContext class. This will use the Settings defined above.

public class NoteContext
{
    private readonly IMongoDatabase _database = null;

    public NoteContext(IOptions<Settings> settings)
    {
        var client = new MongoClient(settings.Value.ConnectionString);
        if (client != null)
            _database = client.GetDatabase(settings.Value.Database);
    }

    public IMongoCollection<Note> Notes
    {
        get
        {
            return _database.GetCollection<Note>("Note");
        }
    }
}

 

Adding the repository

Using a repository interface, we will implement the functions needed to manage the Notes. These will also use Dependency Injection (DI) to be easily access from the application (e.g. controller section):

public interface INoteRepository
{
    Task<IEnumerable<Note>> GetAllNotes();
    Task<Note> GetNote(string id);
    Task AddNote(Note item);
    Task<DeleteResult> RemoveNote(string id);
    Task<UpdateResult> UpdateNote(string id, string body);

    // demo interface - full document update
    Task<ReplaceOneResult> UpdateNoteDocument(string id, string body);

    // should be used with high cautious, only in relation with demo setup
    Task<DeleteResult> RemoveAllNotes();
}

The access to database will be asynchronous. We are using here the new driver, which offers a full async stack.

Just as an example: to get all the Notes, we make an async request:

public async Task<IEnumerable<Note>> GetAllNotes()
{
    return await _context.Notes.Find(_ => true).ToListAsync();
}

Here is the full implementation, for all basic CRUD operations:

public class NoteRepository : INoteRepository
{
    private readonly NoteContext _context = null;

    public NoteRepository(IOptions<Settings> settings)
    {
        _context = new NoteContext(settings);
    }

    public async Task<IEnumerable<Note>> GetAllNotes()
    {
        return await _context.Notes.Find(_ => true).ToListAsync();
    }

    public async Task<Note> GetNote(string id)
    {
        var filter = Builders<Note>.Filter.Eq("Id", id);
        return await _context.Notes
                             .Find(filter)
                             .FirstOrDefaultAsync();
    }

    public async Task AddNote(Note item)
    {
        await _context.Notes.InsertOneAsync(item);
    }

    public async Task<DeleteResult> RemoveNote(string id)
    {
        return await _context.Notes.DeleteOneAsync(
                     Builders<Note>.Filter.Eq("Id", id));
    }

    public async Task<UpdateResult> UpdateNote(string id, string body)
    {
        var filter = Builders<Note>.Filter.Eq(s => s.Id, id);
        var update = Builders<Note>.Update
                            .Set(s => s.Body, body)
                            .CurrentDate(s => s.UpdatedOn);
        return await _context.Notes.UpdateOneAsync(filter, update);
    }

    public async Task<ReplaceOneResult> UpdateNote(string id, Note item)
    {
        return await _context.Notes
                             .ReplaceOneAsync(n => n.Id.Equals(id)
                                                 , item
                                                 , new UpdateOptions { IsUpsert = true });
    }

    public async Task<DeleteResult> RemoveAllNotes()
    {
        return await _context.Notes.DeleteManyAsync(new BsonDocument());
    }    
}

In order to access NoteRepository using DI model, we add a new line in ConfigureServices

services.AddTransient<INoteRepository, NoteRepository>()

where:

  • Transient: Created each time.
  • Scoped: Created only once per request.
  • Singleton: Created the first time they are requested. Each subsequent request uses the instance that was created the first time.

Adding the main controller

First we present the main controller. It provides all the CRUD interfaces, available to external applications.

[Route("api/[controller]")]
public class NotesController : Controller
{
    private readonly INoteRepository _noteRepository;

    public NotesController(INoteRepository noteRepository)
    {
        _noteRepository = noteRepository;
    }

    // GET: notes/notes
    [HttpGet]
    public Task<string> Get()
    {
        return GetNoteInternal();
    }

    private async Task<string> GetNoteInternal()
    {
        var notes = await _noteRepository.GetAllNotes();
        return JsonConvert.SerializeObject(notes);
    }

    // GET api/notes/5
    [HttpGet("{id}")]
    public Task<string> Get(string id)
    {
        return GetNoteByIdInternal(id);
    }

    private async Task<string> GetNoteByIdInternal(string id)
    {
        var note = await _noteRepository.GetNote(id) ?? new Note();
        return JsonConvert.SerializeObject(note);
    }

    // POST api/notes
    [HttpPost]
    public void Post([FromBody]string value)
    {
        _noteRepository.AddNote(new Note() { Body = value, CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now });
    }

    // PUT api/notes/5
    [HttpPut("{id}")]
    public void Put(string id, [FromBody]string value)
    {
        _noteRepository.UpdateNote(id, value);
    }

    // DELETE api/notes/5
    public void Delete(string id)
    {
        _noteRepository.RemoveNote(id);
    }

Adding the admin controller

This will be a controller dedicated to administrative tasks (we use to initialize the database with some dummy data). In real projects, we should very cautiously use such interface. For development only and quick testing purpose, this approach may be convenient.

To use it, we will just add the url in the browser. Running the code below, the full setup will be automatically created (e.g. new database, new collection, sample records). We can use either http://localhost:5000/system/init or http://localhost:53617/system/init(when using IIS). We could even extend the idea, adding more commands. However, as mentioned above, these kind of scenarios should be used just for development, and be never deployed to a production environment.

[Route("api/[controller]")]

public class SystemController : Controller
{
    private readonly INoteRepository _noteRepository;

    public SystemController(INoteRepository noteRepository)
    {
        _noteRepository = noteRepository;
    }

    // Call an initialization - api/system/init
    [HttpGet("{setting}")]
    public string Get(string setting)
    {
        if (setting == "init")
        {
            _noteRepository.RemoveAllNotes();
            _noteRepository.AddNote(new Note() { Id = "1", Body = "Test note 1", 
                          CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, UserId = 1 });
            _noteRepository.AddNote(new Note() { Id = "2", Body = "Test note 2", 
                          CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, UserId = 1 });
            _noteRepository.AddNote(new Note() { Id = "3", Body = "Test note 3", 
                          CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, UserId = 2 });
            _noteRepository.AddNote(new Note() { Id = "4", Body = "Test note 4", 
                          CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, UserId = 2 });

            return "Done";
        }

        return "Unknown";
    }
}

 

Launch settings

In order to have a quick display of the values, once the project will run, please update the file launchSettings.json.

Here is the full file content, pointing by default to api/notes url.

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:53617/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "api/notes",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "NotebookAppApi": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "http://localhost:5000/api/notes",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

 

Running the project

Before running the project, please make sure the MongoDB is running (either as an Windows Service, or via console application, as presented above).

Run first the initialization link:
http://localhost:53617/system/init

and then run the default application link
http://localhost:53617/api/notes

Use Robomongo

Using Robomongo we could check the actual entries inside the database. Connecting to the database, using the credentials, we could see all 4 records.

Fully update the MongoDB documents

Initially the sample project included only selective update of the properties. Using ReplaceOneAsync we could update the full document. Upsert creates the document, in case it doesn’t already exist.

public async Task<replaceoneresult> UpdateNote(string id, Note item)
{
     return await _context.Notes
                          .ReplaceOneAsync(n => n.Id.Equals(id)
                                            , item
                                            , new UpdateOptions { IsUpsert = true });
} 
</replaceoneresult>

Test the update

To be able to test the update, I have used Postman. It is an excellent tool to test APIs.

I have selected the command type POST, then entered the local URL, and added a new Header (Content-Type as application/json).

ASP.NET Core WebAPI Set-header

And then set the Body as raw and updated a dummy value.

ASP.NET Core WebAPI Make the request

Using RoboMongo we can see the value updated.

MongoDB .NET Driver Updated document in Robomongo

Exception management

Starting with C# 5.0 async and await were introduced into the language to simplify using the Task Parallel Library. We can simply use a try/catch block to catch an exception, like so:

public async Task<ienumerable<note>> GetAllNotes()
{
    try
    {
        return await _context.Notes.Find(_ => true).ToListAsync();
    }
    catch (Exception ex)
    {
        // log or manage the exception
        throw ex;
    }
}
</ienumerable<note>

In this way we handle a faulted task by asynchronously wait for it to complete, using await. This will rethrow the original stored exception. Initially I have used void as return. Changing the return type, the exception raised in the async method will get safely saved in the returning Task instance. When we await the faulty method, the exception saved in the Task will get rethrown with its full stack trace preserved.

public async Task AddNote(Note item)
{
    try
    {
        await _context.Notes.InsertOneAsync(item);
    }
    catch (Exception ex)
    {
        // log or manage the exception
        throw ex;
    }
}

LINK: https://www.codeproject.com/Articles/1151842/Using-MongoDB-NET-Driver-with-NET-Core-WebAPI