MongoDB CRUD Operations in Asp.Net Core With C#

Introduction

MongoDB is an open source NoSQL DBMS stores data in form of bson documents (binary-encoded) with JSON format.

It provides high performance and easy to maintain in comparison to Relational Database Management System when we have to deal with unstructured data for our application, and it can work on ASP.NET Core.

BSON stands for Binary JSON, is a binary encoded serialization of JSON like documents. Like JSON, BSON supports the embedding of documents and arrays within other documents and arrays.

Sample prerequisites

  • .NET Core 1.0 or later version(s).
  • Microsoft Visual Studio 2015 update3 or above.

Implementaion

  1. Create a new ASP.NET Core projec: For this, Open Visual Studio (VS) and navigate to File > New > Project. Select Template > Visual C# > .NET Core > ASP.NET Core Web Application (.NET Core) as shown in the following image.

  2.  Name this application as AspCoreApiMongoDb. Click on the OK button which will open the following window which shows ASP.NET Templates. Select Web API as shown in the following image

  3. Right click on the project and select Manage NuGet Packages
  4. In the browser tab, type MongoDB.Driver in the search box as shown in the following image.

 

Note : - Ensure the version is 2.3 or later. Click Install.


5. In the project create a folder Models (if it’s not already created) under project AspCoreApiMongoDb. Now, Add following class Product.cs under this folder.

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.ComponentModel.DataAnnotations;
 
namespace AspCoreApiMongoDb.Models
{
    public class Product
    {
        public ObjectId Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
        public DateTime? UpdatedOn { get; set; }
        public DateTime? CreatedOn { get; set; }
    }
}

The class contains Id property of the type ObjectId. This property is mandatory so that the CLR object can be mapped with Collection in MongoDB. The class contains properties having the BsonElement attribute applied on it. This represents the mapped property with the MongoDB collection.

6. Open AppSettings.json file and add MongoDB connection string.

