CRUD Operations On CosmosDB Mongo API Using ASP.NET Core

In this article, we will discuss how to create a web application to perform Crud operations using Cosmos DB.

Today, in this article, we will discuss how to develop a web application to perform CRUD operations using Cosmos DB. Now, as we all know, Cosmos DB is a NoSQL database, it is an alternative way of storing information when we do not fit our data storing requirement in an RDBMS system. Cosmos DB is a database server which is always distributed globally. It also supports the multi-model database service. That means it can be used to store a document, key-pair values, relational data, and also, a graph model’s data. Now, in this article, we will first create a Cosmos DB database using Azure portal and then develop an application which will insert, update, and delete data into that Cosmos DB database.
 

Prerequisites 

  1. Microsoft Visual Studio 2017
  2. Account in Azure Portal.  
If you don’t have any existing Azure account, then you can create a free trial account in Azure portal using your email id.
 

Cosmos DB Account 

 
For creating a Cosmos DB database in the Azure portal, first, we need to create an Azure Cosmos DB account which is basically an Azure resource which is required to represent the database entity. This account is mainly used to estimate your resource usage and then create billing according to your subscriptions. Azure Cosmos DB account is normally associated with several data models which supported by the Azure Cosmos DB. The default data model of the Azure Cosmos DB is the SQL API.
 

How to Create Cosmos DB Account in Azure Portal

 
To create the Cosmos DB Account in Azure Portal, first, we need to log in to the Azure Portal and then perform the below steps to create a Cosmos DB Account.

Step 1
 
Click on the Azure Cosmos DB option from the Resource Dashboard.
 
Azure portal DashBoard

Step 2
 
On the Create Azure Cosmos DB Account page, enter the required parameter settings for the new Azure Cosmos DB account, including the database name, resource name, location.
 
e
 
Step 3
 
In the above image, Account Name means the database name. API is the data model support which is SQL API by default. We will Select Azure Cosmos DB for MongoDB API from that drop down.
 
Step 4
 
Now click on the review and create button.
 
Step 5
 
After the settings are validated, click Create to create the account
 
Step 6
 
The account creation takes some time. Wait for the portal to display the notification that the deployment succeeded and click the notification.
 
Step 7
 
Once the deployment is succeeded, click Go to resource options to open Cosmos DB Account.
 
Cosmosdb account details
 
Step 8
 
Now, its time to create Cosmos DB Database and Collections. For this, click on the Data Explorer option.
 
e create
 
Step 9
 
Now Click on New Collections button and then provide the Database Name and Collection Name.
  • Database Name : DemoDB
  • Collection Name : Products
Step 10
 
Now click on Ok Button.
 
Step 11
 
Once Database is created, click on ConnectionString option from the left panel.
 
Cosmosdb connection string
 
Step 12
 
Now copy the Primary Connection string value and store in a note pad file. We will use this connection string in a configuration file within the applications.
 

Create a Web Application using .NET Core in VS 2017

 
Step 1
 
Now, open Microsoft Visual Studio 2017 and click on File --> New --> Projects.
 
VS new Solution
 
Step 2
 
Select the Web Application Project template and click OK.
 
MVC Project Templates
 
Step 3
 
In the Project Template Box, Select Web Application (Model-View-Controller) options and click on the OK button.
 
Step 4
 
Now a blank project solution is ready.
 
Step 5
 
Now first open the App.Config file and store the database name and connections string to this file which we already copied from the Azure portal.
  1. {  
  2.   "Logging": {  
  3.     "LogLevel": {  
  4.       "Default""Warning"  
  5.     }  
  6.   },  
  7.   "AllowedHosts""*",  
  8.   "ConnectionStrings": {  
  9.      "ServerName""mongodb://dbtestcosmosdb:aQU1dBTZmwQD56pF9VoqdUHqe7SJ1QXqIiqDA1e4WcnHYZfHFXNYlG5yL9pShotvgtPO3Ss8hALVkp1UzV6WkA==@dbtestcosmosdb.documents.azure.com:10255/?ssl=true&replicaSet=globaldb",  
  10.     "DatabaseName""DemoDB"  
  11.   }  
  12. }  
Step 6
 
Now, add another Class Library Project for creating the Data Access Layer.
 
Step 7
 
After adding the new projects, we need to install the below NuGet Packages to access Cosmos DB database using MongoDB client driver.
 
Installed Nuget Packages
 
Step 8
 
Now, add another class library project for Model Class and add a class called Products and define the Product model class as below.
  1. using MongoDB.Bson;  
  2. using MongoDB.Bson.Serialization.Attributes;  
  3. using Newtonsoft.Json;  
  4. using System;  
  5. using System.ComponentModel.DataAnnotations;  
  6. using System.ComponentModel.DataAnnotations.Schema;  
  7.   
  8. namespace ModelClass  
  9. {  
  10.     public class Product  
  11.     {  
  12.         public Product()  
  13.         {  
  14.             CreatedDate = DateTime.Now;  
  15.         }  
  16.   
  17.         [BsonId]  
  18.         [JsonProperty("objectId"), JsonConverter(typeof(ObjectIdConverter))]  
  19.         public ObjectId ObjectId { getset; }  
  20.   
  21.         [Key]  
  22.         public int ProductId { getset; }  
  23.   
  24.         [Required(ErrorMessage = "Please Enter Name")]  
  25.         [Column(TypeName = "varchar(50)")]  
  26.         public string Name { getset; }  
  27.   
  28.         public decimal UnitPrice { getset; }  
  29.   
  30.         [Required(ErrorMessage = "Please Enter Description")]  
  31.         [Column(TypeName = "varchar(500)")]  
  32.         public string Description { getset; }  
  33.   
  34.         [Column(TypeName = "varchar(50)")]  
  35.         public string ImageName { getset; }  
  36.   
  37.         [Column(TypeName = "varchar(250)")]  
  38.         public string ImagePath { getset; }  
  39.           
  40.         public DateTime CreatedDate { getset; }  
  41.   
  42.         public DateTime? UpdatedDate { getset; }  
  43.     }  
  44. }  
Step 9
 
Now, select the Data Access Layer Projects and Create a New Folder called AppConfig.
 
Step 10
 
Now, within this folder add a new class file called AppConfiguration.cs where we will read the configuration file value by providing the key as below.
  1. using Microsoft.Extensions.Configuration;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.IO;  
  5. using System.Text;  
  6.   
  7. namespace DataContextLayer.AppConfig  
  8. {  
  9.     public static class AppConfiguration  
  10.     {  
  11.         private static IConfiguration currentConfig;  
  12.   
  13.         public static void SetConfig(IConfiguration configuration)  
  14.         {  
  15.             currentConfig = configuration;  
  16.         }  
  17.   
  18.   
  19.         public static string GetConfiguration(string configKey)  
  20.         {  
  21.             try  
  22.             {  
  23.                 string connectionString = currentConfig.GetConnectionString(configKey);  
  24.                 return connectionString;  
  25.             }  
  26.             catch (Exception ex)  
  27.             {  
  28.                 throw (ex);  
  29.             }  
  30.             return "";  
  31.         }  
  32.   
  33.     }  
  34. }  
Step 11
 
Now open the Startup.cs file and add the appConfig file so that we can retrieve value of this application configuration file from the class library.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5. using DataContextLayer.AppConfig;  
  6. using Microsoft.AspNetCore.Builder;  
  7. using Microsoft.AspNetCore.Hosting;  
  8. using Microsoft.AspNetCore.Http;  
  9. using Microsoft.AspNetCore.HttpsPolicy;  
  10. using Microsoft.AspNetCore.Mvc;  
  11. using Microsoft.Extensions.Configuration;  
  12. using Microsoft.Extensions.DependencyInjection;  
  13.   
  14. namespace CosmosDb_Demo_Crud  
  15. {  
  16.     public class Startup  
  17.     {  
  18.         public Startup(IConfiguration configuration)  
  19.         {  
  20.             Configuration = configuration;  
  21.         }  
  22.   
  23.         public IConfiguration Configuration { get; }  
  24.   
  25.         // This method gets called by the runtime. Use this method to add services to the container.  
  26.         public void ConfigureServices(IServiceCollection services)  
  27.         {  
  28.             services.Configure<CookiePolicyOptions>(options =>  
  29.             {  
  30.                 // This lambda determines whether user consent for non-essential cookies is needed for a given request.  
  31.                 options.CheckConsentNeeded = context => true;  
  32.                 options.MinimumSameSitePolicy = SameSiteMode.None;  
  33.             });  
  34.   
  35.             services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);  
  36.   
  37.             services.AddSingleton(_ => Configuration);  
  38.   
  39.         }  
  40.   
  41.         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
  42.         public void Configure(IApplicationBuilder app, IHostingEnvironment env)  
  43.         {  
  44.             if (env.IsDevelopment())  
  45.             {  
  46.                 app.UseDeveloperExceptionPage();  
  47.             }  
  48.             else  
  49.             {  
  50.                 app.UseExceptionHandler("/Home/Error");  
  51.                 // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.  
  52.                 app.UseHsts();  
  53.             }  
  54.   
  55.             app.UseHttpsRedirection();  
  56.             app.UseStaticFiles();  
  57.             app.UseCookiePolicy();  
  58.   
  59.             AppConfiguration.SetConfig(Configuration);  
  60.   
  61.   
  62.             app.UseMvc(routes =>  
  63.             {  
  64.                 routes.MapRoute(  
  65.                     name: "default",  
  66.                     template: "{controller=Products}/{action=Index}/{id?}"  
  67.                 );  
  68.             });  
  69.         }  
  70.     }  
  71. }  
