CRUD Operations Using Knockout.JS and EntityFramework 5 in MVC4 Application

Download Source Code Via Dropbox or Download Source Code Via Google Drive

I. Introduction

I have been browsing multiple sites for a complete end-to-end tutorial or article upon CRUD operations using Knockout.JS and MVC 4. Unfortunately all I found were incomplete or short explanations. In my last article we learned about imlementation of CRUD in ASP.Net web forms using MVC and EntityFramework. This article is the continuation of the series. My effort in this article will be a kind of tutorial to explain how to set up the knockout.js environment in a MVC4 application and perform CRUD operations on it.

2. Our Road-Map

We'll stick to our agenda of Learning Knockout.JS as follows:

3.> Part 2: Complete end-to-end CRUD operations using Knockout.JS and Entity Framework in MVC4 application

We'll continue to explain KO step-by-step in this article;the following are the toics:

  1. Creating an MVC application.
  2. Creating CRUD action methods using Entity Framework 5.
  3. Perform CRUD operations using MVC4 and Entity Framework 5.
  4. Adding Knockout.JS to our MVC application.
  5. Perform CRUD operation using KO in our MVC 4 application.

Before we start, yet without going very deep into theory, I would like to provide an introduction to MVC, Entity Framework and Knockout.

4. MVC

Model: The business entity on which the overall application operates. Many applications use a persistent storage mechanism (such as a database) to store data. MVC does not specify the data access layer because it is understood to be encapsulated by the Model.

View: The user interface that renders the model into a form of interaction.

Controller: Handles a request from a view and updates the model that results in a change in a Model's state.

To implement MVC in .NET we need mainly three classes (View, Controller and Model).

5. Entity Framework

Let's have a look at the standard definition of Entity Framework given by Microsoft:

"The Microsoft ADO.NET Entity Framework is an Object/Relational Mapping (ORM) framework that enables developers to work with relational data as domain-specific objects, eliminating the need for most of the data access plumbing code that developers usually need to write. Using the Entity Framework, developers issue queries using LINQ, then retrieve and manipulate data as strongly typed objects. The Entity Framework's ORM implementation provides services like change tracking, identity resolution, lazy loading, and query translation so that developers can focus on their application-specific business logic rather than the data access fundamentals."

In simple terms, Entity Framework is an Object/Relational Mapping (ORM) framework. It is an enhancement to ADO.NET, an upper layer to ADO.Net that gives developers an automated mechanism for accessing and storing the data in the database.
I hope this gives a glimpse of an ORM and EntityFramework.

6. Knockout.JS

Knockout.JS (KO) is basically a JS library that enables Declarative Bindings using an "Observable" View Model on the client (browser) following an observer pattern approach, enabling the UI to bind and refresh itself automatically whenever the data bound is modified. Knockout.JS provides its own templating pattern that helps us to bind our view model data easily. KO works on the MVVM pattern, in other words Model-View-View Model.

As the architecture is shown, Views interact with View Models in a two-way binding manner, in other words when the model is changed the view updates itself and when the view is updated, the model too updates itself instantaneously.

KO provides the following 3 most important features:

Knockout features

The entire idea of KO derives from these three major functionalities. KO also helps in developing Single Page Applications (SPAs). SPAs are an out-of-the box new way of developing Rich Internet Applications (RIAs) in today's era.

7. Application Architecture

Application Architecture

The architecture is very much self-explanatory. The application works on a client-server model, where our MVC application or Web API application (not covered in this tutorial) will interact with an EntityFramework layer on the server side. The Entity Framework layer will be responsible for data transactions with the database.

On the client side we have HTML templates that will communicate with the server using Ajax calls and the templates will be bound to data via JSON objects through knockout observables (already explained in the first part).

8. MVC Application

Step 1: Create a database named LearningKO and add a table named student to it. The script of the table is as follows:


  1. USE [LearningKO]  
  2. GO  
  3. /****** Object: Table [dbo].[Student] Script Date: 12/04/2013 23:58:12 ******/  
  4. SET ANSI_NULLS ON  
  5. GO  
  6. SET QUOTED_IDENTIFIER ON  
  7. GO  
  8. CREATE TABLE [dbo].[Student](  
  9. [StudentId] [nvarchar](10) NOT NULL,  
  10. [FirstName] [nvarchar](50) NULL,  
  11. [LastName] [nvarchar](50) NULL,  
  12. [Age] [intNULL,  
  13. [Gender] [nvarchar](50) NULL,  
  14. [Batch] [nvarchar](50) NULL,  
  15. [Address] [nvarchar](50) NULL,  
  16. [Class] [nvarchar](50) NULL,  
  17. [School] [nvarchar](50) NULL,  
  18. [Domicile] [nvarchar](50) NULL,  
  19. CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED  
  20. (  
  21. [StudentId] ASC  
  22. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
  23. IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ONON [PRIMARY]  
  24. ON [PRIMARY]  
  25. GO  
  26. INSERT [dbo].[Student] ([StudentId], [FirstName], [LastName], [Age],   
  27. [Gender], [Batch], [Address], [Class], [School], [Domicile]) VALUES (N'1',  
  28.  N'Akhil', N'Mittal', 28, N'Male', N'2006', N'Noida', N'Tenth', N'LFS',   
  29. N'Delhi')  
  30.   
  31. INSERT [dbo].[Student] ([StudentId], [FirstName], [LastName], [Age],   
  32. [Gender], [Batch], [Address], [Class], [School], [Domicile]) VALUES (N'2',  
  33.  N'Parveen', N'Arora', 25, N'Male', N'2007', N'Noida', N'8th', N'DPS',   
  34. N'Delhi')  
  35.   
  36. INSERT [dbo].[Student] ([StudentId], [FirstName], [LastName], [Age],   
  37. [Gender], [Batch], [Address], [Class], [School], [Domicile]) VALUES (N'3',   
  38. N'Neeraj', N'Kumar', 38, N'Male', N'2011', N'Noida', N'10th', N'MIT',   
  39. N'Outside Delhi')  
  40.   
  41. INSERT [dbo].[Student] ([StudentId], [FirstName], [LastName], [Age],   
  42. [Gender], [Batch], [Address], [Class], [School], [Domicile]) VALUES (N'4',   
  43. N'Ekta', N'Mittal', 25, N'Female', N'2005', N' Noida', N'12th', N'LFS',   
  44. N'Delhi'

Create Database


Step 2:
Open your Visual Studio (the Visual Studio Version should be greater than or equal to 12 (Visual Studio 2013)) and add an MVC Internet application as in the following:

Open visual Studio

MVC Internet application

I have given it the name "KnockoutWithMVC4".

Step 3: Y>ou'll get a full structured MVC application with default Home controller in the Controller folder. By default Entity Framework is downloaded as a package inside the application folder; but if not then you can add an Entity Framework package by right-clicking the project, select "Manage Nugget packages" and search for and install Entity Framework as in the following:


nugget packages


entity framework


Step 4: Right-click on the project file, select "Add new item" and add an ADO .Net Entity Data Model, then use the following procedure in the wizard:

add new item


entity data model


Create a entity model from Database


Generate a model from the database, select your server and LearningKO database name. The connection string will automatically be added to your Web.Config, name that connection string "LearningKOEntities".Database Object Table

Select the tables to be added to the model. In our case it's Student Table.

tables added to the model

Step 5: Now add a new controller to the Controller folder, right-click the controller folder and add a controller named Student. Since we have already created our Datamodel, we can choose for an option where CRUD actions are created by the chosen Entity Framework Datamodel as in the following:

add a new controller


add controller

  • Name your controller "StudentController",
  • From the Scaffolding Options, select "MVC controller with read/write actions and views, using Entity Framework".
  • Select the Student Model class in the solution.
  • Select Data context class as LearningKOEntities that was added to our solution when we added the EF data model.
  • Select "Razor" as the rendering engine for views.
  • Click the "Advanced" options, select "Layout or master page" and select "_Layout.cshtml" from the shared folder.

Layout or master page

Step 6:
We see our student controller prepared with all the CRUD operation actions as shown below:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Data;  
  4. using System.Data.Entity;  
  5. using System.Linq;  
  6. using System.Web;  
  7. using System.Web.Mvc;  
  8. namespace KnockoutWithMVC4.Controllers  
  9. {  
  10.     public class StudentController : Controller  
  11.     {  
  12.         private LearningKOEntities db = new LearningKOEntities();  
  13.         //  
  14.         // GET: /Student/  
  15.         public ActionResult Index()  
  16.         {  
  17.             return View(db.Students.ToList());  
  18.         }  
  19.         // GET: /Student/Details/5  
  20.         public ActionResult Details(string id = null)  
  21.         {  
  22.             Student student = db.Students.Find(id);  
  23.             if (student == null)  
  24.             {  
  25.                 return HttpNotFound();  
  26.             }  
  27.             return View(student);  
  28.         }  
  29.         // GET: /Student/Create  
  30.         public ActionResult Create()  
  31.         {  
  32.             return View();  
  33.         }   
  34.         // POST: /Student/Create  
  35.         [HttpPost]  
  36.         [ValidateAntiForgeryToken]  
  37.         public ActionResult Create(Student student)  
  38.         {  
  39.             if (ModelState.IsValid)  
  40.             {  
  41.                 db.Students.Add(student);  
  42.                 db.SaveChanges();  
  43.                 return RedirectToAction("Index");  
  44.             }  
  45.             return View(student);  
  46.         }  
  47.         // GET: /Student/Edit/5  
  48.         public ActionResult Edit(string id = null)  
  49.         {  
  50.             Student student = db.Students.Find(id);  
  51.             if (student == null)  
  52.             {  
  53.                 return HttpNotFound();  
  54.             }  
  55.             return View(student);  
  56.         }  
  57.         // POST: /Student/Edit/5  
  58.         [HttpPost]  
  59.         [ValidateAntiForgeryToken]  
  60.         public ActionResult Edit(Student student)  
  61.         {  
  62.             if (ModelState.IsValid)  
  63.             {  
  64.                 db.Entry(student).State = EntityState.Modified;  
  65.                 db.SaveChanges();  
  66.                 return RedirectToAction("Index");  
  67.             }  
  68.             return View(student);  
  69.         }  
  70.         // GET: /Student/Delete/5  
  71.         public ActionResult Delete(string id = null)  
  72.         {  
  73.             Student student = db.Students.Find(id);  
  74.             if (student == null)  
  75.             {  
  76.                 return HttpNotFound();  
  77.             }  
  78.             return View(student);  
  79.         }  
  80.         //  
  81.         // POST: /Student/Delete/5  
  82.         [HttpPost, ActionName("Delete")]  
  83.         [ValidateAntiForgeryToken]  
  84.         public ActionResult DeleteConfirmed(string id)  
  85.         {  
  86.             Student student = db.Students.Find(id);  
  87.             db.Students.Remove(student);  
  88.             db.SaveChanges();  
  89.             return RedirectToAction("Index");  
  90.         }  
  91.         protected override void Dispose(bool disposing)  
  92.         {  
  93.             db.Dispose();  
  94.             base.Dispose(disposing);  
  95.         }  
  96.     }  
  97. }
Step 7: Open the "App_Start" folder and change the name of the controller from "Home" to "Student", the code will as in the following:


change the name of controller

 
  1. public static void RegisterRoutes(RouteCollection routes)  
  2. {  
  3.     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  4.     routes.MapRoute(  
  5.     name: "Default",  
  6.     url: "{controller}/{action}/{id}",  
  7.     defaults: new { controller = "Student", action = "Index", id = UrlParameter.Optional }  
  8. );  
  9. }
Step 8: Now press F5 to run the application. You'll see the list of all students we added to the table Student; while creating it, it is displayed. Since the CRUD operations are automatically written, we have action results for the display list and other Edit, Delete and Create operations.


Note that views for all the operations are created in the Views Folder under the Student Folder name.

run the application

Now you can perform all the operations on this list.

operations on this list

mvc Code

Since I have not provided any validation checks on the model or creating an existing student id, the code may break, so I am calling an Edit Action in the create when we find that the id already exists as in the following:

Edit Action

Now create new student as in the following:

create new student

We see that the student is created successfully and added to the list as in the following:

created successfully

The database is as in the following:

Database Table

Similarly an Edit is as in the following:

Edit student detail

Change any field and press "Save". The change will be reflected in the list and database as in the following:

change in the list and data base

A Delete is as in the following:

Delete student record

Student Deleted.

Student Deleted

And the database will be as in the following:

Check in Database

So, that's it, our first job is completed, in other words to create an MVC application and perform CRUD operations using Entity Framework 5.You can see that until now we have not written a single line of code. Yes that's the magic of MVC and EF. Cheers!

first job completed

9. Knockout Application

Our first job is well done, now to proceed to our primary target, in other words KO. Since KO depends largely on the MVVM pattern, we'll use MVVM at the client side and use our controller to be the same but modified just a little bit for returning JSON logic. You can learn about the MVVM pattern and KO theory in the first part of this article series.

Step 1: The jQuery and Knockout.js files are very important to be in the solution's script folder. Look for them and if you do not find them then add the packages for jQuery and Knockout in the same fashion as you added Entity Framework. Right-click the project, select "Manage Nugget packages" and search for jQuery then install it , then search for the Knockout package and install it.

Manage nugget packages

JQuery Validation


Install Knockoutjs

Step 2: Right-click the Scripts folder and on the folder named ViewModel. Add four JavaScript files to that folder, and name them as CreateVM.js, EditVM.js,DeleteVM.js and StudentListVM.js respectively.

These are View Model files added for communication with the Controller and ro render our View templates.

Step 3: Add some code to CreateVm.js as in the following:

  1. var urlPath = window.location.pathname;  
  2.   $(function () {  
  3.       ko.applyBindings(CreateVM);  
  4.   });  
  5.   var CreateVM = {  
  6.       Domiciles: ko.observableArray(['Delhi''Outside Delhi']),  
  7.       Genders: ko.observableArray(['Male''Female']),  
  8.       Students: ko.observableArray([]),  
  9.       StudentId: ko.observable(),  
  10.       FirstName: ko.observable(),  
  11.       LastName: ko.observable(),  
  12.       Age: ko.observable(),  
  13.       Batch: ko.observable(),  
  14.       Address: ko.observable(),  
  15.       Class: ko.observable(),  
  16.       School: ko.observable(),  
  17.       Domicile: ko.observable(),  
  18.       Gender: ko.observable(),  
  19.       SaveStudent: function () {  
  20.           $.ajax({  
  21.               url: '/Student/Create',  
  22.               type: 'post',  
  23.               dataType: 'json',  
  24.               data: ko.toJSON(this),  
  25.               contentType: 'application/json',  
  26.               success: function (result) {  
  27.               },  
  28.               error: function (err) {  
  29.                   if (err.responseText == "Creation Failed")  
  30.                   { window.location.href = '/Student/Index/'; }  
  31.                   else {  
  32.                       alert("Status:" + err.responseText);  
  33.                       window.location.href = '/Student/Index/'; ;  
  34.                   }  
  35.               },  
  36.               complete: function () {  
  37.                   window.location.href = '/Student/Index/';  
  38.               }  
  39.           });  
  40.       }  
  41.   };
 


On document load we apply bindings for CreateVM, then inside the view model method we initialize the observables to the properties of the Student that will be bound to the respective view.You can read more about observables in KO in the first part of the series. There is a save function that sends an Ajax request to the Student Controller's Create method, and gets a string result. data: ko.toJSON(this), in other words sending the object in JSON format to the controller method.

Student/Create Controller Method

Modify the code of the controller method of Create, to return JSON to the caller.The HTML templates bound with objects are actually bound to JSON properties, set in the methods of the view model using Knockout Observables.

The work is on the observer pattern, so that when the model is updated the views are automatically updated and when the views are updated the models update itself, this is called two-way binding.

Controller Code

  1. [HttpPost]  
  2. public string Create(Student student)  
  3. {  
  4.     if (ModelState.IsValid)  
  5.     {  
  6.        if (!StudentExists(student))  
  7.          db.Students.Add(student);  
  8.        else  
  9.          return Edit(student);  
  10.          db.SaveChanges();  
  11.         return "Student Created";  
  12.      }  
  13.     return "Creation Failed";  

View Code


Change the code of the views created previously to work with KO.

For "create.cshtml":

  1. <h2>  
  2.     Create</h2>  
  3. <fieldset>  
  4.     <legend>Create Student</legend>  
  5.     <div class="editor-label">  
  6.         Student id  
  7.     </div>  
  8.     <div class="editor-field">  
  9.         <input data-bind="value: StudentId" />  
  10.     </div>  
  11.     <div class="editor-label">  
  12.         First Name  
  13.     </div>  
  14.     <div class="editor-field">  
  15.         <input data-bind="value: FirstName" />  
  16.     </div>  
  17.     <div class="editor-label">  
  18.         Last Name  
  19.     </div>  
  20.     <div class="editor-field">  
  21.         <input data-bind="value: LastName" />  
  22.     </div>  
  23.     <div class="editor-label">  
  24.         Age  
  25.     </div>  
  26.     <div class="editor-field">  
  27.         <input data-bind="value: Age" />  
  28.     </div>  
  29.     <div class="editor-label">  
  30.         Gender  
  31.     </div>  
  32.     <div class="editor-field">  
  33.         <select data-bind="options: Genders, value: Gender, optionsCaption: 'Select Gender...'">  
  34.         </select>  
  35.     </div>  
  36.     <div class="editor-label">  
  37.         Batch  
  38.     </div>  
  39.     <div class="editor-field">  
  40.         <input data-bind="value: Batch" />  
  41.     </div>  
  42.     <div class="editor-label">  
  43.         Address  
  44.     </div>  
  45.     <div class="editor-field">  
  46.         <input data-bind="value: Address" />  
  47.     </div>  
  48.     <div class="editor-label">  
  49.         Class  
  50.     </div>  
  51.     <div class="editor-field">  
  52.         <input data-bind="value: Class" />  
  53.     </div>  
  54.     <div class="editor-label">  
  55.         School  
  56.     </div>  
  57.     <div class="editor-field">  
  58.         <input data-bind="value: School" />  
  59.     </div>  
  60.     <div class="editor-label">  
  61.         Domicile  
  62.     </div>  
  63.     <div class="item ">  
  64.         <select data-bind="options: Domiciles, value: Domicile, optionsCaption: 'Select Domicile...'">  
  65.         </select>  
  66.     </div>  
  67.     <p>  
  68.         <button type="button" data-bind="click: SaveStudent">  
  69.             Save Student To Database</button>  
  70.     </p>  
  71. </fieldset>  
  72. <div>  
  73.     <a href="@Url.Action("Index", "Student")" >Back to List</a>  
  74.  </div>  
  75. @section Scripts {  
  76.     @Scripts.Render("~/Scripts/ViewModels/CreateVM.js")  
  77. }
You can see that I have used the data-bind attribute of HTML5 to bind the View elements to the View Models properties like data-bind="value: StudentId" , the same applies to all the editable elements. The Click button is bound to the SaveStudent method of the view model.

 
At the end of the page we have registered the CreateVM.js view model for this specific view by

  1. @section Scripts {  
  2.     @Scripts.Render("~/Scripts/ViewModels/CreateVM.js")  

>Tag.


Step 3: We do the same set of operations for all the views, View models and the Controller method, the code is as below.

For Edit

View Model

Code is to be added in StudentListVM for Edit View Model, since it only performs a get when it loads.

Controller methods

  1. public ActionResult Edit(string id=null)  
  2. {  
  3.    Student student = db.Students.Find(id);  
  4.    if (student == null)  
  5.    {  
  6.    return null;  
  7. }  
  8. JavaScriptSerializer serializer = new JavaScriptSerializer();  
  9. ViewBag.InitialData = serializer.Serialize(student);  
  10. return View();  
  11. }  
  12. /// <summary>  
  13. /// Edits particular student details  
  14. /// </summary>  
  15. /// <param name="student"></param>  
  16. /// <returns></returns>  
  17. [HttpPost]  
  18. public string Edit(Student student)  
  19. {  
  20.    if (ModelState.IsValid)  
  21.    {  
  22.        db.Entry(student).State = EntityState.Modified;  
  23.        db.SaveChanges();  
  24.        return "Student Edited";  
  25.     }  
  26.     return "Edit Failed";  


View

  1. <h2>  
  2.     Edit</h2>  
  3. <fieldset>  
  4.     <legend>Edit Student</legend>  
  5.     <div class="editor-label">  
  6.         Student id  
  7.     </div>  
  8.     <div class="editor-field">  
  9.         <input data-bind="value: StudentId" readonly="readonly" />  
  10.     </div>  
  11.     <div class="editor-label">  
  12.         First Name  
  13.     </div>  
  14.     <div class="editor-field">  
  15.         <input data-bind="value: FirstName" />  
  16.     </div>  
  17.     <div class="editor-label">  
  18.         Last Name  
  19.     </div>  
  20.     <div class="editor-field">  
  21.         <input data-bind="value: LastName" />  
  22.     </div>  
  23.     <div class="editor-label">  
  24.         Age  
  25.     </div>  
  26.     <div class="editor-field">  
  27.         <input data-bind="value: Age" />  
  28.     </div>  
  29.     <div class="editor-label">  
  30.         Gender  
  31.     </div>  
  32.     <div class="editor-field">  
  33.         <select data-bind="options: Genders, value: Gender, optionsCaption: 'Select Gender...'">  
  34.         </select>  
  35.     </div>  
  36.     <div class="editor-label">  
  37.         Batch  
  38.     </div>  
  39.     <div class="editor-field">  
  40.         <input data-bind="value: Batch" />  
  41.     </div>  
  42.     <div class="editor-label">  
  43.         Address  
  44.     </div>  
  45.     <div class="editor-field">  
  46.         <input data-bind="value: Address" />  
  47.     </div>  
  48.     <div class="editor-label">  
  49.         Class  
  50.     </div>  
  51.     <div class="editor-field">  
  52.         <input data-bind="value: Class" />  
  53.     </div>  
  54.     <div class="editor-label">  
  55.         School  
  56.     </div>  
  57.     <div class="editor-field">  
  58.         <input data-bind="value: School" />  
  59.     </div>  
  60.     <div class="editor-label">  
  61.         Domicile  
  62.     </div>  
  63.     <div class="editor-field">  
  64.         <select data-bind="options: Domiciles, value: Domicile, optionsCaption: 'Select Domicile...'">  
  65.         </select>  
  66.     </div>  
  67.     <p>  
  68.         <button type="button" data-bind="click: SaveStudent">  
  69.             Save Student To Database</button>  
  70.     </p>  
  71. </fieldset>  
  72.     <div>  
  73.          <a href="@Url.Action("Index", "Student")">Back to List</a>  
  74.     </div>  
  75. @section Scripts {  
  76. <script>  
  77.                $(function () {  
  78.     ko.applyBindings(EditVM);  
  79. });  
  80.     var initialData = '@Html.Raw(ViewBag.InitialData)'//get the raw json  
  81.     var parsedJSON = $.parseJSON(initialData); //parse the json client side  
  82.     var EditVM = {  
  83.         Domiciles: ko.observableArray(['Delhi''Outside Delhi']),  
  84.         Genders: ko.observableArray(['Male''Female']),  
  85.         Students: ko.observableArray([]),  
  86.         StudentId: ko.observable(parsedJSON.StudentId),  
  87.         FirstName: ko.observable(parsedJSON.FirstName),  
  88.         LastName: ko.observable(parsedJSON.LastName),  
  89.         Age: ko.observable(parsedJSON.Age),  
  90.         Batch: ko.observable(parsedJSON.Batch),  
  91.         Address: ko.observable(parsedJSON.Address),  
  92.         Class: ko.observable(parsedJSON.Class),  
  93.         School: ko.observable(parsedJSON.School),  
  94.         Domicile: ko.observable(parsedJSON.Domicile),  
  95.         Gender: ko.observable(parsedJSON.Gender),  
  96.         SaveStudent: function () {  
  97.             $.ajax({  
  98.                 url: '/Student/Edit',  
  99.                 type: 'post',  
  100.                 dataType: 'json',  
  101.                 data: ko.toJSON(this),  
  102.                 contentType: 'application/json',  
  103.                 success: function (result) {  
  104.                 },  
  105.                 error: function (err) {  
  106.                     if (err.responseText == "Creation Failed")  
  107.                     { window.location.href = '/Student/Index/'; }  
  108.                     else {  
  109.                         alert("Status:" + err.responseText);  
  110.                         window.location.href = '/Student/Index/'; ;  
  111.                     }  
  112.                 },  
  113.                 complete: function () {  
  114.                     window.location.href = '/Student/Index/';  
  115.                 }  
  116.             });  
  117.         }  
  118.     };  
  119. </script>  
  120. }
>For Delete


View Model


Code is to be added in StudentListVM for the Edit View Model, since it only performs a get when it loads.

Controller methods

  1. public ActionResult Delete(string id = null)  
  2. {  
  3.     Student student = db.Students.Find(id);  
  4.     if (student == null)  
  5.     {  
  6.         return null;  
  7.     }  
  8.     JavaScriptSerializer serializer = new JavaScriptSerializer();  
  9.     ViewBag.InitialData = serializer.Serialize(student);  
  10.     return View();  
  11. }  
  12. /// <summary>  
  13. /// Delete particular student details  
  14. /// </summary>  
  15. /// <param name="student"></param>  
  16. /// <returns></returns>  
  17. [HttpPost]  
  18. public string Delete(Student student)  
  19. {  
  20.     Student studentDetail = db.Students.Find(student.StudentId);  
  21.     db.Students.Remove(studentDetail);  
  22.     db.SaveChanges();  
  23.     return "Student Deleted";  

 

View

  1. @model KnockoutWithMVC4.Student  
  2. @{  
  3.     ViewBag.Title = "Delete";  
  4. }  
  5. <h2>  
  6.     Delete Student</h2>  
  7. <h3>  
  8.     Are you sure you want to delete this?</h3>  
  9. <fieldset>  
  10.     <legend>Delete</legend>  
  11.     <div class="display-label">  
  12.         Student Id  
  13.     </div>  
  14.     <div class="display-field">  
  15.         <input data-bind="value: StudentId" />  
  16.     </div>  
  17.     <div class="display-label">  
  18.         First Name  
  19.     </div>  
  20.     <div class="display-field">  
  21.         <input data-bind="value: FirstName" />  
  22.     </div>  
  23.     <div class="display-label">  
  24.         Last Name  
  25.     </div>  
  26.     <div class="display-field">  
  27.         <input data-bind="value: LastName" />  
  28.     </div>  
  29.     <div class="display-label">  
  30.         Age  
  31.     </div>  
  32.     <div class="display-field">  
  33.         <input data-bind="value: Age" />  
  34.     </div>  
  35.     <div class="display-label">  
  36.         Gender  
  37.     </div>  
  38.     <div class="display-field">  
  39.         <input data-bind="value: Gender" />  
  40.     </div>  
  41.     <div class="display-label">  
  42.         Batch  
  43.     </div>  
  44.     <div class="display-field">  
  45.         <input data-bind="value: Batch" />  
  46.     </div>  
  47.     <div class="display-label">  
  48.         Address  
  49.     </div>  
  50.     <div class="display-field">  
  51.         <input data-bind="value: Address" />  
  52.     </div>  
  53.     <div class="display-label">  
  54.         Class  
  55.     </div>  
  56.     <div class="display-field">  
  57.         <input data-bind="value: Class" />  
  58.     </div>  
  59.     <div class="display-label">  
  60.         School  
  61.     </div>  
  62.     <div class="display-field">  
  63.         <input data-bind="value: School" />  
  64.     </div>  
  65.     <div class="display-label">  
  66.         Domicile  
  67.     </div>  
  68.     <div class="display-field">  
  69.         <input data-bind="value: Domicile" />  
  70.     </div>  
  71. </fieldset>  
  72. <p>  
  73.    <button type="button" data-bind="click: DeleteStudent">Delete Student</button> |  
  74.    <a href="@Url.Action("Index", "Student")">Back to List</a>  
  75. </p>  
  76. @section Scripts {  
  77. <script>  
  78.     $(function () {  
  79.         ko.applyBindings(DeleteVM);  
  80.     });  
  81.     var initialData = '@Html.Raw(ViewBag.InitialData)'//get the raw json  
  82.     var parsedJSON = $.parseJSON(initialData); //parse the json client side  
  83.     var DeleteVM = {  
  84.         Domiciles: ko.observableArray(['Delhi''Outside Delhi']),  
  85.         Genders: ko.observableArray(['Male''Female']),  
  86.         Students: ko.observableArray([]),  
  87.         StudentId: ko.observable(parsedJSON.StudentId),  
  88.         FirstName: ko.observable(parsedJSON.FirstName),  
  89.         LastName: ko.observable(parsedJSON.LastName),  
  90.         Age: ko.observable(parsedJSON.Age),  
  91.         Batch: ko.observable(parsedJSON.Batch),  
  92.         Address: ko.observable(parsedJSON.Address),  
  93.         Class: ko.observable(parsedJSON.Class),  
  94.         School: ko.observable(parsedJSON.School),  
  95.         Domicile: ko.observable(parsedJSON.Domicile),  
  96.         Gender: ko.observable(parsedJSON.Gender),  
  97.         DeleteStudent: function () {  
  98.             $.ajax({  
  99.                 url: '/Student/Delete',  
  100.                 type: 'post',  
  101.                 dataType: 'json',  
  102.                 data: ko.toJSON(this),  
  103.                 contentType: 'application/json',  
  104.                 success: function (result) {  
  105.                 },  
  106.                 error: function (err) {  
  107.                     if (err.responseText == "Creation Failed")  
  108.                     { window.location.href = '/Student/Index/'; }  
  109.                     else {  
  110.                         alert("Status:" + err.responseText);  
  111.                         window.location.href = '/Student/Index/'; ;  
  112.                     }  
  113.                 },  
  114.                 complete: function () {  
  115.                     window.location.href = '/Student/Index/';  
  116.                 }  
  117.             });  
  118.         }  
  119.     };  
  120. </script>  
  121. }
 


For Index (to the display list)

View Model

  1. var urlPath = window.location.pathname;  
  2. $(function () {  
  3.   ko.applyBindings(StudentListVM);  
  4.   StudentListVM.getStudents();  
  5. });  
  6. //View Model  
  7. var StudentListVM = {  
  8. Students: ko.observableArray([]),  
  9. getStudents: function () {  
  10. var self = this;  
  11. $.ajax({  
  12.   type: "GET",  
  13.   url: '/Student/FetchStudents',  
  14.   contentType: "application/json; charset=utf-8",  
  15.   dataType: "json",  
  16.   success: function (data) {  
  17.   self.Students(data); //Put the response in ObservableArray  
  18. },  
  19. error: function (err) {  
  20. alert(err.status + " : " + err.statusText);  
  21. }  
  22. });  
  23. },  
  24. };  
  25. self.editStudent = function (student) {  
  26. window.location.href = '/Student/Edit/' + student.StudentId;  
  27. };  
  28. self.deleteStudent = function (student) {  
  29. window.location.href = '/Student/Delete/' + student.StudentId;  
  30. };  
  31. //Model  
  32. function Students(data) {  
  33. this.StudentId = ko.observable(data.StudentId);  
  34. this.FirstName = ko.observable(data.FirstName);  
  35. this.LastName = ko.observable(data.LastName);  
  36. this.Age = ko.observable(data.Age);  
  37. this.Gender = ko.observable(data.Gender);  
  38. this.Batch = ko.observable(data.Batch);  
  39. this.Address = ko.observable(data.Address);  
  40. this.Class = ko.observable(data.Class);  
  41. this.School = ko.observable(data.School);  
  42. this.Domicile = ko.observable(data.Domicile);  

Controller methods
  1. public JsonResult FetchStudents()  
  2. {  
  3.    return Json(db.Students.ToList(), JsonRequestBehavior.AllowGet);  

View
  1. @model IEnumerable<KnockoutWithMVC4.Student>  
  2. @{  
  3.     ViewBag.Title = "Index";  
  4. }  
  5. <h2>Students List</h2>  
  6. <p><a href="@Url.Action("Create", "Student")" >Create Student</a></p>  
  7. <table>  
  8. <thead>  
  9. <tr>  
  10.   <th>Student Id</th>  
  11.   <th>First Name</th>  
  12.   <th>Last Name</th>  
  13.   <th>Age</th>  
  14.   <th>Gender</th>  
  15.   <th>Batch</th>  
  16.   <th>Address</th>  
  17.   <th>Class</th>  
  18.   <th>School</th>  
  19.   <th>Domicile</th>  
  20.   <th></th>  
  21. </tr>  
  22. </thead>kk  
  23. <tbody data-bind="foreach: Students">  
  24. <tr>  
  25.   <td data-bind="text: StudentId"></td>  
  26.   <td data-bind="text: FirstName"></td>  
  27.   <td data-bind="text: LastName"></td>  
  28.   <td data-bind="text: Age"></td>  
  29.   <td data-bind="text: Gender"></td>  
  30.   <td data-bind="text: Batch"></td>  
  31.   <td data-bind="text: Address"></td>  
  32.   <td data-bind="text: Class"></td>  
  33.   <td data-bind="text: School"></td>  
  34.   <td data-bind="text: Domicile"></td>  
  35.   <td>  
  36.     <a data-bind="click: editStudent">Edit</a>  
  37.    <a data-bind="click: deleteStudent">Delete</a>  
  38. </td>  
  39. </tr>  
  40. </tbody>  
  41. </table>         
  42. @section Scripts {  
  43.     @Scripts.Render("~/Scripts/ViewModels/StudentListVM.js")  
  44. }
>The return Json(db.Students.ToList(), JsonRequestBehavior.AllowGet); code returns the student object in JSON format, for binding to the view.


All set now, you can press F5 to run the application and we see that the application runs in the same manner as it executed before.

F5 to run the application

Now you can perform all the operations on this list.

all the operations on this list

Create chtml Page

Do not type anything else other than int for student id and Age, since the validation checks are missing, they may cause an error.

validation check

Now create a new student >as in the following:

create new student again

We see that the student is created successfully and added to the list as in the following:

student created successfully

In the database:

Database Check again

Similarly for Edit:

Edit student detail Again

Change any field and press "Save". The change will be reflected in the list and the database.


change in the list and data base again


For Delete:


Delete Student record Again

The Student has been deleted.

Student Deleted Again

And in the database:

see the chenge in Database table


10. Knockout Attributes Glossary


Knockout Attributes Glossary

  • .observable: Used to define model/entity properties. If these properties are bound with the user interface and when the value for these properties are updated,
    the UI elements automatically bound with these properties will be updated with the new value instantaneously.

    For example this.StudentId = ko.observable("1"); - => StudentId is the observable property. KO represents an object for the Knockout.js library.

    The value of the observable is read as var id= this. StudentId ();

  • .observableArray: observableArray represents a collection of data elements that require notifications. It's used to bind with the List kind of elements.

    E.g this.Students = ko.observableArray([]);

  • .applyBindings: This is used to activate Knockout for the current HTML document or a specific UI element in the HTML document. The parameter for this method
    is the view-model that is defined in JavaScript. This ViewModel contains the observable, observableArray and various methods.

Various other types of binding are used in this article:
  • .click: Represents a click event handler added to the UI element so that the JavaScript function is called.

  • .value: This represents the value binding with the UI element's value property to the property defined in the ViewModel.

    The value binding should be used with <input>, <select> and <textarea>.

  • .visible: This is used to hide or unhide the UI element based upon the value ed to it's binding.

  • .Text: This represent the text value of the parameter ed to the UI element.

11. Conclusion

In this article of series about Knockout, we learned many things about MVC, Entity Framework and Knockout.JS. We did practical hands-on exercises by creating a CRUD operations application too.

 

tasks done

Therefore we can mark it as tasks done. We'll be covering more topics in my future articles.

Note: A few of the images in this article are taken via Google search. You can follow my articles at: codeteddy.com


Similar Articles