Use MongoDB in ASP.NET Core (Part - 2, CRUD operations)
In Part 1 of this
article we discussed how to perform CRUD operations using MongoDB console
client. In this part we will learn to perform CRUD operations using ASP.NET Core
and MongoDB driver for .NET Core.
Ok. Let's begin.
Our ASP.NET Core application that we are going to develop in this article
looks like this :

The Index view shown above renders a list of employees in a MongoDB database
(FirstDatabase that we created in
Part - 1). You can then
add new employees, modify existing employees, or delete an employee.
Begin by creating a new ASP.NET Core MVC application. To work with MongoDB
database we need to add a NuGet package - MongoDB.Driver. The following figure
shows this package in Manage NuGet Packages dialog.

This package provides a MongoDB driver that you can use to connect with the
database and perform database operations.
Creating Employee model
Next, add a model class named Employee in the Models folder. This class
represents the document that you wish to store in a MongoDB collection.
public class Employee
{
[BsonId]
public ObjectId Id { get; set; }
[BsonElement]
public int EmployeeID { get; set; }
[BsonElement]
public string FirstName { get; set; }
[BsonElement]
public string LastName { get; set; }
}
The Employee class consists of four properties namely Id, EmployeeID,
FirstName, and LastName. The Id property is the _id value assigned by MongoDB
and hence it is decorated with [BsonId] attribute. The EmployeeID, FirstName,
and LastName properties are decorated with [BsonElement] attribute indicating
that they are BSON (binary representation of JSON data) elements.
Now open the HomeController and add the following code to it :
public class HomeController : Controller
{
private IMongoCollection<Employee> collection;
public HomeController()
{
var client = new MongoClient("mongodb://localhost:27017");
IMongoDatabase db = client.GetDatabase("FirstDatabase");
this.collection = db.GetCollection<Employee>("Employees");
}
}
The code declares a class level variable of IMongoCollection<Employee>. The
IMongoCollection interface represents a MongoDB collection.
The constructor creates an instance of MongoClient. As the name suggests the
MongoClient class acts as a client to the MongoDB database server. We pass a URI
that specifies a port where MongoDB server is listening. The default port is
27017 and you can also see it on the Mongod console window (read
Part -1 for more details).
Then we call GetDatabase() method on the MongoClient and specify the database
name to connect (FirstDatabase in this case). The GetDatabase() return an
IMongoDatabase object. Then Employees collection is retrieved using the
GetCollection() method of IMongoDatabase.
Now that we have access to the Employees collection, we can use it to perform
CRUD operations.
Displaying a list of employees
Modify the Index() action of HomeController as shown below :
public IActionResult Index()
{
var model = collection.Find
(FilterDefinition<Employee>.Empty).ToList();
return View(model);
}
The above code calls the Find() method on the Employees collection to
retrieve a list of all employees. The Find() method accepts a FilterDefination
object representing a find criteria. Since we want to fetch all the records we
pass Empty there. The List of Employee objects is then passed to the Index view.
The Index.cshtml that renders the Employee list is shown below :
@model List<MongoDBDemo.Models.Employee>
<h1>List of Employees</h1>
<h2>@TempData["Message"]</h2>
<a asp-controller="Home" asp-action="Insert">
Add New Employee</a>
<br /><br />
<table border="1" cellpadding="10">
@foreach(var item in Model)
{
<tr>
<td>@item.EmployeeID</td>
<td>@item.FirstName</td>
<td>@item.LastName</td>
<td>
<a asp-controller="Home" asp-action="Update"
asp-route-id="@item.Id">Edit</a>
</td>
<td>
<a asp-controller="Home" asp-action="ConfirmDelete"
asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</table>
The Index view is quite straightforward and hence I won't go into too much
details. Note that ObjectId of an Employee is passed in the route parameter in
the Edit and Delete links.
Adding a new Employee
When you click Add New Employee link on the Index view, you are taken to the
Insert view :

Here you can enter an Employee details such as EmployeeID, FirstName, and
LastName and hit the Save button to add the Employee.
The following markup shows how Insert.cshtml does its job :
@model MongoDBDemo.Models.Employee
<h1>Insert Employee</h1>
<h2>@ViewBag.Message</h2>
<form asp-controller="Home" asp-action="Insert"
method="post">
<table border="1" cellpadding="10">
<tr>
<td>Employee ID :</td>
<td><input asp-for="EmployeeID" /></td>
</tr>
<tr>
<td>First Name :</td>
<td><input asp-for="FirstName" /></td>
</tr>
<tr>
<td>Last Name :</td>
<td><input asp-for="LastName" /></td>
</tr>
<tr>
<td colspan="2">
<button type="submit">Save</button>
</td>
</tr>
</table>
</form>
Notice that the <form> POSTs to Insert() action.
The two Insert() actions responsible for adding the Employee are shown below
:
public IActionResult Insert()
{
return View();
}
[HttpPost]
public IActionResult Insert(Employee emp)
{
collection.InsertOne(emp);
ViewBag.Message = "Employee added successfully!";
return View();
}
Notice t he code shown in bold letters. We call InsertOne() method on
Employees collection to add a new employee. A success message is also displayed
on the Insert view.
Modifying an existing Employee
When you click on the Edit link of a particular employee from the listing,
you are taken to the Update view shown below :

The Update view looks similar to the Insert view but it shows an existing
Employee details for editing.
The markup of Update,cshtml is shown below :
@model MongoDBDemo.Models.Employee
<h1>Update Employee</h1>
<h2>@ViewBag.Message</h2>
<form asp-controller="Home" asp-action="Update" method="post">
<input type="hidden" name="Id" value="@Model.Id.ToString()" />
<table border="1" cellpadding="10">
<tr>
<td>Employee ID :</td>
<td><input asp-for="EmployeeID"
readonly="readonly" /></td>
</tr>
<tr>
<td>First Name :</td>
<td><input asp-for="FirstName" /></td>
</tr>
<tr>
<td>Last Name :</td>
<td><input asp-for="LastName" /></td>
</tr>
<tr>
<td colspan="2">
<button type="submit">Save</button>
</td>
</tr>
</table>
</form>
Notice the code marked in bold letters. We store the Id property of the
Employee being edited into a hidden form field. This is required for model
binding to work as expected. We need Id during update operation and hence we
store it this way.
Also notice that EmployeeID textbox is marked as readonly since we don't want
to modify this field.
The Update <form> submits to Update() action. The two Update() actions
responsible for the update operation are shown below :
public IActionResult Update(string id)
{
ObjectId oId = new ObjectId(id);
Employee emp = collection.Find(e => e.Id
== oId).FirstOrDefault();
return View(emp);
}
[HttpPost]
public IActionResult Update(string id,Employee emp)
{
emp.Id = new ObjectId(id);
var filter = Builders<Employee>.
Filter.Eq("Id", emp.Id);
var updateDef = Builders<Employee>.Update.
Set("FirstName", emp.FirstName);
updateDef = updateDef.Set("LastName", emp.LastName);
var result = collection.UpdateOne(filter, updateDef);
if (result.IsAcknowledged)
{
ViewBag.Message = "Employee updated successfully!";
}
else
{
ViewBag.Message = "Error while updating Employee!";
}
return View(emp);
}
The GET Update() action converts the string id into an ObjectId and then
passes to the Find() method. This way we retrieve an Employee whose Id matches
with what was passed in the id route parameter.
The POST Update() action updates the modified Employee into the database. To
accomplish this task we prepare a FilterDefinition and an UpdateDefinition. The
FilterDefinition specifies a criteria used while updating a document. In our
case the criteria specifies that Id property should match with the specified
Employee's Id value. The UpdateDefinition specifies the modified properties and
their new values.
Then we call UpdateOne() method on the Employees collection and pass the
FilterDefinition and UpdateDefinition objects we just constructed.
The result.IsAcknowledged property tells us whether the update operation was
successful or now.
Deleting an existing Employee
When you click on the Delete link on the Index view, you are taken to the
ConfirmDelete view. This view is shown below :

Upon clicking the Delete button Delete() action is called and the Employee is
removed from the database. The markup of ConfirmDelete.cshtml is shown below :
@model MongoDBDemo.Models.Employee
<h2>Do you want to delete this employee?</h2>
<form asp-controller="Home" asp-action="Delete" method="post">
<input type="hidden" name="Id"
value="@Model.Id.ToString()" />
<table border="1" cellpadding="10">
<tr>
<td>Employee ID :</td>
<td>@Model.EmployeeID</td>
</tr>
<tr>
<td>First Name :</td>
<td>@Model.FirstName</td>
</tr>
<tr>
<td>Last Name :</td>
<td>@Model.LastName</td>
</tr>
<tr>
<td colspan="2">
<button type="submit">Delete</button>
</td>
</tr>
</table>
</form>
The ConfirmDelete view also stores the ObjectId into a hidden form field. The
ConfirmDelete() action and the Delete() action is shown below :
public IActionResult ConfirmDelete(string id)
{
ObjectId oId = new ObjectId(id);
Employee emp = collection.Find(e =>
e.Id == oId).FirstOrDefault();
return View(emp);
}
[HttpPost]
public IActionResult Delete(string id)
{
ObjectId oId = new ObjectId(id);
var result = collection.DeleteOne<Employee>
(e => e.Id == oId);
if (result.IsAcknowledged)
{
TempData["Message"] = "Employee deleted successfully!";
}
else
{
TempData["Message"] = "Error while deleting Employee!";
}
return RedirectToAction("Index");
}
The ConfirmDelete() action is quite similar to Update() GET action. The
Delete() action accepts the Id of an Employee to be deleted and converts it into
an ObjectId. The DeleteOne() method of Employees collection specifies the
deletion criteria to be the matching Id value.
This completes all that is required to perform CRUD operations. Before you
run the ASP.NET Core application make sure to start the MongoDB server using the
mongod.exe (see Part - 1
for more details). Then start the ASP.NET Core application and try performing
all the operations.
That's it for now! Keep coding!!