Introduction
This article shows Databinding and Templating using Knockout in the ASP.NET Web API. In this article we use the Knockout.js file. Knockout contains a JavaScript library and this library helps for creating a responsive display and editor user interface under laying of the data model.
Use the following procedure to create a sample.
Step 1
First we create a Web API application:
- Start Visual Studio 2012.
- From the Start window select "Installed" -> "Visual C#" -> "Web".
- Select "ASP.NET MVC4 Web Application" and click on the "OK" button.
- From the MVC4 Project window select "Web API".
- Click on the "OK" button.
Step 2
Create a Model class:
- In the "Solution Explorer".
- Right-click on the "Model" -> "Add" -> "Class".
- Select "Installed" -> "Visual C#".
- And then select "Class" and click on the "OK' button.
Add the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Knockoutbinding.Models
{
public class Post
{
public int P_Id { get; set; }
public string P_Title { get; set; }
public string P_Post { get; set; }
public string P_Comments { get; set; }
public bool P_IsDeleted { get; set; }
}
}
Step 3
Now Rename "ValuesController" to "PostsController". This file exists in the "Controller folder".
Add the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Knockoutbinding.Models;
using System.Web;
namespace Knockoutbinding.Controllers
{
public class PostsController : ApiController
{
List<Post> PostContext;
public PostsController()
{
if (HttpContext.Current.Application["postContext"] == null)
{
HttpContext.Current.Application["postContext"] = new List<Post>();
((List<Post>)HttpContext.Current.Application["postContext"]).Add(
new Post { P_Id = 1, P_Title = "Enter Title 1", P_IsDeleted = false, P_Post = "Post_No 1" });
((List<Post>)HttpContext.Current.Application["postContext"]).Add(
new Post { P_Id = 2, P_Title = "Enter Title 2", P_IsDeleted = false, P_Post = "Post_No 2" });
}
PostContext = (List<Post>)(HttpContext.Current.Application["postContext"]);
}
// GET api/values
public IEnumerable<Post> Get()
{
return PostContext;
}
// GET api/values/5
public Post Get(int id)
{
Post current = PostContext.Find(p => p.P_Id == id && !p.P_IsDeleted);
if (current == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
else
{
return current;
}
}
// POST api/values
public void Post([FromBody]Post value)
{
value.P_Id = PostContext.Count + 1;
PostContext.Add(value);
}
// PUT api/values/5
public void Put(int id, [FromBody]Post value)
{
Post current = PostContext.Find(p => p.P_Id == id);
if (current == null || current.P_IsDeleted)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
else
{
current.P_Title = value.P_Title;
current.P_Post = value.P_Post;
current.P_IsDeleted = value.P_IsDeleted;
}
}
// DELETE api/values/5
public void Delete(int id)
{
Post current = PostContext.Find(b => b.P_Id == id);
if (current == null || current.P_IsDeleted)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
else
{
current.P_IsDeleted = true;
}
}
}
}
Step 4
Now create a knockout.js file as in the following:
- In the "Solution Explorer".
- Right-click on the "Script" folder select "Add" -> "New Item".
- Then select "JavaScript". Click on the "Add" button.
Add the following code:
var viewModel =
{
posts: ko.observableArray([]),
selectedPost: ko.observable(null),
selectPost: function (post) {
viewModel.selectedPost(this);
$(".right-section").show();
},
newPost: function () {
this.posts.push({
P_Title: ko.observable("New Post " + this.posts().length),
P_Id: ko.observable(this.posts().length+1),
P_Post: ko.observable("Post_No " + this.posts().length),
IsNew: ko.observable(true)
});
}
}
$(document).ready(function () {
$(".right-section").hide();
$.ajax(
{
url: "/api/Posts",
contentType: "text/json",
type: "GET",
success: function (data) {
$.each(data, function (index) {
viewModel.posts.push(toKoObserable(data[index]));
});
ko.applyBindings(viewModel);
},
error: function (data) {
alert("ERROR");
}
});
function toKoObserable(post) {
return {
P_Id: ko.observable(post.P_Id),
P_Title: ko.observable(post.P_Title),
P_Post: ko.observable(post.P_Post),
P_Comments: ko.observable(post.P_Comments),
P_IsDeleted: ko.observable(post.P_IsDeleted)
};
}
$("#saveAll").click(function () {
var saveData = ko.toJS(viewModel.posts);
$.each(saveData, function (index) {
var current = saveData[index];
var action = "PUT";
var stringyF = JSON.stringify(current);
var vUrl = "/api/Posts?P_Id=" + current.P_Id;
if (current.IsNew) {
action = "POST";
vUrl = "/api/Posts";
}
$.ajax(
{
url: vUrl,
contentType: "application/json;charset=utf-8",
type: action,
data: JSON.stringify(current)
});
});
});
});
Provide the reference of this file in the "Index.cshtml" file.
Step 5
Now write some HTML code and a reference of the Knockout file in the View "index.cshtml". This file exists in the "Home" folder.
Add the following code:
<div id="body">
<div class="left-section" style="height: 600px; width: 25%; float: left; background-color: #b9b9b9">
<h2>Posts</h2>
<button data-bind="click: newPost">New Post</button>
<button id="saveAll">Save</button>
<ul data-bind="foreach: posts">
<li style="list-style: none">
<a data-bind="text: P_Title, id: P_Id" href="#"></a>
<input type="button" value="Select" data-bind="click: $parent.selectPost" />
</li>
</ul>
</div>
<div class="right-section" style="height: 600px; width: 75%; float: left; background-color: #d9d9d9"
data-bind="with: selectedPost">
<div>
Post Title:
<input data-bind="value: P_Title" />
</div>
<div>
Post Number:
<textarea data-bind="value: P_Post" ></textarea>
</div>
</div>
</div>
@section Scripts{
<script src="~/Scripts/knockout-2.2.0.js"></script>
<script src="~/Scripts/ko-post.js"></script>
}
Step 6
Execute the application:
When we click on the select button it displays two TextBoxes, one for the title and the other displays the post number.
When click on New Post button then it adds a new post: