Implementing CRUD Operation With Entity Framework in Asp.net MVC: Part II


In the previous article, we were able to add a data layer to our demo application using the Database first approach with Ado.Net. In this article, we are going to create MVC pages to interact with the database.


Let us start by adding Student Controller. 
  • Right click on the controller folder > Add > Controller. 
  • Select MVC 5 Controller- Empty then Click Add.
  • Name the controller ‘Student’.

Click on Add and wait for the visual studio to complete the process.

Right click on the index method generated by VS to add Index view



Click on add and wait for the visual studio to complete the process.

Visual studio generated an empty index view.

Before we build and launch the solution, let us set the Student index page as the landing page for this demo application. In the solution explorer, navigate to App_Start > RouteConfig.

Edit the RouteConfig and change the controller to ‘Student’ like so



Also, modify the Layout like so:
 <!DOCTYPE html>  
 <html>  
 <head>  
   <meta charset="utf-8" />  
   <meta name="viewport" content="width=device-width, initial-scale=1.0">  
   <title>@ViewBag.Title - CRUD Demo</title>  
   @Styles.Render("~/Content/css")  
   @Scripts.Render("~/bundles/modernizr")  
 </head>  
 <body>  
   <div class="navbar navbar-inverse navbar-fixed-top">  
     <div class="container">  
       <div class="navbar-header">  
         <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">  
           <span class="icon-bar"></span>  
           <span class="icon-bar"></span>  
           <span class="icon-bar"></span>  
         </button>  
         @Html.ActionLink("CRUD Demo", "Index", "Student", new { area = "" }, new { @class = "navbar-brand" })  
       </div>  
       <div class="navbar-collapse collapse">  
         <ul class="nav navbar-nav">  
           <li>@Html.ActionLink("Students", "Index", "Student")</li>  
         </ul>  
       </div>  
     </div>  
   </div>  
   <div class="container body-content">  
     @RenderBody()  
     <hr />  
     <footer>  
       <p>&copy; @DateTime.Now.Year - CRUD Demo</p>  
     </footer>  
   </div>  
   @Scripts.Render("~/bundles/jquery")  
   @Scripts.Render("~/bundles/bootstrap")  
   @RenderSection("scripts", required: false)  
 </body>  
 </html>  

Save all the changes, build and run the solution, you should have an index page similar to :




Modify the index page, add a button to create new student and table to display students like so.

 @{  
     ViewBag.Title = "Index";  
     Layout = "~/Views/Shared/_Layout.cshtml";  
   }  
   <div class="row">  
 <h3>  
 Students</h3>  
 </div>  
 <div class="row" style="padding-bottom: 5px;">  
 <button class="btn btn-primary pull-right"><i class="fa fa-plus"></i>New Student</button>  
   </div>  
 <div class="row">  
 <table class="table table-striped table-responsive table-bordered">  
   <thead>  
 <tr>  
   <th>S/N</th>  
   <th>Name</th>  
   <th>Email</th>  
   <th>Phone Number</th>  
   <th>Date of Birth</th>  
   <th>Address</th>  
   <th>Actions</th>  
    </tr>  
 </thead>  
   <tbody>  
 <tr>  
   <td></td>  
   <td></td>  
   <td></td>  
   <td></td>  
   <td></td>  
   <td></td>  
   <td><button class="btn btn-xs btn-primary">view</button>|<button class="btn btn-xs btn-success">edit</button>|<button class="btn btn-xs btn-danger">delete</button></td>  
         </tr>  
 </tbody>  
     </table>  
 </div>  

Let us add student collection to be displayed on the index page. We start by creating a view model for the Student class generated by the Entity framework. By this approach, we are creating a layer on top of our database object and we are sure that we are not exposing directly the table structure.

Add a new class called StudentViewModel to the model's folder, modify like so:
 using System;  
 namespace MVCSampleCRUDOperation.Models  
 {  
   public class StudentViewModel  
   {  
     public int Student_Id { get; set; }  
     public string Student_Name { get; set; }  
     public Nullable<int> Student_Age { get; set; }  
     public string Student_Email { get; set; }  
     public string Phone_Number { get; set; }  
     public Nullable<System.DateTime> Student_DOB { get; set; }  
     public string Address_Line1 { get; set; }  
     public string Address_Line2 { get; set; }  
   }  
 }  
This view model (StudentViewModel) will be used as a data transfer object between the view pages, controllers and the database object.

