Knockout JS is a fantastic library when you are looking for a drop-in enhancement that brings in client side data-binding and elements of the MVVM design pattern into your website that’s a potpourri of Razor syntax, server side Html Helpers and jQuery plugins.
Well Knockout JS was built to bring meaning into this chaos, but before you get started, you have to detune yourself a bit. Let’s see what that means. By the way, this article assumes you have the KO cheat-sheet created by Sumit Maitra handy so that you can quickly lookup some of the syntax we throw around. Sumit has helped me a great deal in co-authoring this article and just like an AngularJS + MVC series, we are planning to collaborate to do a KnockoutJS series too.
Read the second part of this article - KnockoutJS and ASP.NET MVC – Alternate techniques and using the Anti Forgery Token
Separating the Server side and the client side
Most newbies have trouble visualizing the server side and the client side, especially devs coming from WinForms background. ViewBag is often interpreted as ViewState and then all hell breaks loose. Here is the thumb rule:
Rendered on Client (i.e. the browser) == HTML only (plus JavaScript of course)
Rendered on Server == cshtml markup + all the Razor expressions a.k.a. anything that starts with an @.
So anything that was written in the CSHTML file including binding of a Select to a SelectList in ViewBag, is all interpreted by the “View Engine” and converted into HTML BEFORE it reaches the browser.
This distinction is extremely important to understand. Once this distinction is clear, you know exactly what you have in the DOM when you are writing the $(document).ready (…)
ViewModel is the starting point of your UI
Knockout works with a ViewModel that can either be a JS object or a JS function. Either ways, your ViewModel is your data source. Always think of what you need to do to update the ViewModel in order to get a certain output on the view and not how to update the view by hacking the DOM using jQuery or JavaScript.
Let’s take an example. Say you have a C# object - Lookup
public class Lookup
{
public int Id { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
Consider the requirement where you have to render all the existing lookups and add new ones. You can easily render a collection into an HTML <table>. However you are spoilt for choices when it comes to adding a new Lookup value. You could use a jQuery UI plugin or Bootstrap plugin to show a fancy modal dialog that would temporarily store the data for new item. If you are hitting the server as the dialog is dismissed you are good. What if you have to avoid hitting the server on dialog dismissal, but maintain the changes till an Explicit save function is called? You potentially have to keep track of changes in more than one Lookup and looping the DOM elements on click of the Save button isn’t the best way to ‘get’ the latest data. Another requirement could be you want to add new rows inline in the table itself and Edit it inline as well. How could we do that without hacking the DOM?
Observables in Knockout help you with ‘Two-Way’ Data Binding
Observables in Knockout are built for the precise purpose of keeping track of changes and updating the UI as changes happen in the ViewModel. So if you consider converting your Server Side Data into a JavaScript object collection on the client side and add, delete or modify values in this collection, you can post the updated collection back once you are ready with all your changes in one go. Best part is if you bind your <table> to the JavaScript object collection, you don’t have to write any DOM manipulation code at all.
Example
Consider the above Lookup class and assume we have scaffolded a Controller and CRUD operations + UI for it in an ASP.NET MVC Application Template. Our UI looks like this for the Index

The Server side markup for this is as follows
@model IEnumerable<KnockoutSamples.Models.Lookup>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Key)
</th>
<th>
@Html.DisplayNameFor(model => model.Value)
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Key)
</td>
<td>
@Html.DisplayFor(modelItem => item.Value)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
@Html.ActionLink("Details", "Details", new { id = item.Id }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
When we click on Create, the server routes us to a different page and when we save on that page, we get routed back to the Index page.

Business requirements never match scaffolded/auto-generated templates, because if they did, we would have automated software development a long time ago. So let’s say our requirement changed and now we have to do the Create, Update and Delete actions inline, in the Index page.
This would present to us the perfect opportunity to introduce a ViewModel and start using KO to data-bind the UI to the view Model. We add KnockoutJS to our Project and add a knockout.samples.js for our custom scripts.
The script in the knockout.samples.js file is as follows to start off with. The viewModel object has only one property the lookupCollection of type ko.observableArray(). This means anytime an item is added or removed from the Array, Knockout will update any UI elements that are bound to this collection.
viewModel = {
lookupCollection : ko.observableArray()
};
$(document).ready(function () {
$.ajax({
type: "GET",
url: "/Lookups/GetIndex",
}).done(function (data) {
$(data).each(function (index, element) {
viewModel.lookupCollection.push(element);
});
ko.applyBindings(viewModel);
}).error(function (ex) {
alert("Error");
});
});
Next we have the jQuery document ready function. Here we directly do an AJAX get to retrieve some data from the server. Once the server returns data (essentially the list of Lookup objects as JSON), we populate the lookupCollection in our viewModel. As we are pushing data into the observable collection, KO is updating the UI for us automatically.
One small gotcha remains, the URL that our AJAX call is pointing to - GetIndex action method, doesn’t exist yet, lets put that in:
public ActionResult Index()
{
return View();
}
public JsonResult GetIndex()
{
return Json(db.Lookups.ToList(), JsonRequestBehavior.AllowGet);
}
Actually we’ve got two changes here. The Index method now returns an empty View and the GetIndex method returns a Json array of the Lookup Objects.
Then we update the Index.cshtml and get rid of all the server side ‘stuff’
<title>Index</title>
<h2>Index</h2>
<p>
<button class="btn btn-primary" id="create">Create</button>
</p>
<table class="table">
<tr>
<th>
Key
</th>
<th>
Value
</th>
<th></th>
</tr>
<tbody data-bind="foreach: lookupCollection">
<tr>
<td data-bind="text: Key"></td>
<td data-bind="text: Value"></td>
<td>
<button class="btn btn-success">Edit</button>
<button class="btn btn-danger">Delete</button>
</td>
</tr>
</tbody>
</table>
Look Ma, no Razor syntax! Okay I cheated we still have @section for Scripts, but apart from that there is no Razor syntax.
Understanding the KO DataBinding
As you can see in the markup above, there are some special data-bind attributes. These are HTML5 compliant attributes that Knockout uses to bind the viewModel to the HTML View.
The foreach binding - The <tbody> is bound using what’s referred to as foreach binding. This tells KO that it should bind to an array by the name lookupCollection. KO automatically assumes the content inside the <tbody> should be repeated for every item in the lookupCollection.
The text binding - Inside the foreach, we have an entire <tr> defined. This will be repeated for as many items that are there in the collection. Now the binding context automatically changes from the collection to the item in the collection. So when we databind to text: Key it tell KO to pull out the Key property of the current item and in this case (since it’s bound to the td) place it as inner text.
Nice! Let’s run the application and visit the Lookups’ Index page

Wow, super cool! But now our Create/Edit/Delete buttons no longer work! What now?
Editing objects on Client Side
Since the aim of this article was to showcase how to use ViewModel as opposed to DOM manipulation, we’ll apply some more KO features now.
Creating different templates for Edit and View
In the above markup for Index.cshtml, we have assumed that the view is going to be read-only, but what if we want to toggle between a readonly view and Edit view when user clicks on the Edit button? KO has a solution for that – Named Templates.
Named Templates are a KO feature that allows you to define snippets of markup tagged with a name to identify it. KO then replaces this snippet wherever the template binding calls requests for it.
For example: in our above sample, we have the <tbody> bound to the lookupCollection. The <tr> contains the <td> elements that are bound to the Key and Value properties of the viewModel. However we want two different modes now, display and edit. In display mode, the view will be as it is currently, i.e. use Labels, but in edit mode we should have Input boxes that allow us to save the changes. Solution? Define two templates one for display and one for edit.
The Updated markup for the <tbody> is as follows:
<tbody data-bind="foreach: lookupCollection">
<tr data-bind="template: { name: Mode, data: $data }">
</tr>
</tbody>
As you can see here, the <tr> is now bound to a template whose name is defined in a property called Mode and whose data comes from a variable $data.
Hold on to the thought that we have a new property in our Lookup object called Mode, we’ll see ‘how’ in a minute.
The $data variable is provided by KO and it is a pointer to the current viewModel element that is available for data binding. So in this case, since we are inside the lookupCollection, $data represents a Lookup element from the collection. Thus we are passing the current element to the Template and elements inside the template can bind to the properties it.
The Templates are defined as follows:
<script type="text/html" id="display">
<td data-bind="text: Key"></td>
<td data-bind="text: Value"></td>
<td>
<button class="btn btn-success kout-edit">Edit</button>
<button class="btn btn-danger kout-delete">Delete</button>
</td>
</script>
<script type="text/html" id="edit">
<td><input type="text" data-bind="value: Key" /></td>
<td><input type="text" data-bind="value: Value" /></td>
<td>
<button class="btn btn-success kout-save">Update</button>
<button class="btn btn-danger kout-cancel">Cancel</button>
</td>
</script>
So templates are defined as Script blocks to keep them valid HTML and given a unique ID. This is the name that we saw earlier in the template binding. So when our Lookup Element’s Mode property is set to display, the first template is used (readonly). When it is set to edit, the second template (using input boxes) is shown.
Also note the Buttons change Text in Edit Mode.
Last but not least we have added classes starting with kout- to our Edit, Delete, Update and Cancel buttons. Why?
This is because we need click handlers for the buttons and since these buttons are part of a template we cannot give them an Id in the markup because the ID would get duplicated. So to attach click handlers we use the class name.
Applying Templates and Switching them on-the-fly
Now that we have added the templates, time to apply them. The key thing missing is the Mode property that’s not available on the Server side, so it won’t be present in the JSON that come back from the server. Solution? We create our custom object and add the custom object to the collection. Sounds complicated but it isn’t, here is what the done function looks like
.done(function (data) {
$(data).each(function (index, element) {
var mappedItem =
{
Id: ko.observable(element.Id),
Key: ko.observable(element.Key),
Value: ko.observable(element.Value),
Mode: ko.observable("display")
};
viewModel.lookupCollection.push(mappedItem);
});
ko.applyBindings(viewModel);
})
As we can see, we were earlier looping through the incoming array and directly pushing the JS object into the lookupCollection. Now, we are creating a new object called mappedItem with four properties, Id, Key, Value and Mode. Key and Value is set to the values we get from the server, whereas the Mode property is set to “display” by default because initially everything will be in readonly mode.
Switching Modes
We need to switch modes when user clicks on Edit and Update. So to do that we bind the ‘click’ event handlers using the jQuery $(document).on(…) function
$(document).on("click", ".kout-edit", null, function (ev) {
var current = ko.dataFor(this);
current.Mode("edit");
})
$(document).on("click", ".kout-update", null, function (ev) {
var current = ko.dataFor(this);
current.Mode("display");
})
Here we see another KO function in use dataFor. This function retrieves any KO object that is bound to the current context. Since we clicked on the Edit/Update button of a row that’s bound to a mappedItem object, KO will return it. Once we have the currently object, we simply flip the Modes.
Running the Application, we can see we can toggle between edit and display modes.
Nice! So without manipulating DOM manually, we have managed to implement seamless Edit functionality. Though data is not going to the Server yet. Let see how we can add the Create functionality as well and then we’ll send data to the server too.
Creating new Rows of Data and Updating Modified Data
We hookup the Create button a click even handler and create a new JS object with the properties Id, Key, Value all set to empty or (zero) and the Mode set to edit. Then we push it into the viewModel.lookupCollection and voila we are done! No change in markup required.
Yup, to get the above all we need is the following snippet of code added to our knockout.samples.js file
$(document).on("click", "#create", null, function (ev) {
var current = {
Id: ko.observable(0),
Key: ko.observable(),
Value: ko.observable(),
Mode: ko.observable("edit")
}
viewModel.lookupCollection.push(current);
});
Next we add a saveData function that takes in a currentData object which is the current LookupItem being edited/added as input parameter.
The function checks if the Id property exists and if it’s non-zero positive number (indicating it has already been saved earlier). If it has a non-zero ID, the current data is POSTed to the /Lookups/Update action. If the ID is 0 the new data is POSTed to the /Lookups/Create action method
function saveData(currentData) {
var postUrl = "";
var submitData = {
Id : currentData.Id(),
Key : currentData.Key(),
Value: currentData.Value()
};
if (currentData.Id && currentData.Id > 0) {
postUrl = "/Lookups/Edit"
}
else {
postUrl = "/Lookups/Create"
}
$.ajax({
type: "POST",
contentType: "application/json",
url: postUrl,
data: JSON.stringify(submitData)
}).done(function (id) {
currentData.Id(id);
}).error(function (ex) {
alert("ERROR Saving");
})
}
We need to make small changes on the Server side. For one, we’ll temporarily disable AntiForgeryToken and next we’ll return a Json with the Id of the entity create/edited. So the update Create method is as follows:
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Create(Lookup lookup)
{
if (ModelState.IsValid)
{
db.Lookups.Add(lookup);
db.SaveChanges();
return Json(lookup.Id);
}
return View(lookup);
}
The Updated Edit method is as follows
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Edit(Lookup lookup)
{
if (ModelState.IsValid)
{
db.Entry(lookup).State = EntityState.Modified;
db.SaveChanges();
return Json(lookup.Id);
}
return View(lookup);
}
Now if we run the application and click on “Create”, we’ll see a new blank row is added:

When we hit the Update button, the data gets Saved.
Next we click Edit and the mode changes to Edit Mode.
We update the value and hit Update to save the changes.
On the server we see the following:

Isn’t that awesome.
We managed Create/Update and List functionalities without manipulating DOM elements manually. No $(<selector>).val() called. No HTML manipulated or injected in our code anywhere!
That’s the magic of KO and working with the View Model.
Based on the comments received in this article, read the second part of this article - KnockoutJS and ASP.NET MVC – Alternate techniques and using the Anti Forgery Token which looks back at the suggestions we received in the comments of that article and answers the questions and explores alternate techniques of doing things
Conclusion
We conclude this post here. This series was inspired by Sumit’s experiences with some new members of a team he is consulting. Learning something new is all about getting in the right groove. Hopefully this article and possibly future ones will get you in the KO groove. Feel free to share your comments/experiences, tips and tricks while learning KO and we’ll try to incorporate them in the future.
Download the entire source code of this article (Github)
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn