Introduction

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. namespace ModelClass
  8. {
  9. public class Product
  10. {
  11. public Product()
  12. {
  13. CreatedDate = DateTime.Now;
  14. }
  15. [BsonId]
  16. [JsonProperty("objectId"), JsonConverter(typeof(ObjectIdConverter))]
  17. public ObjectId ObjectId { get; set; }
  18. [Key]
  19. public int ProductId { get; set; }
  20. [Required(ErrorMessage = "Please Enter Name")]
  21. [Column(TypeName = "varchar(50)")]
  22. public string Name { get; set; }
  23. public decimal UnitPrice { get; set; }
  24. [Required(ErrorMessage = "Please Enter Description")]
  25. [Column(TypeName = "varchar(500)")]
  26. public string Description { get; set; }
  27. [Column(TypeName = "varchar(50)")]
  28. public string ImageName { get; set; }
  29. [Column(TypeName = "varchar(250)")]
  30. public string ImagePath { get; set; }
  31. public DateTime CreatedDate { get; set; }
  32. public DateTime? UpdatedDate { get; set; }
  33. }
  34. }
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. namespace DataContextLayer.AppConfig
  7. {
  8. public static class AppConfiguration
  9. {
  10. private static IConfiguration currentConfig;
  11. public static void SetConfig(IConfiguration configuration)
  12. {
  13. currentConfig = configuration;
  14. }
  15. public static string GetConfiguration(string configKey)
  16. {
  17. try
  18. {
  19. string connectionString = currentConfig.GetConnectionString(configKey);
  20. return connectionString;
  21. }
  22. catch (Exception ex)
  23. {
  24. throw (ex);
  25. }
  26. return "";
  27. }
  28. }
  29. }
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. namespace CosmosDb_Demo_Crud
  14. {
  15. public class Startup
  16. {
  17. public Startup(IConfiguration configuration)
  18. {
  19. Configuration = configuration;
  20. }
  21. public IConfiguration Configuration { get; }
  22. // This method gets called by the runtime. Use this method to add services to the container.
  23. public void ConfigureServices(IServiceCollection services)
  24. {
  25. services.Configure<CookiePolicyOptions>(options =>
  26. {
  27. // This lambda determines whether user consent for non-essential cookies is needed for a given request.
  28. options.CheckConsentNeeded = context => true;
  29. options.MinimumSameSitePolicy = SameSiteMode.None;
  30. });
  31. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  32. services.AddSingleton(_ => Configuration);
  33. }
  34. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  35. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  36. {
  37. if (env.IsDevelopment())
  38. {
  39. app.UseDeveloperExceptionPage();
  40. }
  41. else
  42. {
  43. app.UseExceptionHandler("/Home/Error");
  44. // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
  45. app.UseHsts();
  46. }
  47. app.UseHttpsRedirection();
  48. app.UseStaticFiles();
  49. app.UseCookiePolicy();
  50. AppConfiguration.SetConfig(Configuration);
  51. app.UseMvc(routes =>
  52. {
  53. routes.MapRoute(
  54. name: "default",
  55. template: "{controller=Products}/{action=Index}/{id?}"
  56. );
  57. });
  58. }
  59. }
  60. }
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. namespace DataContextLayer
  6. {
  7. public class clsMongoDbDataContext
  8. {
  9. private string _connectionStrings = string.Empty;
  10. private string _databaseName = string.Empty;
  11. private string _collectionName = string.Empty;
  12. private readonly IMongoClient _client;
  13. private readonly IMongoDatabase _database;
  14. public clsMongoDbDataContext(string strCollectionName)
  15. {
  16. this._collectionName = strCollectionName;
  17. this._connectionStrings = AppConfiguration.GetConfiguration("ServerName");
  18. this._databaseName = AppConfiguration.GetConfiguration("DatabaseName");
  19. this._client = new MongoClient(_connectionStrings);
  20. this._database = _client.GetDatabase(_databaseName);
  21. }
  22. public IMongoClient Client
  23. {
  24. get { return _client; }
  25. }
  26. public IMongoDatabase Database
  27. {
  28. get { return _database; }
  29. }
  30. public IMongoCollection<Product> GetProducts
  31. {
  32. get { return _database.GetCollection<Product>(_collectionName); }
  33. }
  34. }
  35. }
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. namespace CosmosDb_Demo_Crud.Controllers
  12. {
  13. public class ProductsController : Controller
  14. {
  15. clsMongoDbDataContext _dbContext = new clsMongoDbDataContext("Products");
  16. // GET: Products
  17. public async Task<ActionResult> Index()
  18. {
  19. IEnumerable<Product> products = null;
  20. using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(new BsonDocument()))
  21. {
  22. while (await cursor.MoveNextAsync())
  23. {
  24. products = cursor.Current;
  25. }
  26. }
  27. return View(products);
  28. }
  29. }
  30. }
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. namespace CosmosDb_Demo_Crud.Controllers
  12. {
  13. public class ProductsController : Controller
  14. {
  15. clsMongoDbDataContext _dbContext = new clsMongoDbDataContext("Products");
  16. // GET: Products
  17. public async Task<ActionResult> Index()
  18. {
  19. IEnumerable<Product> products = null;
  20. using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(new BsonDocument()))
  21. {
  22. while (await cursor.MoveNextAsync())
  23. {
  24. products = cursor.Current;
  25. }
  26. }
  27. return View(products);
  28. }
  29. // GET: Products/Details/5
  30. [HttpGet]
  31. public async Task<ActionResult> Details(string id)
  32. {
  33. if (!string.IsNullOrEmpty(id))
  34. {
  35. FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));
  36. IEnumerable<Product> entity = null;
  37. using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(filter))
  38. {
  39. while (await cursor.MoveNextAsync())
  40. {
  41. entity = cursor.Current;
  42. }
  43. }
  44. return View(entity.FirstOrDefault());
  45. }
  46. return RedirectToAction("Index");
  47. }
  48. // GET: Products/Create
  49. public ActionResult Create()
  50. {
  51. return View();
  52. }
  53. // POST: Products/Create
  54. [HttpPost]
  55. [ValidateAntiForgeryToken]
  56. public async Task<ActionResult> Create(Product model)
  57. {
  58. try
  59. {
  60. if (!ModelState.IsValid)
  61. {
  62. return View(model);
  63. }
  64. model.CreatedDate = DateTime.UtcNow;
  65. await this._dbContext.GetProducts.InsertOneAsync(model);
  66. return RedirectToAction("Index");
  67. }
  68. catch
  69. {
  70. return View();
  71. }
  72. }
  73. // GET: Products/Edit/5
  74. public async Task<ActionResult> Edit(string id)
  75. {
  76. if (!string.IsNullOrEmpty(id))
  77. {
  78. FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));
  79. IEnumerable<Product> entity = null;
  80. using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(filter))
  81. {
  82. while (await cursor.MoveNextAsync())
  83. {
  84. entity = cursor.Current;
  85. }
  86. }
  87. return View(entity.FirstOrDefault());
  88. }
  89. return View();
  90. }
  91. // POST: Products/Edit/5
  92. [HttpPost]
  93. [ValidateAntiForgeryToken]
  94. public async Task<ActionResult> Edit(string id, Product model)
  95. {
  96. try
  97. {
  98. if (!ModelState.IsValid)
  99. {
  100. return View(model);
  101. }
  102. model.UpdatedDate = DateTime.UtcNow;
  103. model.ObjectId = ObjectId.Parse(id);
  104. FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));
  105. await this._dbContext.GetProducts.ReplaceOneAsync(filter, model, new UpdateOptions() { IsUpsert = true });
  106. return RedirectToAction("Index");
  107. }
  108. catch
  109. {
  110. return RedirectToAction("Index");
  111. }
  112. }
  113. [HttpGet]
  114. public async Task<ActionResult> Delete(string id)
  115. {
  116. if (!string.IsNullOrEmpty(id))
  117. {
  118. FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));
  119. IEnumerable<Product> entity = null;
  120. using (IAsyncCursor<Product> cursor = await this._dbContext.GetProducts.FindAsync(filter))
  121. {
  122. while (await cursor.MoveNextAsync())
  123. {
  124. entity = cursor.Current;
  125. }
  126. }
  127. return View(entity.FirstOrDefault());
  128. }
  129. return View();
  130. }
  131. // POST: Products/Delete/5
  132. [HttpPost]
  133. [ValidateAntiForgeryToken]
  134. public async Task<ActionResult> Delete(string id, Product model)
  135. {
  136. try
  137. {
  138. if (string.IsNullOrEmpty(id))
  139. {
  140. return View(model);
  141. }
  142. model.ObjectId = ObjectId.Parse(id);
  143. FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("_id", ObjectId.Parse(id));
  144. await this._dbContext.GetProducts.DeleteOneAsync(filter);
  145. return RedirectToAction("Index");
  146. }
  147. catch
  148. {
  149. return View();
  150. }
  151. }
  152. }
  153. }
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.