Modify the Student controller like so:
 using MVCSampleCRUDOperation.Models;  
 using MVCSampleCRUDOperation.Models.DataAccessLayer;  
 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Web;  
 using System.Web.Mvc;  
 namespace MVCSampleCRUDOperation.Controllers  
 {  
   public class StudentController : Controller  
   {  
     MVCSampleCRUD_DBEntities dbContext = new MVCSampleCRUD_DBEntities();  
     public ActionResult Index()  
     {  
       var model = dbContext.Students.Select(m => new StudentViewModel()  
       {  
         Student_Id = m.Id,  
         Student_Age = m.Age,  
         Student_DOB = m.DOB,  
         Student_Email = m.Email,  
         Student_Name = m.Name,  
         Address_Line1 = m.AddressLine1,  
         Address_Line2 = m.AddressLine2,  
         Phone_Number = m.PhoneNumber  
       }).ToList();  
       return View(model);  
     }  
     protected override void Dispose(bool disposing)  
     {  
       dbContext.Dispose();  
       base.Dispose(disposing);  
     }  
   }  
 }  


On the controller, we created an instance of the context class, we also added a Dispose method to properly dispose our database context. List of the student was also spooled and sent to the index page as a model.

Let us now modify the index page to use the model like so:
 @model IEnumerable<MVCSampleCRUDOperation.Models.StudentViewModel>  
 @{  
   ViewBag.Title = "Index";  
   Layout = "~/Views/Shared/_Layout.cshtml";  
 }  
 <div class="row">  
   <h3>Students</h3>  
 </div>  
 <div class="row" style="padding-bottom: 5px;">  
   <a href="~/Student/CreateStudent" class="btn btn-primary pull-right">New Student</a>  
 </div>  
 <div class="row">  
   <table class="table table-striped table-responsive table-bordered">  
     <thead>  
       <tr>  
         <th>S/N</th>  
         <th>Name</th>  
         <th>Email</th>  
         <th>Phone Number</th>  
         <th>Date of Birth</th>  
         <th>Address</th>  
         <th>Actions</th>  
       </tr>  
     </thead>  
     <tbody>  
       @{  
         int i = 1;  
       }  
       @foreach (var item in Model)  
       {  
         <tr>  
           <td>@i</td>  
           <td>@item.Student_Name</td>  
           <td>@item.Student_Email</td>  
           <td>@item.Phone_Number</td>  
           <td>@item.Student_DOB.Value.ToString("dd-MM-yyyy")</td>  
           <td>@item.Address_Line1</td>  
           <td><button class="btn btn-xs btn-primary" onclick="viewStudentfn('@item.Student_Id')">view</button>|<button class="btn btn-xs btn-success" onclick="editStudentfn('@item.Student_Id')">edit</button>|<button class="btn btn-xs btn-danger" onclick="deleteStudentfn('@item.Student_Id','@item.Student_Name')">delete</button></td>  
         </tr>  
         i++;  
       }  
     </tbody>  
   </table>  
 </div>  

First, we added a collection of students as a model, we now modify the table body to loop through the model taking advantage of the Razor view engine which enables us to combine C# codes with HTML. You can learn more on Razor codes in MVC.

Save all the changes, build and run the solution, you should have the following




Since there is no record yet in the student table, the table is empty.

Now, let us add a "create page" to the solution so as to bring in new students to our collection.

Add the following method to Student controller

 public ActionResult CreateStudent()  
  {  
    return View();  
  }  

