Knockout.js with ASP.NET

Knockout.js is a popular standalone JavaScript implementation of Model-View-ViewModel (MVVM) pattern. It’s a great framework to create modern web applications, single page applications or JavaScript UIs.

For more details about knockout.js check their web site http://knockoutjs.com/index.html

For learning knockout.js check their interactive learning site http://learn.knockoutjs.com/#/?tutorial=intro

For more details about MVVM check http://en.wikipedia.org/wiki/Model-View-ViewModel

Knockout.js can be seamlessly integrated with ASP.NET projects, you can consume ASP.NET web services in knockout.js pages.

In this article, we’re going to create Expense list application using knockout.js and ASP.NET web services.

Setting up the Project

We need the following tools to create the project:

1.       Visual Studio 2013 (any earlier version will also do)

2.       Knockout.js (download from http://knockoutjs.com/downloads/knockout-3.0.0.js)

3.       Jquery.js (download from http://jquery.com/download/)

4.       Json.NET (download from within Visual Studio using NuGet package manager)

Create a new ASP.NET web project in Visual Studio with Empty as template.

Create a new folder called JS in Solution Explorer under project

Copy knockout.js and jquery.js in side JS folder

Create ASP.NET web service

We’re going to create a ASP.NET web service that will return JSON data to knockout.js.

Right Click on Project and select Add New Item

Select WCF Service (Ajax-enabled) , name your class ExpensesService.svc

Add the following code to class:

public class ExpensesService

{

List<Expense> lstExpense = new List<Expense>();

private void LoadExpenses()

{

lstExpense.Clear();

for (int i = 0; i < 3; i++ )

{

lstExpense.Add(new Expense() { ID = i + 1, Title = "Bills - " + (i + 1), Amount = (i + 1) * 1000, Paid = true });

}

}

 

[OperationContract]

public string GetAllExpenses()

{

LoadExpenses();

return JsonConvert.SerializeObject(lstExpense);

}

 

[OperationContract]

public string GetExpense(int ID)

{

LoadExpenses();

var ex1 = lstExpense.Find(ex => ex.ID == ID);

return JsonConvert.SerializeObject(ex1);

}

[DataContract]

public class Expense

{

[DataMember]

public int ID;

[DataMember]

public string Title;

[DataMember]

public int Amount;

[DataMember]

public bool Paid;

}

}

Code explanation

We’ve created 2 methods in ExpensesService web service, GetAllExpenses() and GetExpense(ID)

GetAllExpenses() return JSON data of all expenses, for the example sake we’ve hard-coded the values, it can be easily replaced with database interaction code.

GetExpense() return a single expense object in JSON format.

We’ve also created a DataContract called Expense that is the definition of the Expense object (ID, Title, Amount & Paid).

Now the service is ready to be consumed by knockoutjs.

Creating JavaScript UI with knockout.js

Right Click on Project and select Add New Item

Select Web Form , name your page main

Replace main.aspx with the following:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="main.aspx.cs" Inherits="knockoutTest.main" %>

 

<!DOCTYPE html>

 

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

 

<meta charset="utf-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<!-- Bootstrap -->

<link href="css/bootstrap.min.css" rel="stylesheet" media="screen" />

<title>knockoutTest</title>

</head>

<body>

<form id="form1" runat="server">

<div>

 

<asp:ScriptManager ID="ScriptManager1" runat="server">

<Services>

<asp:ServiceReference Path="~/ExpensesService.svc" />

</Services>

</asp:ScriptManager>

 

<h3>Expense Tracking</h3>

 

<table class="table table" style="width: 50%;">

<thead>

<tr>

<td><b>Paid</b></td>

<td><b>Expense</b></td>

<td><b>Amount</b></td>

<td></td>

</tr>

</thead>

<tbody data-bind="foreach: expenses, visible: expenses().length > 0" >

<tr>

<td><input type="checkbox" data-bind="checked: Paid" /></td>

<td><input data-bind="value: Title, disable: Paid" /></td>

<td><input data-bind="value: Amount, disable: Paid" /></td>

<td><a href="#" data-bind="click: $parent.removeExpense">Delete</a></td>

</tr>

</tbody>

</table>

 

</div>

</form>

 

<form data-bind="submit: addExpense">

<b>Add Expense:</b>

<input data-bind="value: newExpenseText" placeholder="What is the expense?" />

<input data-bind="value: newAmountText" placeholder="Amount?" />

<button type="submit">Add</button>

</form>

 

 

<script type="text/javascript" src="js/knockout-3.0.0.js"></script>

<script type="text/javascript" src="js/jquery.js"></script>

 

<script type="text/javascript">

 

function Expense(data)

{

this.ID = ko.observable(data.ID);

this.Title = ko.observable(data.Title);

this.Amount = ko.observable(data.Amount);

this.Paid = ko.observable(data.Paid);

}

 

function ExpenseListViewModel() {

//Data

var self = this;

 

self.expenses = ko.observableArray([]);

self.newExpenseText = ko.observable();

self.newAmountText = ko.observable();

 

//Operations

self.addExpense = function () {

self.expenses.push(new Expense({ Title: this.newExpenseText(), Amount: this.newAmountText() }));

self.newExpenseText("");

self.newAmountText("100");

};

 

self.removeExpense = function (expense) {

 

if (confirm("Sure to delete?"))

{

self.expenses.remove(expense)

}

};

 

//load data from WCF service

ExpensesService.GetAllExpenses(

function (result)

{

//callback success function

var mappedExpenses = $.map(JSON.parse(result), function (item) { return new Expense(item) });

self.expenses(mappedExpenses);

},

function (err)

{

//callback error function

alert(err.get_message());

});

 

}

//Activates knockout.js

ko.applyBindings(new ExpenseListViewModel());

 

</script>

</body>

</html>

 

Code explanation

JavaScript:

Create JavaScript class Expense that maps the DataContract in ExpensesService web service.

Create knockout.js view model ExpenseListViewModel

Create expenses as onservableArray.

Create newExpenseText and newAmountText as observable properties.

Create addExpense and removeExpense as methods of view model ExpenseViewModel.

Call ExpensesService.GetAllExpenses from view model ExpenseListViewModel and map the resultant JSON into expenses observableArray.

HTML:

Add reference to ExpensesService in our aspx page by using ScriptManager tags.

Add reference to knockout.js and jquery.js.

Add knockout.js data-bind attribute to TBODY tag. This attribute uses knockout.js foreach to loop thru expenses observableArray from the view model ExpenseListViewModel.

Add knockout.js data-bind attribute to input elements to connect to Expense object properties (Paid, Title, Amount).

Add knockout.js data-bind attribute to the Delete link and call removeExpense method of view model ExpenseViewModel.

Add knockout.js data-bind attribute to the form and call addExpense method of view model ExpenseViewModel.

Summary

In this article we explored how to integrate knockout.js with ASP.NET projects. Knockout.js is a great framework to create modern web UI and single page web applications and ASP.NET is a flag-ship web server technology from Microsoft. We have best of both when we combine these technologies and create rich and responsive web applications. It’s highly recommended for your current and new ASP.NET projects.

By Shameem Ahmed   Popularity  (4424 Views)