{
   "MongoConnection": {
    "ConnectionString": "mongodb://localhost:27017",
    "Database": "ProductDb"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

7. In the Models folder Add a new Settings.cs class file to map the custom database connection settings.

namespace AspCoreApiMongoDb.Models
{
    public class Settings
    {
        public string ConnectionString { get; set; }
        public string Database { get; set; }
    }
}
 

8. Create a folder DataLayer under the project. Add following class  MongoRepository.cs under this folder.

using AspCoreApiMongoDb.Models;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using System;
 
 
namespace AspCoreApiMongoDb.DataLayer
{
    public class MongoRepository 
    {
        //delcaring mongo db
        private readonly IMongoDatabase _database;
 
        public MongoRepository(IOptions<Settings> settings)
        {
            try
            {
                var client = new MongoClient(settings.Value.ConnectionString);
                if (client != null)
                    _database = client.GetDatabase(settings.Value.Database);
            }
            catch(Exception ex)
            {
                throw new Exception("Can not access to MongoDb server.", ex);
            }
 
        }
 
        public IMongoCollection<Product> products =>      _database.GetCollection<Product>("Products");
        
    }

 

9. Create a folder Abstracts under the DataLayer. Add following class IProductService under this folder.

using AspCoreApiMongoDb.Models;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Threading.Tasks;
 
namespace AspCoreApiMongoDb.DataLayer.Abstracts
{
    public interface IProductService
    {
        Task<IEnumerable<Product>> GetAllProducts();
        Task<Product> GetProduct(string name);
        Task AddProduct(Product model);
        Task<bool> UpdatePrice(Product model);
        Task<DeleteResult> RemoveProduct(string name);
        Task<DeleteResult> RemoveAllProducts();
    }
}

 

10. Add following class ProductService under DataLayer folder.

using AspCoreApiMongoDb.DataLayer.Abstracts;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AspCoreApiMongoDb.Models;
using MongoDB.Driver;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
 
namespace AspCoreApiMongoDb.DataLayer
{
    public class ProductService : IProductService
    {
        private readonly MongoRepository _repository = null;
        public ProductService(IOptions<Settings> settings)
        {
            _repository = new MongoRepository(settings);
        }
 
        public async Task<IEnumerable<Product>> GetAllProducts()
        {
            return await _repository.products.Find(x => true).ToListAsync();
        }
 
        public async Task<Product> GetProduct(string name)
        {
            var filter = Builders<Product>.Filter.Eq("Name", name);
            return await _repository.products.Find(filter).FirstOrDefaultAsync();
        }
        public async Task AddProduct(Product model)
        {
            //inserting data
            await _repository.products.InsertOneAsync(model);
        }
 
        public async Task<bool> UpdatePrice(Product model)
        {
 
            var filter = Builders<Product>.Filter.Eq("Name", model.Name);
            var product = _repository.products.Find(filter).FirstOrDefaultAsync();
            if (product.Result == null)
                return false;
            var update = Builders<Product>.Update
                                          .Set(x => x.Price, model.Price)
                                          .Set(x => x.UpdatedOn, model.UpdatedOn);
 
            await _repository.products.UpdateOneAsync(filter, update);
            return true;
        }
 
        public async Task<DeleteResult> RemoveProduct(string name)
        {
            var filter = Builders<Product>.Filter.Eq("Name", name);
            return await _repository.products.DeleteOneAsync(filter);
        }
        public async Task<DeleteResult> RemoveAllProducts()
        {
            return await _repository.products.DeleteManyAsync(new BsonDocument());
        }
 
 
    }
}

 

11. Add following Controller class ProductController under Controllers folder.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using AspCoreApiMongoDb.DataLayer.Abstracts;
using AspCoreApiMongoDb.Models;
 
namespace AspCoreApiMongoDb.Controllers
{
    public class ProductController : Controller
    {
        private readonly IProductService _productService;
        public ProductController(IProductService productService)
        {
            _productService = productService;
        }
        [HttpGet]
        [Route("api/product")]
        public Task<IEnumerable<Product>> Get()
        {
            return _productService.GetAllProducts();
        }
 
        [HttpGet]
        [Route("api/product/getByName")]
        public async Task<IActionResult> GetByCategory(string name)
        {
            try
            {
                var product = await _productService.GetProduct(name);
                if (product == null)
                {
                    return Json("No product found!");
                }
                return Json(product);
            }
            catch (Exception ex)
            {
                return Json(ex.ToString());
 
            }
 
        }
 
        [HttpPost]
        [Route("api/product")]
        public async Task<IActionResult> Post(Product model)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(model.Name))
                    return BadRequest("Please enter product name");
                else if (string.IsNullOrWhiteSpace(model.Category))
                    return BadRequest("Please enter category");
                else if (model.Price <= 0)
                    return BadRequest("Please enter price");
 
                model.CreatedOn = DateTime.UtcNow;
                await _productService.AddProduct(model);
                return Ok("Your product has been added successfully");
            }
            catch (Exception ex)
            {
                return BadRequest(ex.ToString());
            }
        }
 
        [HttpPut]
        [Route("api/product/updatePrice")]
        public async Task<IActionResult> UpdatePrice(Product model)
        {
            if (string.IsNullOrWhiteSpace(model.Name))
                return BadRequest("Product name missing");
            model.UpdatedOn = DateTime.UtcNow;
            var result = await _productService.UpdatePrice(model);
            if (result)
            {
                return Ok("Your product's price has been updated successfully");
            }
            return BadRequest("No product found to update");
 
        }
 
        [HttpDelete]
        [Route("api/product")]
        public async Task<IActionResult> Delete(string name)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(name))
                    return BadRequest("Product name missing");
                await _productService.RemoveProduct(name);
                return Ok("Your product has been deleted successfully");
            }
            catch (Exception ex)
            {
                return BadRequest(ex.ToString());
            }
        }
        [HttpDelete]
        [Route("api/product/deleteAll")]
        public IActionResult DeleteAll()
        {
            try
            {
                _productService.RemoveAllProducts();
                return Ok("Your all products has been deleted");
            }
            catch (Exception ex)
            {
                return BadRequest(ex.ToString());
            }
        }
 
    }
}

 

12. Now, Let’s modify Startup.cs to inject Settings in the Options accessor model and register the service.

 public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddMvc();
            //injecting Settings in the Options accessor model
            services.Configure<Settings>(Options =>
            {
                Options.ConnectionString =   Configuration.GetSection("MongoConnection:ConnectionString").Value;
                Options.Database = Configuration.GetSection("MongoConnection:Database").Value;
            });
            services.AddTransient<IProductService, ProductService>();
        }
 

Configure MongoDB & Robomongo

To use MongoDB within ours .NET application, first we need to install MongoDB and Robomongo (Free GUI tool to use MongoDB) into our system.

This is the very easy process to install, configure and use MongoDB.

Steps to Configure MongoDB

  1. First, We have to download MongoDB. Download MongoDB     from  https://www.mongodb.com/download-center?jmp=nav#community
  2. Run the downloaded file and go for "Complete" installation option.
  3. Create Empty directory: C:\data\db. This is the directory where MongoDB stores its database files.
  4. Navigate to path: C:\Program Files\MongoDB\Server\3.4 (OR installed version)\bin
  5. Run mongod.exe, this will start the MongoDB server on port: 27017 in insecure mode.
  6. Run mongo.exe
  7. Run following commands –
  8. use ProductDb

This will create a database of name ProductDb if it does not exist already, else it will be opened for transactions if the database already exists. In this database, we can create a transaction using the following command

a. db.Products.insert({'Name':'Home Theater','Price':10000,'Category':'Electronics'})

b. Exit;



Steps to Configure Robomongo(GUI tool)

  1. Run RoboMongo, and create a connection.

  2. Create a connection to localhost and Test.
  3. Save connection.
  4. Connect with MongoDB database.
  5. Connection successful.