Right-click on the method name and select add view, wait for the visual studio to complete the process. Modify the generated view as follow:

 @model MVCSampleCRUDOperation.Models.StudentViewModel  
 @{  
   ViewBag.Title = "CreateStudent";  
   Layout = "~/Views/Shared/_Layout.cshtml";  
 }  
 <h2>Create Student</h2>  
 <p></p>  
 <div class="row">  
   @using( Html.BeginForm("CreateStudent", "student", FormMethod.Post, new { @class = "form-horizontal", id = "newStudentForm" }))  
   {  
   <div class="form-group">  
     <div class="col-md-10 col-md-offset-2" style="color:red">  
       <p>@Html.ValidationSummary()</p>  
     </div>  
   </div>  
   <div class="form-group">  
     <label class="control-label col-md-2">  
       Full Name  
     </label>  
     <div class="col-md-3">  
       @Html.TextBoxFor(model => model.Student_Name, new { placeholder = "Full Name", @class = "form-control" })  
     </div>  
   </div>  
   <div class="form-group">  
     <label class="control-label col-md-2">  
       Email  
     </label>  
     <div class="col-md-3">  
       @Html.TextBoxFor(model => model.Student_Email, new { placeholder = "Email", @class = "form-control" })  
     </div>  
   </div>  
   <div class="form-group">  
     <label class="control-label col-md-2">  
       Mobile  
     </label>  
     <div class="col-md-3">  
       @Html.TextBoxFor(model => model.Phone_Number, new { placeholder = "Phone Number", @class = "form-control" })  
     </div>  
   </div>  
   <div class="form-group">  
     <label class="control-label col-md-2">  
       Date of Birth  
     </label>  
     <div class="col-md-3">  
       @Html.TextBoxFor(model => model.Student_DOB, new { placeholder = "Date of Birth [mm/dd/yyyy]", @class = "form-control" })  
     </div>  
   </div>  
   <div class="form-group">  
     <label class="control-label col-md-2">  
       Address  
     </label>  
     <div class="col-md-3">  
       @Html.TextBoxFor(model => model.Address_Line1, new { placeholder = "Line 1", @class = "form-control" })  
     </div>  
   </div>  
   <div class="form-group">  
     <div class="col-md-3 col-md-offset-2">  
       @Html.TextBoxFor(model => model.Address_Line2, new { placeholder = "Line 2", @class = "form-control" })  
     </div>  
   </div>  
   <div class="form-group">  
     <div class="col-md-3 col-md-offset-2">  
       <button class="btn btn-primary btn-sm" id="btnAdd" type="submit">Add</button>  
       <button class="btn btn-warning btn-sm" id="btnRest" type="reset">Reset</button>  
       <a href="~/Student/index" class="btn btn-danger btn-sm">Close</a>  
     </div>  
   </div>  
   }  
 </div>  

In the above code, we added the student model and we created a strongly typed form. Three buttons were added to submit the form, reset and go back to the student index page.

Replace the create button on the index page with the following

  <a href="~/Student/CreateStudent" class="btn btn-primary pull-right">New Student</a>  

Save all changes, build and run the project. Click on create new student button you should have the following




Let us add post action method to the student controller

On the student controller, add the following method

    [HttpPost]  
     public ActionResult CreateStudent(StudentViewModel model)  
     {  
       try  
       {  
         var student = new Student()  
         {  
           Name = model.Student_Name,  
           PhoneNumber = model.Phone_Number,  
           DOB = model.Student_DOB,  
           Email = model.Student_Email,  
           AddressLine1 = model.Address_Line1,  
           AddressLine2 = model.Address_Line2,  
           Age = DateTime.Now.Subtract(model.Student_DOB.Value).Days  
         };  
         dbContext.Students.Add(student);  
         if (dbContext.SaveChanges() > 0)  
         {  
           return RedirectToAction("Index");  
         }  
       }  
       catch (Exception ex)  
       {  
         ModelState.AddModelError("",$"Error {ex?.Message}");  
         return View(model);  
       }  
       ModelState.AddModelError("", "Error occurred while saving record, please try again");  
       return View(model);  
     }  

Note that the post method ‘CreateStudent’ have the same name as the previous method but it is decorated with ‘HttpPost’ attribute. This allows the compiler to know which method to call for post action and get action.

The method takes a parameter of type ‘StudentViewModel ‘. On submitting a new student, the compiler will automatically bind the submit data to ‘StudentViewModel ‘ because the student form is strongly typed of ‘StudentViewModel’. New Student object is now created and added to the student context. SaveChanges method of dbcontext is called to persist the data into the database, if this process is successful, the page will be redirected to the index page but if it fails, the Create page is returned with the model, and an error message added to ModelState.

Save all changes, build and run the project.
Navigate to the student creation page and add a new student.

Note that no validation was added, but we have tried to catch any exception that may occur when posting new student using try catch.
This project was also intended to be kept as simple as much as possible.

In this article, we demonstrated how to persist data into the database using Entity framework and MVC. In the next article, we will focus on previewing, editing and deleting a student from the database.

Download Complete Source Code

Previous Article                                                                                                                   Next Article


Implementing CRUD Operation With Entity Framework in Asp.net MVC: Part II Implementing CRUD Operation With Entity Framework in Asp.net MVC: Part II Reviewed by Akintunde Toba on March 06, 2019 Rating: 5

No comments:

Home Ads

Powered by Blogger.