ASP.NET

ASP.NET Core 2.0 Tutorial – CRUD Operations using MongoDB

A newer version of ASP.NET Core is available. Checkout CRUD operations with ASP.NET Core 5.0 here.

In this ASP.NET Core 2.0 Tutorial, we will follow a step by step approach and create an application performing all CRUD (Create, Retrieve, Update, Delete) operations with MongoDB. In order to keep things simple and we are using “Product” entity to perform all CRUD operations.

Getting started with ASP.NET Core 2.0 Tutorial

Pre-Requisites:

Below are the Prerequisites for understanding and executing the ASP.NET MVC Core 2.0 application.

  1. Microsoft Visual Studio 2017 – assuming you already have installed it.
  2. Please follow the below link for installing MongoDB Community Edition on windows.
    https://docs.mongodb.com/getting-started/shell/tutorial/install-mongodb-on-windows
  3. Mongo Booster (IDE for Mongo DB). (https://nosqlbooster.com/downloads)

ASP.NET Core 2.0 Tutorial with MongoDB:

Below steps guide you to creating a new project.

  1. Open Visual Studio 2017.
  2. Click on File -> New -> Project.
  3. Click “OK”.
    Select “Empty” template and Click on “OK”.
  4. The new empty solution will be open in your window.
  5. In this article, we will talk about “DotNetCoreWithMongoApplication”. The Solution Explorer window for that project is defined as below.
  6. For running the application, you first need to change the database connection string. Open “appsettings.json” file.
    You need to be change the mongo connection as per your system.
  7. Mongo Database snapshot is as below.
  8. Right click on solution, clean & rebuild the solution.
Follow here for complete ASP.NET Core 5.0 Tutorials as well as latest updates.

Performing CRUD Operations using ASP.NET Core 2.0 with MongoDB

Now, in this ASP.NET Core 2.0 article, we will move forward to create an Entity i.e. Product, it’s snapshot, Listing page, Creation page, Editing page and Deleting a record.

Product “Entity” Section:

  1. Product.cs class: Add a new class under Model. We will define the properties of Product in this class. This class is also mapped to MongoDB Collection named Product.
    using MongoDB.Bson.Serialization.Attributes;
    using System.ComponentModel.DataAnnotations;
    
    namespace DotNetCoreWithMongoApplication.Model
    {
     public class Product
     {
     [BsonId]
     public string Id { get; set; }
     [Display(Name = "Product Name")]
     public string Name { get; set; }
     [Display(Name = "Product Code")]
     public string Code { get; set; }
     [Display(Name = "Product Category")]
     public string ProductCategory { get; set; }
     }
    }
  2. MongoSetting.cs class: In this class, We will define the ConnectionString and Database property for MongoDB connection.
    namespace DotNetCoreWithMongoApplication.Model
    {
     public class MongoSetting
     {
     public string ConnectionString;
     public string Database;
     }
    }
  3. Defining Product Context class: We will define ProductContext class for accessing the database. Here we can use MongoDB C# driver for connecting to the MongoDB.
    using DotNetCoreWithMongoApplication.Model;
    using Microsoft.Extensions.Options;
    using MongoDB.Driver;
    
    namespace DotNetCoreWithMongoApplication.Data
    {
     public class ProductContext
     {
     private readonly IMongoDatabase _database = null;
    
    public ProductContext(IOptions<MongoSetting> settings)
     {
     var client = new MongoClient(settings.Value.ConnectionString);
     if (client != null)
     _database = client.GetDatabase(settings.Value.Database);
     }
    
    public IMongoCollection<Product> Products
     {
     get
     {
     return _database.GetCollection<Product>("Product");
     }
     }
     }
    }
  4. Product Repository Interface & class: We can define Repository Interface for implementing dependency injection design pattern, so it will be easily accessible from the controller. Repository class containing all the CRUD operation logic.
    using DotNetCoreWithMongoApplication.Model;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    
    namespace DotNetCoreWithMongoApplication.Interface
    {
     public interface IProductRepository
     {
     Task<IEnumerable<Product>> GetAllProducts();
     Task<Product> GetProduct(string id);
     Task AddProduct(Product item);
     Task<bool> RemoveProduct(string id);
     Task<bool> UpdateProduct(string id, Product item);
     }
    }

    You can easily find the IProductRepository implementation with available source code.

  5. Startup and Configuration file section: We can use Startup class for configuring Mongo Setting class. Mongo Setting class is containing ConnectionString and Database property. In Startup class, we can initialize ConnectionString and Database property from the configuration (app.json) file.
    using DotNetCoreWithMongoApplication.Data;
    using DotNetCoreWithMongoApplication.Interface;
    using DotNetCoreWithMongoApplication.Model;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    
    namespace DotNetCoreWithMongoApplication
    {
     public class Startup
     {
     public Startup(IConfiguration configuration)
     {
     Configuration = configuration;
     }
    
    public IConfiguration Configuration { get; }
    
    // This method gets called by the runtime. Use this method to add services to the container.
     public void ConfigureServices(IServiceCollection services)
     {
     services.AddCors(options =>
     {
     options.AddPolicy("CorsPolicy",
     builder => builder.AllowAnyOrigin()
     .AllowAnyMethod()
     .AllowAnyHeader()
     .AllowCredentials());
     });
    
    services.AddMvc();
    
    services.Configure<MongoSetting>(options =>
     {
     options.ConnectionString = Configuration.GetSection("MongoConnection:ConnectionString").Value;
     options.Database = Configuration.GetSection("MongoConnection:Database").Value;
     });
    
    services.AddTransient<IProductRepository, ProductRepository>();
     }
    
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
     public void Configure(IApplicationBuilder app, IHostingEnvironment env)
     {
     app.UseCors("CorsPolicy");
    
    if (env.IsDevelopment())
     {
     app.UseDeveloperExceptionPage();
     }
    
    app.UseStaticFiles();
    
    app.UseMvc(routes =>
     {
     routes.MapRoute(
     name: "default",
     template: "{controller=Product}/{action=Index}/{id?}");
     });
     }
     }
    }

Listing Screen:

In this section, we can define the View, Controller logic, Repository logic and output screen for Product List page.

  1. Cshtml page
    @model IEnumerable<DotNetCoreWithMongoApplication.Model.Product>
    @using DotNetCoreWithMongoApplication.Model
    
    <div class="top-buffer"></div>
    <div class="panel panel-primary">
     <div class="panel-heading panel-head">Products</div>
     <div class="panel-body">
     <div class="btn-group">
     <a id="createEditProductModal" data-toggle="modal" asp-action="AddEditProduct" data-target="#modal-action-product" class="btn btn-primary">
     <i class="glyphicon glyphicon-plus"></i> Add Product
     </a>
     </div>
     <div class="top-buffer"></div>
     <table class="table table-bordered table-striped table-condensed">
     <thead>
     <tr>
     <th>Name</th> 
     <th>Code</th>
     <th>Product Category</th>
     <th>Action</th>
     </tr>
     </thead>
     <tbody>
    
     @foreach (var item in Model)
     {
     <tr>
     <td>@Html.DisplayFor(modelItem => item.Name)</td>
     <td>@Html.DisplayFor(modelItem => item.Code)</td>
     <td>@Html.DisplayFor(modelItem => item.ProductCategory)</td> 
     <td>
     <a id="editProductModal" data-toggle="modal" asp-action="AddEditProduct" asp-route-id= "@item.Id" data-target="#modal-action-product" 
     class="btn btn-info">
     <i class="glyphicon glyphicon-pencil"></i> Edit
     </a>
     <a id="deleteProductModal" data-toggle="modal" asp-action="DeleteProduct" asp-route-id= "@item.Id" data-target="#modal-action-product" class="btn btn-danger">
     <i class="glyphicon glyphicon-trash"></i> Delete
     </a>
     </td>
     </tr>
     }
     </tbody>
     </table>
     </div>
    </div>
    
    @Html.Partial("_Modal", new BootstrapModel { ID = "modal-action-product", AreaLabeledId = "modal-action-product-label", Size = ModalSize.Medium })
    @section scripts
    {
     <script src="~/js/product-index.js" asp-append-version="true"></script>
    }
  2. Controller Action Method
    [HttpGet]
     public IActionResult Index()
     {
     IEnumerable<Product> model = _productRepository.GetAllProducts().Result;
     return View("Index", model);
     }
  3. Repository Method
    public async Task<IEnumerable<Product>> GetAllProducts()
     {
     try
     {
     return await _context.Products.Find(_ => true).ToListAsync();
     }
     catch (Exception ex)
     {
     throw ex;
     }
     }
  4. Output screen
More ASP.NET Core 2.0 Tutorial and Related

Creation/Modification Screen:

In this section, we can define the View, Controller logic, Repository logic and output screen for Add/Edit product.

  1. Cshtml page
    @model DotNetCoreWithMongoApplication.Model.Product
    @using DotNetCoreWithMongoApplication.Model
    
    <form asp-action="AddEditProduct" role="form">
     @await Html.PartialAsync("_ModalHeader", new ModalHeader { Heading = String.Format("{0} Product", string.IsNullOrWhiteSpace(Model.Id) ? "Add" : "Edit") })
     
     <div class="modal-body form-horizontal">
     <div class="form-group">
     <label asp-for="Name" class="col-lg-3 col-sm-3 control-label"></label> 
     <div class="col-lg-6">
     <input asp-for="Name" class="form-control" /> 
     </div>
     </div>
     <div class="form-group">
     <label asp-for="Code" class="col-lg-3 col-sm-3 control-label"></label> 
     <div class="col-lg-6">
     <input asp-for="Code" class="form-control" /> 
     </div>
     </div>
     <div class="form-group">
     <label asp-for="ProductCategory" class="col-lg-3 col-sm-3 control-label"></label>
     <div class="col-lg-6">
     <input asp-for="ProductCategory" class="form-control" />
     </div>
     </div>
     </div>
     @await Html.PartialAsync("_ModalFooter", new ModalFooter { })
    </form>
  2. Create/Edit Controller Action Methods
    [HttpGet]
     public IActionResult AddEditProduct(string id)
     {
     Product model = new Product();
     if (!string.IsNullOrWhiteSpace(id))
     {
     model = _productRepository.GetProduct(id).Result;
     }
     return PartialView("~/Views/Product/_AddEditProduct.cshtml", model);
     }
    
    [HttpPost]
     public ActionResult AddEditProduct(string id, Product model)
     {
     try
     {
     if (ModelState.IsValid)
     {
     bool isNew = string.IsNullOrWhiteSpace(id);
     if (isNew)
     {
     model.Id = ObjectId.GenerateNewId().ToString();
     _productRepository.AddProduct(model);
     }
     else
     {
     _productRepository.UpdateProduct(id, model);
     }
     }
     }
     catch (Exception ex)
     {
     throw ex;
     }
     return RedirectToAction("Index");
     }
  3. Repository Methods
    public async Task AddProduct(Product item)
     {
     try
     {
     await _context.Products.InsertOneAsync(item);
     }
     catch (Exception ex)
     {
     throw ex;
     }
     }
    public async Task<bool> UpdateProduct(string id, Product item)
     {
     try
     {
     ReplaceOneResult actionResult = await _context.Products
     .ReplaceOneAsync(n => n.Id.Equals(id)
     , item
     , new UpdateOptions { IsUpsert = true });
     return actionResult.IsAcknowledged
     && actionResult.ModifiedCount > 0;
     }
     catch (Exception ex)
     {
     throw ex;
     }
     }
  4. Output screen

Delete Screen:

In this section, we can define the View, Controller logic, Repository logic and output screen for Delete product.

  1. Cshtml Page
    @model DotNetCoreWithMongoApplication.Model.Product
    @using DotNetCoreWithMongoApplication.Model
    
    @using (Html.BeginForm())
    {
     @Html.Partial("_ModalHeader", new ModalHeader { Heading = "Delete Product" })
    
    <div class="modal-body form-horizontal">
     Are you want to delete @Model.Name?
     </div>
     @Html.Partial("_ModalFooter", new ModalFooter { SubmitButtonText = "Delete" })
    }
  2. Delete Controller Action Methods
    [HttpGet]
     public IActionResult DeleteProduct(string id)
     {
     Product product = _productRepository.GetProduct(id).Result;
     return PartialView("~/Views/Product/_DeleteProduct.cshtml", product);
     }
    
     [HttpPost]
     public IActionResult DeleteProduct(string id, IFormCollection form)
     {
     _productRepository.RemoveProduct(id);
     return RedirectToAction("Index");
     }
  3. Repository Methods
    public async Task<Product> GetProduct(string id)
     {
     var filter = Builders<Product>.Filter.Eq("Id", id);
     try
     {
     return await _context.Products
     .Find(filter)
     .FirstOrDefaultAsync();
     }
     catch (Exception ex)
     {
     throw ex;
     }
     }
    
    public async Task<bool> RemoveProduct(string id)
     {
     try
     {
     DeleteResult actionResult = await _context.Products.DeleteOneAsync(
     Builders<Product>.Filter.Eq("Id", id));
     return actionResult.IsAcknowledged
     && actionResult.DeletedCount > 0;
     }
     catch (Exception ex)
     {
     throw ex;
     }
     }
  4. Output screen

Concluding Remarks: We have created an ASP.NET Core 2.0 application with all CRUD operations following a step by step approach. This simple application can be taken as base to further enhance your skills and develop more advanced applications on ASP.NET Core 2.0.

More ASP.NET Core 2.0 Tutorial and Related
Online Course Expert

Share
Published by
Online Course Expert

Recent Posts

Simple Tips to Help You Prepare for Employment After an Injury

It’s a tough reality: every year, over 14.1 million workers suffer from work-related injuries. For…

1 month ago

London’s Top 5 Cooking Courses for Beginners

If you’ve ever wanted to learn how to cook, but didn’t know where to start,…

1 month ago

The Role of Knowing Your International IQ Score in Choosing the Right Career Path

Choosing the right career path can be a daunting task, especially with the myriad of…

5 months ago

How HR Software Can Empower Your Business

Believe it or not, the concept of human resources has existed for more than 100…

5 months ago

Web3 in Gaming: Revolutionizing the Industry

Web3 managed to change the gaming industry by leveraging blockchain technology. It offers a decentralized…

5 months ago

Tips for Overcoming Homesickness in College

College is often fun and is filled with lots of activities, especially in the first…

5 months ago