Step 12
 
Now, add another class called clsMongoDBDataContext.cs and then add the below code. This data context is basically established communication between the Cosmos DB and the application.
  1. using DataContextLayer.AppConfig;  
  2. using Microsoft.Extensions.Configuration;  
  3. using ModelClass;  
  4. using MongoDB.Driver;  
  5.   
  6. namespace DataContextLayer  
  7. {  
  8.     public class clsMongoDbDataContext  
  9.     {  
  10.         private string _connectionStrings = string.Empty;  
  11.         private string _databaseName = string.Empty;  
  12.         private string _collectionName = string.Empty;  
  13.           
  14.   
  15.         private readonly IMongoClient _client;  
  16.         private readonly IMongoDatabase _database;  
  17.   
  18.         public clsMongoDbDataContext(string strCollectionName)  
  19.         {  
  20.             this._collectionName = strCollectionName;  
  21.             this._connectionStrings = AppConfiguration.GetConfiguration("ServerName");  
  22.             this._databaseName = AppConfiguration.GetConfiguration("DatabaseName");  
  23.             this._client = new MongoClient(_connectionStrings);  
  24.             this._database = _client.GetDatabase(_databaseName);  
  25.         }  
  26.   
  27.         public IMongoClient Client  
  28.         {  
  29.             get { return _client; }  
  30.         }  
  31.   
  32.         public IMongoDatabase Database  
  33.         {  
  34.             get { return _database; }  
  35.         }  
  36.   
  37.         public IMongoCollection<Product> GetProducts  
  38.         {  
  39.             get { return _database.GetCollection<Product>(_collectionName); }  
  40.         }  
  41.     }  
  42. }  
Step 13
 
Now, go to the main projects i.e. MVC Application projects.
 
Step 14
 
Select the Controller folder and add a new MVC Controller Name ProductsController.cs
  
Step 15
 
Now, within the controller class, write down the below code within the Index Method.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5. using DataContextLayer;  
  6. using Microsoft.AspNetCore.Http;  
  7. using Microsoft.AspNetCore.Mvc;  
  8. using ModelClass;  
  9. using MongoDB.Bson;  
  10. using MongoDB.Driver;  
  11.   
  12.   
  13.   
  14. namespace CosmosDb_Demo_Crud.Controllers  
  15. {  
  16.     public class ProductsController : Controller  
  17.     {  
  18.         clsMongoDbDataContext _dbContext = new clsMongoDbDataContext("Products");  
  19.   
  20.         // GET: Products  
  21.         public async Task<ActionResult> Index()  
  22.         {  
  23.             IEnumerable<Product> products = null;  
  24.             using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(new BsonDocument()))  
  25.             {  
  26.                 while (await cursor.MoveNextAsync())  
  27.                 {  
  28.                     products = cursor.Current;  
  29.                 }  
  30.             }  
  31.             return View(products);  
  32.         }  
  33. }  
  34. }  
Step 16
 
Now, add a new view against the Index method by clicking the right mouse button. A new view has been added in the view folder.
 
Step 17
 
Now again go to the Azure portal, open the data explorer and click on the new documents option to insert a document in the product collection.
 
Insert data into Cosmos db 
 
Step 18
 
Now, run the application. It will display the insert item in the list page.
 
Product Index List 
Step 19
 
Now, create a new method for creating in the ProductController and add related view against that action method.
 
Step 20
 
Now, create an action method for the saving the data and write down the below code.
 
Create Product UI 
Step 21
 
Now run the application and try to insert a new record from the application.

Step 22
 
Now, go back to the Azure portal and check if the newly inserted data is shown in the Data Explorer or not.
 
Inserted Data View
 
Step 23
 
Similarly, add the edit records and delete records functionality along with the related view. Below is the complete code of ProductsController.cs file,
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5. using DataContextLayer;  
  6. using Microsoft.AspNetCore.Http;  
  7. using Microsoft.AspNetCore.Mvc;  
  8. using ModelClass;  
  9. using MongoDB.Bson;  
  10. using MongoDB.Driver;  
  11.   
  12.   
  13.   
  14. namespace CosmosDb_Demo_Crud.Controllers  
  15. {  
  16.     public class ProductsController : Controller  
  17.     {  
  18.         clsMongoDbDataContext _dbContext = new clsMongoDbDataContext("Products");  
  19.   
  20.         // GET: Products  
  21.         public async Task<ActionResult> Index()  
  22.         {  
  23.             IEnumerable<Product> products = null;  
  24.             using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(new BsonDocument()))  
  25.             {  
  26.                 while (await cursor.MoveNextAsync())  
  27.                 {  
  28.                     products = cursor.Current;  
  29.                 }  
  30.             }  
  31.             return View(products);  
  32.         }  
  33.   
  34.         // GET: Products/Details/5  
  35.         [HttpGet]  
  36.         public async Task<ActionResult> Details(string id)  
  37.         {  
  38.             if (!string.IsNullOrEmpty(id))  
  39.             {  
  40.                 FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));  
  41.                 IEnumerable<Product> entity = null;  
  42.                 using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(filter))  
  43.                 {  
  44.                     while (await cursor.MoveNextAsync())  
  45.                     {  
  46.                         entity = cursor.Current;  
  47.                     }  
  48.                 }  
  49.                 return View(entity.FirstOrDefault());  
  50.             }  
  51.             return RedirectToAction("Index");  
  52.         }  
  53.   
  54.         // GET: Products/Create  
  55.         public ActionResult Create()  
  56.         {  
  57.             return View();  
  58.         }  
  59.   
  60.         // POST: Products/Create  
  61.         [HttpPost]  
  62.         [ValidateAntiForgeryToken]  
  63.         public async Task<ActionResult> Create(Product model)  
  64.         {  
  65.             try  
  66.             {  
  67.                 if (!ModelState.IsValid)  
  68.                 {  
  69.                     return View(model);  
  70.                 }  
  71.   
  72.                 model.CreatedDate = DateTime.UtcNow;  
  73.   
  74.                 await this._dbContext.GetProducts.InsertOneAsync(model);  
  75.   
  76.                 return RedirectToAction("Index");  
  77.             }  
  78.             catch  
  79.             {  
  80.                 return View();  
  81.             }  
  82.         }  
  83.   
  84.         // GET: Products/Edit/5  
  85.         public async Task<ActionResult> Edit(string id)  
  86.         {  
  87.             if (!string.IsNullOrEmpty(id))  
  88.             {  
  89.                 FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));  
  90.                 IEnumerable<Product> entity = null;  
  91.                 using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(filter))  
  92.                 {  
  93.                     while (await cursor.MoveNextAsync())  
  94.                     {  
  95.                         entity = cursor.Current;  
  96.                     }  
  97.                 }  
  98.                 return View(entity.FirstOrDefault());  
  99.             }  
  100.             return View();  
  101.         }  
  102.   
  103.         // POST: Products/Edit/5  
  104.         [HttpPost]  
  105.         [ValidateAntiForgeryToken]  
  106.         public async Task<ActionResult> Edit(string id, Product model)  
  107.         {  
  108.             try  
  109.             {  
  110.                 if (!ModelState.IsValid)  
  111.                 {  
  112.                     return View(model);  
  113.                 }  
  114.                 model.UpdatedDate = DateTime.UtcNow;  
  115.                 model.ObjectId = ObjectId.Parse(id);  
  116.                 FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));  
  117.                 await this._dbContext.GetProducts.ReplaceOneAsync(filter, model, new UpdateOptions() { IsUpsert = true });                 
  118.                 return RedirectToAction("Index");  
  119.             }  
  120.             catch  
  121.             {  
  122.                 return RedirectToAction("Index");  
  123.             }  
  124.         }  
  125.   
  126.         [HttpGet]  
  127.         public async Task<ActionResult> Delete(string id)  
  128.         {  
  129.             if (!string.IsNullOrEmpty(id))  
  130.             {  
  131.                 FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));  
  132.                 IEnumerable<Product> entity = null;  
  133.                 using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(filter))  
  134.                 {  
  135.                     while (await cursor.MoveNextAsync())  
  136.                     {  
  137.                         entity = cursor.Current;  
  138.                     }  
  139.                 }  
  140.                 return View(entity.FirstOrDefault());  
  141.             }  
  142.             return View();  
  143.         }  
  144.   
  145.         // POST: Products/Delete/5  
  146.         [HttpPost]  
  147.         [ValidateAntiForgeryToken]  
  148.         public async Task<ActionResult> Delete(string id, Product model)  
  149.         {  
  150.             try  
  151.             {  
  152.                 if (string.IsNullOrEmpty(id))  
  153.                 {  
  154.                     return View(model);  
  155.                 }  
  156.                 model.ObjectId = ObjectId.Parse(id);  
  157.                 FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));  
  158.                 await this._dbContext.GetProducts.DeleteOneAsync(filter);  
  159.                 return RedirectToAction("Index");  
  160.             }  
  161.             catch  
  162.             {  
  163.                 return View();  
  164.             }  
  165.         }  
  166.     }  
  167. }  
Step 24
 
Now the add all CRUD-related operations methods; i.e., update existing data and also, delete any existing data with related views.
 

Conclusion

 
In this article, we discussed how to insert, update, or delete data in a MongoDB API based Cosmos DB Database in Azure portal using ASP.NET Core. I hope this article will help you understand. In the next article, we will discuss how to upload files in Azure Blob Storage. For any further query or clarification, ping me.