Click here to Skip to main content
15,867,704 members
Articles / Programming Languages / C#

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

Rate me:
Please Sign up or sign in to vote.
4.89/5 (30 votes)
26 Nov 2014CPOL11 min read 193.2K   1.8K   90   55
This article will be a kind of tutorial to explain how we can set up a knockout.js environment in an MVC4 application that is also capable of performing CRUD operations

I) Introduction 

I have been browsing multiple sites to check if I could find a complete end to end tutorial or article upon CRUD operations using Knockout.JS and MVC 4. Unfortunately, all the ones I found were incomplete or had too short an explanation. In my last article we learned CRUD in ASP.NET web forms using MVC and EntityFramework. This article is the continuation to the same series. This article will be a kind of tutorial to explain how we can set up a Knockout.JS environment in an MVC4 application that is also capable of performing CRUD operations. 

II) Our Road-Map

We’ll stick to our agenda of Learning Knockout.JS as follows,

  1. Part 1: Introduction to Knockout.js and CRUD Operations in Asp.Net Web Forms using Knockout.JS and Entity Framework.
  2. Part 2: Complete end to end CRUD operations using Knockout.JS and Entity Framework in MVC4 application.

III) Part2: Complete end to end CRUD operations using Knockout.JS and Entity Framework in MVC4 application

We’ll continue to discuss KO step by step in this article

  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, not going very deep into theory I would like to give an introduction to MVC,Entity Framework and Knockout.

IV) 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 specifically mention 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 a change in Model’s state.

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

V) Entity Framework

Let’s have a look on 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 a simple language, 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 & storing the data in the database.

Hope this gives a glimpse of an ORM and EntityFramework.

VI) Knockout.JS

Knockout.JS (KO) is basically a JS library that enables Declarative Bindings using an ‘Observable’ View Model on the client (browser) following observer pattern approach, enabling 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 MVVM pattern i.e. Model-View-View Model.

As the architecture is shown, Views interact with View Models in a two way binding manner i.e. when the model is changed it view updates itself and when view is updated, the model updates itself instantaneously. 

KO provides 3 most important features like,

Knockout Akhil

The whole idea of KO derives from these three major functionalities. KO also helps in developing Single page applications (SPA’s).SPA’s are out of the box new way of developing rich internet applications(RIA’s) in todays era.

VII) Application Architecture

knockout Architecture by Akhil Mittal

 

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

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

VIII) MVC Application

1. Step1: Create a data base named LearningKO and add a table named student to it, script of the table is as follows,

SQL
USE [LearningKO]
GO
/****** Object:  Table [dbo].[Student]    Script Date: 12/04/2013 23:58:12 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Student](
	[StudentId] [nvarchar](10) NOT NULL,
	[FirstName] [nvarchar](50) NULL,
	[LastName] [nvarchar](50) NULL,
	[Age] [int] NULL,
	[Gender] [nvarchar](50) NULL,
	[Batch] [nvarchar](50) NULL,
	[Address] [nvarchar](50) NULL,
	[Class] [nvarchar](50) NULL,
	[School] [nvarchar](50) NULL,
	[Domicile] [nvarchar](50) NULL,
 CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED 
(
	[StudentId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT [dbo].[Student] ([StudentId], [FirstName], [LastName], [Age], [Gender], [Batch], [Address], [Class], [School], [Domicile]) VALUES (N'1', N'Akhil', N'Mittal', 28, N'Male', N'2006', N'Noida', N'Tenth', N'LFS', N'Delhi')
INSERT [dbo].[Student] ([StudentId], [FirstName], [LastName], [Age], [Gender], [Batch], [Address], [Class], [School], [Domicile]) VALUES (N'2', N'Parveen', N'Arora', 25, N'Male', N'2007', N'Noida', N'8th', N'DPS', N'Delhi')
INSERT [dbo].[Student] ([StudentId], [FirstName], [LastName], [Age], [Gender], [Batch], [Address], [Class], [School], [Domicile]) VALUES (N'3', N'Neeraj', N'Kumar', 38, N'Male', N'2011', N'Noida', N'10th', N'MIT', N'Outside Delhi')
INSERT [dbo].[Student] ([StudentId], [FirstName], [LastName], [Age], [Gender], [Batch], [Address], [Class], [School], [Domicile]) VALUES (N'4', N'Ekta', N'Mittal', 25, N'Female', N'2005', N' Noida', N'12th', N'LFS', N'Delhi')

Image 3

  • Step2: Open your Visual Studio (Visual Studio Version should be greater than or equal to 12) and add an MVC Internet application,

    Image 4

    Image 5

    I have given it a name "KnockoutWithMVC4".

  • Step3: You’ll get a full structured MVC application with default Home controller in the Controller folder. By default the entity framework is downloaded as a package inside application folder, but if not you can add entity framework package by right click the project, select manage nugget packages and search and install Entity Framework,

    Image 6

    Image 7

    4. Step 4: Right click project file, select add new item and add ADO.NET entity data model. Follow the steps in the wizard as shown below,

    Image 8

    Image 9

    Image 10

    Generate the model from the data base, select your server and LearningKO database name, the connection string will automatically be added to your Web.Config, name that connection string as LearningKOEntities

    Image 11

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

    Image 12

  • Step5: Now add a new controller to the Controller folder, right click 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 chosen Entity Framework Datamodel,

Image 13

Image 14

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

Image 15

  • Step6: We see out student controller prepared with all the CRUD operation actions as shown below,
    C#
    7.	using System;
    8.	using System.Collections.Generic;
    9.	using System.Data;
    10.	using System.Data.Entity;
    11.	using System.Linq;
    12.	using System.Web;
    13.	using System.Web.Mvc;
    14.	
    15.	namespace KnockoutWithMVC4.Controllers
    16.	{
    17.	    public class StudentController : Controller
    18.	    {
    19.	        private LearningKOEntities db = new LearningKOEntities();
    20.	
    21.	        //
    22.	        // GET: /Student/
    23.	
    24.	        public ActionResult Index()
    25.	        {
    26.	            return View(db.Students.ToList());
    27.	        }
    28.	
    29.	        //
    30.	        // GET: /Student/Details/5
    31.	
    32.	        public ActionResult Details(string id = null)
    33.	        {
    34.	            Student student = db.Students.Find(id);
    35.	            if (student == null)
    36.	            {
    37.	                return HttpNotFound();
    38.	            }
    39.	            return View(student);
    40.	        }
    41.	
    42.	        //
    43.	        // GET: /Student/Create
    44.	
    45.	        public ActionResult Create()
    46.	        {
    47.	            return View();
    48.	        }
    49.	
    50.	        //
    51.	        // POST: /Student/Create
    52.	
    53.	        [HttpPost]
    54.	        [ValidateAntiForgeryToken]
    55.	        public ActionResult Create(Student student)
    56.	        {
    57.	            if (ModelState.IsValid)
    58.	            {
    59.	                db.Students.Add(student);
    60.	                db.SaveChanges();
    61.	                return RedirectToAction("Index");
    62.	            }
    63.	
    64.	            return View(student);
    65.	        }
    66.	
    67.	        //
    68.	        // GET: /Student/Edit/5
    69.	
    70.	        public ActionResult Edit(string id = null)
    71.	        {
    72.	            Student student = db.Students.Find(id);
    73.	            if (student == null)
    74.	            {
    75.	                return HttpNotFound();
    76.	            }
    77.	            return View(student);
    78.	        }
    79.	
    80.	        //
    81.	        // POST: /Student/Edit/5
    82.	
    83.	        [HttpPost]
    84.	        [ValidateAntiForgeryToken]
    85.	        public ActionResult Edit(Student student)
    86.	        {
    87.	            if (ModelState.IsValid)
    88.	            {
    89.	                db.Entry(student).State = EntityState.Modified;
    90.	                db.SaveChanges();
    91.	                return RedirectToAction("Index");
    92.	            }
    93.	            return View(student);
    94.	        }
    95.	
    96.	        //
    97.	        // GET: /Student/Delete/5
    98.	
    99.	        public ActionResult Delete(string id = null)
    100.	        {
    101.	            Student student = db.Students.Find(id);
    102.	            if (student == null)
    103.	            {
    104.	                return HttpNotFound();
    105.	            }
    106.	            return View(student);
    107.	        }
    108.	
    109.	        //
    110.	        // POST: /Student/Delete/5
    111.	
    112.	        [HttpPost, ActionName("Delete")]
    113.	        [ValidateAntiForgeryToken]
    114.	        public ActionResult DeleteConfirmed(string id)
    115.	        {
    116.	            Student student = db.Students.Find(id);
    117.	            db.Students.Remove(student);
    118.	            db.SaveChanges();
    119.	            return RedirectToAction("Index");
    120.	        }
    121.	
    122.	        protected override void Dispose(bool disposing)
    123.	        {
    124.	            db.Dispose();
    125.	            base.Dispose(disposing);
    126.	        }
    127.	    }
    128.	} 
  • 7. Step7: Open App_Start folder and, change the name of controller from Home to Student,

    Image 16

    the code will become as,

    C#
    public static void RegisterRoutes(RouteCollection routes)
       {
           routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
           routes.MapRoute(
               name: "Default",
               url: "{controller}/{action}/{id}",
               defaults: new { controller = "Student", action = "Index", id = UrlParameter.Optional }
           );
       }
    
  • Step8: Now press F5 to run the application, and you’ll see the list of all students we added in to table Student while creating it is displayed. Since the CRUD operations are automatically written, we have action results for display list and other Edit, Delete and Create operations. Note that views for all the operations are created in Views Folder under Student Folder name.

    Image 17

     

    Now you can perform all the operations on this list.

     Image 18

     Image 19

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

     Image 20

    Now create new student ,

     Image 21

    We see that the student is created successfully and added to the list,

     Image 22

    In data base,

     Image 23

    Similarly for Edit,

     Image 24

    Change any field and press save.The change will be reflected in the list and data base,

     Image 25

    For Delete, 

     Image 26

    Student Deleted.

    And in database,

     Image 27

    So, that’s it, our first job is completed i.e. 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!

    Image 28

     

    IX) Knockout Application

    Our first job is well done,now moving on to our primary target, i.e. KO. Since KO depends largely on MVVM pattern, we’ll take MVVM at client side, and use our controller to be as same just modified little bit for returning JSON logic. You can learn about MVVM pattern and KO theory in first part of this article series.

    1. Step1:

      JQuery and Knockout.js files are very important to be in the solution’s script folder. Check to 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 project, select "Manage nugget packages" and search for jQuery then install it , then search for knockout package and install it,

       Image 29

       Image 30

    2. Step2: Right click Scripts folder and a folder named ViewModel.Add four js files to that folder, and name them as CreateVM.js, EditVM.js, DeleteVM.js and StudentListVM.js respectively. These are View Model files added to communicate to Controller and render our View templates.

       

    3. Step3: Add some code to CreateVm.js as,

       

      var urlPath = window.location.pathname;
      $(function () {
          ko.applyBindings(CreateVM);
      });
      
      var CreateVM = {
          Domiciles: ko.observableArray(['Delhi', 'Outside Delhi']),
          Genders: ko.observableArray(['Male', 'Female']),
          Students: ko.observableArray([]),
          StudentId: ko.observable(),
          FirstName: ko.observable(),
          LastName: ko.observable(),
          Age: ko.observable(),
          Batch: ko.observable(),
          Address: ko.observable(),
          Class: ko.observable(),
          School: ko.observable(),
          Domicile: ko.observable(),
          Gender: ko.observable(),
          SaveStudent: function () {
              $.ajax({
                  url: '/Student/Create',
                  type: 'post',
                  dataType: 'json',
                  data: ko.toJSON(this),
                  contentType: 'application/json',
                  success: function (result) {
                  },
                  error: function (err) {
                      if (err.responseText == "Creation Failed")
                      { window.location.href = '/Student/Index/'; }
                      else {
                          alert("Status:"+err.responseText);
                          window.location.href = '/Student/Index/';;
                      }
                  },
                  complete: function () {
                      window.location.href = '/Student/Index/';
                  }
              });
          }
      };

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

      Student/Create Controller Method

      Modify the code of 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 view model using Knockout Observables. 

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

      Controller Code

      [HttpPost]
       public string Create(Student student)
       {
           if (ModelState.IsValid)
           {
               if (!StudentExists(student))
                   db.Students.Add(student);
               else
                   return Edit(student);
               db.SaveChanges();
               return "Student Created";
           }
           return "Creation Failed";
       }
      

      View Code

      Change the code of the already created views to work with KO,

      For create.cshtml,

      <h2>Create</h2>
      <fieldset>
          <legend>Create Student</legend>
      
          <div class="editor-label">
              Student id
          </div>
          <div class="editor-field">
              <input data-bind="value: StudentId" />
          </div>
      
          <div class="editor-label">
              First Name
          </div>
          <div class="editor-field">
              <input data-bind="value: FirstName" />
          </div>
      
          <div class="editor-label">
              Last Name
          </div>
          <div class="editor-field">
              <input data-bind="value: LastName" />
          </div>
      
          <div class="editor-label">
              Age
          </div>
          <div class="editor-field">
              <input data-bind="value: Age" />
          </div>
      
          <div class="editor-label">
              Gender
          </div>
          <div class="editor-field">
              <select data-bind="options: Genders, value: Gender, optionsCaption: 'Select Gender...'"></select>
          </div>
      
          <div class="editor-label">
              Batch
          </div>
          <div class="editor-field">
              <input data-bind="value: Batch" />
          </div>
      
          <div class="editor-label">
              Address
          </div>
          <div class="editor-field">
              <input data-bind="value: Address" />
          </div>
      
          <div class="editor-label">
              Class
          </div>
          <div class="editor-field">
              <input data-bind="value: Class" />
          </div>
      
          <div class="editor-label">
              School
          </div>
          <div class="editor-field">
              <input data-bind="value: School" />
          </div>
      
          <div class="editor-label">
              Domicile
          </div>
          <div class="item ">
              <select data-bind="options: Domiciles, value: Domicile, optionsCaption: 'Select Domicile...'"></select>
          </div>
      
          <p>
              <button type="button" data-bind="click: SaveStudent">Save Student To Database</button>
          </p>
      </fieldset>
      <div>
          <a href="@Url.Action("Index", "Student")" >Back to List</a>
      </div>
      
      @section Scripts {
          @Scripts.Render("~/Scripts/ViewModels/CreateVM.js")
      }

      You can see I have used data-bind attribute of HTML5 to bind the View elements to View Models properties like data-bind="value: StudentId" , the same applies to all the editable elements. Click button is bound to SaveStudent method of view model.

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

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

      Tag.

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

       

    For Edit

    View Model

    Code added in StudentListVM for Edit View Model, since it only perform get when it loads.

    Controller methods

    C#
    public ActionResult Edit(string id=null)
            {
                Student student = db.Students.Find(id);
                if (student == null)
                {
                    return null;
                }
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                ViewBag.InitialData = serializer.Serialize(student); 
                return View();
            }
    
            /// <summary>
            /// Edits particular student details
            /// </summary>
            /// <param name="student"></param>
            /// <returns></returns>
            [HttpPost]
            public string Edit(Student student)
            {
                if (ModelState.IsValid)
                {
                    db.Entry(student).State = EntityState.Modified;
                    db.SaveChanges();
                    return "Student Edited";
                }
                return "Edit Failed";
            }

    View

    <h2>Edit</h2>
    <fieldset>
        <legend>Edit Student</legend>
    
        <div class="editor-label">
            Student id
        </div>
        <div class="editor-field">
            <input data-bind="value: StudentId" readonly="readonly" />
        </div>
    
        <div class="editor-label">
            First Name
        </div>
        <div class="editor-field">
            <input data-bind="value: FirstName" />
        </div>
    
        <div class="editor-label">
            Last Name
        </div>
        <div class="editor-field">
            <input data-bind="value: LastName" />
        </div>
    
        <div class="editor-label">
            Age
        </div>
        <div class="editor-field">
            <input data-bind="value: Age" />
        </div>
    
        <div class="editor-label">
            Gender
        </div>
        <div class="editor-field">
            <select data-bind="options: Genders, value: Gender, optionsCaption: 'Select Gender...'"></select>
        </div>
    
        <div class="editor-label">
            Batch
        </div>
        <div class="editor-field">
            <input data-bind="value: Batch" />
        </div>
    
        <div class="editor-label">
            Address
        </div>
        <div class="editor-field">
            <input data-bind="value: Address" />
        </div>
    
        <div class="editor-label">
            Class
        </div>
        <div class="editor-field">
            <input data-bind="value: Class" />
        </div>
    
        <div class="editor-label">
            School
        </div>
        <div class="editor-field">
            <input data-bind="value: School" />
        </div>
    
        <div class="editor-label">
            Domicile
        </div>
        <div class="editor-field">
            <select data-bind="options: Domiciles, value: Domicile, optionsCaption: 'Select Domicile...'"></select>
        </div>
        <p>
            <button type="button" data-bind="click: SaveStudent">Save Student To Database</button>
        </p>
    </fieldset>
    <div>
        <a href="@Url.Action("Index", "Student")">Back to List</a>
    </div>
    @section Scripts {
        <script>
    
            $(function () {
                ko.applyBindings(EditVM);
            });
    
            var initialData = '@Html.Raw(ViewBag.InitialData)'; //get the raw json
            var parsedJSON = $.parseJSON(initialData); //parse the json client side
            var EditVM = {
                Domiciles: ko.observableArray(['Delhi', 'Outside Delhi']),
                Genders: ko.observableArray(['Male', 'Female']),
                Students: ko.observableArray([]),
                StudentId: ko.observable(parsedJSON.StudentId),
                FirstName: ko.observable(parsedJSON.FirstName),
                LastName: ko.observable(parsedJSON.LastName),
                Age: ko.observable(parsedJSON.Age),
                Batch: ko.observable(parsedJSON.Batch),
                Address: ko.observable(parsedJSON.Address),
                Class: ko.observable(parsedJSON.Class),
                School: ko.observable(parsedJSON.School),
                Domicile: ko.observable(parsedJSON.Domicile),
                Gender: ko.observable(parsedJSON.Gender),
                SaveStudent: function () {
                    $.ajax({
                        url: '/Student/Edit',
                        type: 'post',
                        dataType: 'json',
                        data: ko.toJSON(this),
                        contentType: 'application/json',
                        success: function (result) {
                        },
                        error: function (err) {
                            if (err.responseText == "Creation Failed")
                            { window.location.href = '/Student/Index/'; }
                            else {
                                alert("Status:" + err.responseText);
                                window.location.href = '/Student/Index/';;
                            }
                        },
                        complete: function () {
                            window.location.href = '/Student/Index/';
                        }
                    });
                }
            };
    
        </script>
    }

    For Delete

    View Model

    Code added in StudentListVM for Edit View Model, since it only perform get when it loads.

    Controller methods

    C#
    public ActionResult Delete(string id = null)
     {
         Student student = db.Students.Find(id);
         if (student == null)
         {
             return null;
         }
         JavaScriptSerializer serializer = new JavaScriptSerializer();
         ViewBag.InitialData = serializer.Serialize(student);
         return View();
     }
    
     /// <summary>
     /// Delete particular student details
     /// </summary>
     /// <param name="student"></param>
     /// <returns></returns>
     [HttpPost]
     public string Delete(Student student)
     {
         Student studentDetail = db.Students.Find(student.StudentId);
         db.Students.Remove(studentDetail);
         db.SaveChanges();
         return "Student Deleted";
     }
    

    View

    @model KnockoutWithMVC4.Student
    
    @{
        ViewBag.Title = "Delete";
    }
    
    <h2>Delete Student</h2>
    
    <h3>Are you sure you want to delete this?</h3>
    <fieldset>
        <legend>Delete</legend>
        <div class="display-label">
            Student Id
        </div>
        <div class="display-field">
            <input data-bind="value: StudentId" />
    
        </div>
        <div class="display-label">
            First Name
        </div>
        <div class="display-field">
            <input data-bind="value: FirstName" />
        </div>
    
        <div class="display-label">
            Last Name
        </div>
        <div class="display-field">
            <input data-bind="value: LastName" />
    
        </div>
    
        <div class="display-label">
            Age
        </div>
        <div class="display-field">
            <input data-bind="value: Age" />
    
        </div>
    
        <div class="display-label">
            Gender
        </div>
        <div class="display-field">
            <input data-bind="value: Gender" />
    
        </div>
    
        <div class="display-label">
            Batch
        </div>
        <div class="display-field">
            <input data-bind="value: Batch" />
    
        </div>
    
        <div class="display-label">
            Address
    
        </div>
        <div class="display-field">
            <input data-bind="value: Address" />
    
        </div>
    
        <div class="display-label">
            Class
        </div>
        <div class="display-field">
            <input data-bind="value: Class" />
    
        </div>
    
        <div class="display-label">
            School
        </div>
        <div class="display-field">
            <input data-bind="value: School" />
    
        </div>
    
        <div class="display-label">
            Domicile
        </div>
        <div class="display-field">
            <input data-bind="value: Domicile" />
    
        </div>
    </fieldset>
    
    <p>
        <button type="button" data-bind="click: DeleteStudent">Delete Student</button> |
        <a href="@Url.Action("Index", "Student")">Back to List</a>
    </p>
    
    @section Scripts {
        <script>
    
            $(function () {
                ko.applyBindings(DeleteVM);
            });
    
            var initialData = '@Html.Raw(ViewBag.InitialData)'; //get the raw json
            var parsedJSON = $.parseJSON(initialData); //parse the json client side
            var DeleteVM = {
                Domiciles: ko.observableArray(['Delhi', 'Outside Delhi']),
                Genders: ko.observableArray(['Male', 'Female']),
                Students: ko.observableArray([]),
                StudentId: ko.observable(parsedJSON.StudentId),
                FirstName: ko.observable(parsedJSON.FirstName),
                LastName: ko.observable(parsedJSON.LastName),
                Age: ko.observable(parsedJSON.Age),
                Batch: ko.observable(parsedJSON.Batch),
                Address: ko.observable(parsedJSON.Address),
                Class: ko.observable(parsedJSON.Class),
                School: ko.observable(parsedJSON.School),
                Domicile: ko.observable(parsedJSON.Domicile),
                Gender: ko.observable(parsedJSON.Gender),
                DeleteStudent: function () {
                    $.ajax({
                        url: '/Student/Delete',
                        type: 'post',
                        dataType: 'json',
                        data: ko.toJSON(this),
                        contentType: 'application/json',
                        success: function (result) {
                        },
                        error: function (err) {
                            if (err.responseText == "Creation Failed")
                            { window.location.href = '/Student/Index/'; }
                            else {
                                alert("Status:" + err.responseText);
                                window.location.href = '/Student/Index/';;
                            }
                        },
                        complete: function () {
                            window.location.href = '/Student/Index/';
                        }
                    });
                }
            };
    
        </script>
    }

    For Index(To display list)

    View Model

    var urlPath = window.location.pathname;
    $(function () {
        ko.applyBindings(StudentListVM);
        StudentListVM.getStudents();
    });
    
    //View Model
    var StudentListVM = {
        Students: ko.observableArray([]),
        getStudents: function () {
            var self = this;
            $.ajax({
                type: "GET",
                url: '/Student/FetchStudents',
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (data) {
                    self.Students(data); //Put the response in ObservableArray
                },
                error: function (err) {
                    alert(err.status + " : " + err.statusText);
                }
            });
        },
    };
    
    self.editStudent = function (student) {
        window.location.href =  '/Student/Edit/' + student.StudentId;
    };
    self.deleteStudent = function (student) {
        window.location.href = '/Student/Delete/' + student.StudentId;
    };
    
    //Model
    function Students(data) {
        this.StudentId = ko.observable(data.StudentId);
        this.FirstName = ko.observable(data.FirstName);
        this.LastName = ko.observable(data.LastName);
        this.Age = ko.observable(data.Age);
        this.Gender = ko.observable(data.Gender);
        this.Batch = ko.observable(data.Batch);
        this.Address = ko.observable(data.Address);
        this.Class = ko.observable(data.Class);
        this.School = ko.observable(data.School);
        this.Domicile = ko.observable(data.Domicile);
    }

    Controller methods

    C#
    public JsonResult FetchStudents()
            {
                return Json(db.Students.ToList(), JsonRequestBehavior.AllowGet);
            }

    View

    @model IEnumerable<KnockoutWithMVC4.Student>
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Students List</h2>
    
    <p>
        <a href="@Url.Action("Create", "Student")" >Create Student</a>
    </p>
    <table>
        <thead>
            <tr>
                <th>
                    Student Id
                </th>
                <th>
                    First Name
                </th>
                <th>
                    Last Name
                </th>
                <th>
                    Age
                </th>
                <th>
                    Gender
                </th>
                <th>
                    Batch
                </th>
                <th>
                    Address
                </th>
                <th>
                    Class
                </th>
                <th>
                    School
                </th>
                <th>
                    Domicile
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody data-bind="foreach: Students">
            <tr>
                <td data-bind="text: StudentId"></td>
                <td data-bind="text: FirstName"></td>
                <td data-bind="text: LastName"></td>
                <td data-bind="text: Age"></td>
                <td data-bind="text: Gender"></td>
                <td data-bind="text: Batch"></td>
                <td data-bind="text: Address"></td>
                <td data-bind="text: Class"></td>
                <td data-bind="text: School"></td>
                <td data-bind="text: Domicile"></td>
                <td>
                    <a data-bind="click: editStudent">Edit</a>
                    <a data-bind="click: deleteStudent">Delete</a>
                </td>
            </tr>
        </tbody>
    </table>
    @section Scripts {
        @Scripts.Render("~/Scripts/ViewModels/StudentListVM.js")
    }

    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 application runs in the same manner as it executed before,

     Image 31

    Now you can perform all the operations on this list. 

     Image 32

     Image 33

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

     Image 34

    Now create new student ,

    Image 35 

    We see that the student is created successfully and added to the list,

     Image 36

    In data base,

    Image 37 

    Similarly for Edit,

     Image 38

    Change any field and press save.The change will be reflected in the list and data base,

     Image 39

    For Delete,

     Image 40

    Student Deleted.

    Image 41 

    And in database,

    Image 42 

    X) Knockout Attributes Glossary  

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

    e.g. this.StudentId = ko.observable("1"); - => StudentId is the observable property. KO represent an object for the Knockout.js library.

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

     Image 43

    · observableArray: observableArray represents a collection of data elements which required 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 HTML document. The parameter for this method is the view-model which 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 JavaScript function is called.

    . value: This represents the value binding with the UI element’s value property to the property defined into the ViewModel.

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

    . visible: This is used to hide or unhide the UI element based upon the value passed to it’s binding.

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

    XI) Conclusion

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

    Image 44

    Therefore we can mark it as tasks done.

    We’ll be covering more topics in my upcoming articles.

    Note: few of the images in this article are taken via Google search.

    Happy Coding :).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect https://codeteddy.com/
India India
Akhil Mittal is two times Microsoft MVP (Most Valuable Professional) firstly awarded in 2016 and continued in 2017 in Visual Studio and Technologies category, C# Corner MVP since 2013, Code Project MVP since 2014, a blogger, author and likes to write/read technical articles, blogs, and books. Akhil is a technical architect and loves to work on complex business problems and cutting-edge technologies. He has an experience of around 15 years in developing, designing, and architecting enterprises level applications primarily in Microsoft Technologies. He has diverse experience in working on cutting-edge technologies that include Microsoft Stack, AI, Machine Learning, and Cloud computing. Akhil is an MCP (Microsoft Certified Professional) in Web Applications and Dot Net Framework.
Visit Akhil Mittal’s personal blog CodeTeddy (CodeTeddy ) for some good and informative articles. Following are some tech certifications that Akhil cleared,
• AZ-304: Microsoft Azure Architect Design.
• AZ-303: Microsoft Azure Architect Technologies.
• AZ-900: Microsoft Azure Fundamentals.
• Microsoft MCTS (70-528) Certified Programmer.
• Microsoft MCTS (70-536) Certified Programmer.
• Microsoft MCTS (70-515) Certified Programmer.

LinkedIn: https://www.linkedin.com/in/akhilmittal/
This is a Collaborative Group

779 members

Comments and Discussions

 
GeneralRe: Error Message Pin
Navya Sri30-Jun-14 23:00
Navya Sri30-Jun-14 23:00 
GeneralRe: Error Message Pin
Akhil Mittal1-Jul-14 0:08
professionalAkhil Mittal1-Jul-14 0:08 
QuestionRe: Error Message Pin
Navya Sri30-Jun-14 23:13
Navya Sri30-Jun-14 23:13 
AnswerRe: Error Message Pin
Akhil Mittal1-Jul-14 0:23
professionalAkhil Mittal1-Jul-14 0:23 
GeneralRe: Error Message Pin
Navya Sri1-Jul-14 1:01
Navya Sri1-Jul-14 1:01 
GeneralRe: Error Message Pin
Akhil Mittal1-Jul-14 1:09
professionalAkhil Mittal1-Jul-14 1:09 
AnswerRe: Error Message Pin
Akhil Mittal1-Jul-14 0:25
professionalAkhil Mittal1-Jul-14 0:25 
QuestionRe: Error Message Pin
Navya Sri2-Jul-14 20:29
Navya Sri2-Jul-14 20:29 
Questionvery nice article Pin
laxmanreddy22-Apr-14 14:43
laxmanreddy22-Apr-14 14:43 
AnswerRe: very nice article Pin
Akhil Mittal9-May-14 7:20
professionalAkhil Mittal9-May-14 7:20 
SuggestionExcellent Hands on Pin
ajayvbc15-Apr-14 13:16
ajayvbc15-Apr-14 13:16 
GeneralRe: Excellent Hands on Pin
Akhil Mittal9-May-14 7:22
professionalAkhil Mittal9-May-14 7:22 
QuestionKnockout Pin
farrdy207-Apr-14 11:41
farrdy207-Apr-14 11:41 
AnswerRe: Knockout Pin
Akhil Mittal12-Apr-14 0:38
professionalAkhil Mittal12-Apr-14 0:38 
GeneralMy vote of 5 Pin
Member 104384461-Apr-14 21:02
Member 104384461-Apr-14 21:02 
GeneralRe: My vote of 5 Pin
Akhil Mittal12-Apr-14 0:38
professionalAkhil Mittal12-Apr-14 0:38 
GeneralMy vote of 5 Pin
bto.rdz15-Feb-14 9:23
bto.rdz15-Feb-14 9:23 
GeneralRe: My vote of 5 Pin
Akhil Mittal17-Feb-14 1:15
professionalAkhil Mittal17-Feb-14 1:15 
GeneralMy vote of 5 Pin
Shmeenimal14-Jan-14 6:57
Shmeenimal14-Jan-14 6:57 
GeneralRe: My vote of 5 Pin
Akhil Mittal17-Feb-14 1:16
professionalAkhil Mittal17-Feb-14 1:16 
QuestionTiny trouble with Edit Pin
Shmeenimal14-Jan-14 6:56
Shmeenimal14-Jan-14 6:56 
QuestionGetting Required Anti-Forgery form field! Pin
dedamu12-Jan-14 18:00
professionaldedamu12-Jan-14 18:00 
BugGreat article, missing some code however Pin
Jason Gayda26-Dec-13 15:16
Jason Gayda26-Dec-13 15:16 
GeneralMy vote of 5 Pin
m_aks19-Dec-13 21:58
m_aks19-Dec-13 21:58 
GeneralRe: My vote of 5 Pin
Akhil Mittal19-Dec-13 22:01
professionalAkhil Mittal19-Dec-13 22:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.