Please enable Javascript to correctly display the contents on Dot Net Tricks!

Web API CRUD Operations with Knockout

Posted By : Shailendra Chauhan, 01 Apr 2013
Updated On : 01 Apr 2013
Total Views : 21,284   
 

In previous article, I have explained Knockout CRUD Operations using MVC4. In this article, I will demonstrate, how to use Knockout with Web API for CRUD (Create, Read, Update, Delete) Operations.

Step 1: Define Model

Product.cs

public class Product
{
 public int Id { get; set; }
 public string Name { get; set; }
 public string Category { get; set; }
 public decimal Price { get; set; }
}

IProductRepository.cs

interface IProductRepository
{
 IEnumerable<Product> GetAll();
 Product Get(int id);
 Product Add(Product item);
 bool Update(Product item);
 bool Delete(int id);
}

ProductRepository.cs

public class ProductRepository : IProductRepository
{
 private List<Product> products = new List<Product>();
 private int _nextId = 1;

 public ProductRepository()
 {
 // Add products for the Demonstration
 Add(new Product { Name = "Computer", Category = "Electronics", Price = 23.54M });
 Add(new Product { Name = "Laptop", Category = "Electronics", Price = 33.75M });
 Add(new Product { Name = "iPhone4", Category = "Phone", Price = 16.99M });
 }

 public IEnumerable<Product> GetAll()
 {
 // TO DO : Code to get the list of all the records in database
 return products;

 }

 public Product Get(int id)
 {
 // TO DO : Code to find a record in database
 return products.Find(p => p.Id == id);

 }

 public Product Add(Product item)
 {
 if (item == null)
 {
 throw new ArgumentNullException("item");
 }
 
 // TO DO : Code to save record into database
 item.Id = _nextId++;
 products.Add(item);

 return item;
 }
 public bool Update(Product item)
 {
 if (item == null)
 {
 throw new ArgumentNullException("item");
 }
 
 // TO DO : Code to update record into database
 int index = products.FindIndex(p => p.Id == item.Id);
 if (index == -1)
 {
 return false;
 }
 products.RemoveAt(index);
 products.Insert(index,item);

 return true;
 }

 public bool Delete(int id)
 {
 // TO DO : Code to remove the records from database
 products.RemoveAll(p => p.Id == id);

 return true;
 }
}

Step 2: Define Controller

HomeController.cs

public class HomeController : Controller
{
 public ActionResult Product()
 {
 return View();
 }
}

ProductController.cs for Web API

public class ProductController : ApiController
{
 static readonly IProductRepository repository = new ProductRepository();

 public IEnumerable GetAllProducts()
 {
 return repository.GetAll();
 }

 public Product PostProduct(Product item)
 {
 return repository.Add(item);
 }

 public IEnumerable PutProduct(int id, Product product)
 {
 product.Id = id;
 if (repository.Update(product))
 {
 return repository.GetAll();
 }
 else
 {
 return null;
 }
 }

 public bool DeleteProduct(int id)
 {
 if (repository.Delete(id))
 {
 return true;
 }
 else
 {
 return false;
 }

 }
}

Step 3: Define View

Product.cshtml

@{
 ViewBag.Title = "Products' List";
}

@section scripts {
 <style type="text/css">
 body {
 margin: 20px;
 font-family: "Arial", "Helventica", sans-serif;
 }

 label {
 width: 80px;
 display: inline-block;
 }

 button {
 display: inline-block;
 outline: none;
 cursor: pointer;
 text-align: center;
 text-decoration: none;
 padding: .4em 1.1em .4em;
 color: #fef4e9;
 border: solid 1px #006fb9;
 background: #1276bb;
 }

 button:hover {
 text-decoration: none;
 background: #282828;
 border: solid 1px #000;
 }

 table {
 padding-top: 1em;
 }

 thead, tfoot {
 font-weight: 600;
 }

 th, td {
 padding: .1em .5em;
 text-align: left;
 }

 td li, td ul {
 margin: 0;
 padding: 0;
 }

 td li {
 display: inline;
 }

 td li::after {
 content: ',';
 }

 td li:last-child::after {
 content: '';
 }
 </style>
 <script src="~/Scripts/knockout-2.2.0.js"></script>
 <script src="@Url.Content("~/Scripts/knockout-2.2.0.debug.js")" type="text/javascript"></script>
 <script type="text/javascript">

 function formatCurrency(value) {
 return "$" + value.toFixed(2);
 }

 function ProductViewModel() {

 //Make the self as 'this' reference
 var self = this;
 //Declare observable which will be bind with UI 
 self.Id = ko.observable("");
 self.Name = ko.observable("");
 self.Price = ko.observable("");
 self.Category = ko.observable("");

 var Product = {
 Id: self.Id,
 Name: self.Name,
 Price: self.Price,
 Category: self.Category
 };

 self.Product = ko.observable();
 self.Products = ko.observableArray(); // Contains the list of products

 // Initialize the view-model
 $.ajax({
 url: 'api/product',
 cache: false,
 type: 'GET',
 contentType: 'application/json; charset=utf-8',
 data: {},
 success: function (data) {
 self.Products(data); //Put the response in ObservableArray
 }
 });

 // Calculate Total of Price After Initialization
 self.Total = ko.computed(function () {
 var sum = 0;
 var arr = self.Products();
 for (var i = 0; i < arr.length; i++) {
 sum += arr[i].Price;
 }
 return sum;
 });

 //Add New Item
 self.create = function () {
 if (Product.Name() != "" && Product.Price() != "" && Product.Category() != "") {
 $.ajax({
 url: 'api/product',
 cache: false,
 type: 'POST',
 contentType: 'application/json; charset=utf-8',
 data: ko.toJSON(Product),
 success: function (data) {
 // alert('added');
 self.Products.push(data);
 self.Name("");
 self.Price("");
 self.Category("");

 }
 }).fail(
 function (xhr, textStatus, err) {
 alert(err);
 });

 }
 else {
 alert('Please Enter All the Values !!');
 }

 }
 // Delete product details
 self.delete = function (Product) {
 if (confirm('Are you sure to Delete "' + Product.Name + '" product ??')) {
 var id = Product.Id;
 $.ajax({
 url: 'api/product/' + id,
 cache: false,
 type: 'DELETE',
 contentType: 'application/json; charset=utf-8',
 data: {},
 success: function (data) {
 self.Products.remove(Product);

 }
 }).fail(
 function (xhr, textStatus, err) {
 alert(err);
 });
 }
 }

 // Edit product details
 self.edit = function (Product) {
 self.Product(Product);

 }

 // Update product details
 self.update = function () {
 var Product = self.Product();
 var id = Product.Id;

 $.ajax({
 url: 'api/product/' + id,
 cache: false,
 type: 'PUT',
 contentType: 'application/json; charset=utf-8',
 data: ko.toJSON(Product),
 success: function (data) {
 self.Products.removeAll();
 self.Products(data); //Put the response in ObservableArray
 self.Product(null);
 alert("Record Updated Successfully");
 
 }
 })
 .fail(
 function (xhr, textStatus, err) {
 alert(err);
 });
 }
 
 // Reset product details
 self.reset = function () {
 self.Name("");
 self.Price("");
 self.Category("");
 }

 // Cancel product details
 self.cancel = function () {
 self.Product(null);

 }
 }
 var viewModel = new ProductViewModel();
 ko.applyBindings(viewModel);

 </script>
}

<div id="body">

 <h2>Knockout CRUD Operations with MVC4</h2>

 <h3>List of Products</h3>

 <table id="products1" data-bind="visible: Products().length > 0">
 <thead>
 <tr>
 <th>ID</th>
 <th>Name</th>
 <th>Category</th>
 <th>Price</th>
 <th>Actions</th>
 </tr>
 </thead>
 <tbody data-bind="foreach: Products">
 <tr>
 <td data-bind="text: Id"></td>
 <td data-bind="text: Name"></td>
 <td data-bind="text: Category"></td>
 <td data-bind="text: formatCurrency(Price)"></td>

 <td>
 <button data-bind="click: $root.edit">Edit</button>
 <button data-bind="click: $root.delete">Delete</button>

 </td>

 </tr>
 </tbody>
 <tfoot>
 <tr>
 <td></td>
 <td></td>
 <td>Total :</td>
 <td data-bind="text: formatCurrency($root.Total())"></td>
 <td></td>
 </tr>
 </tfoot>
 </table>
 <br />
 <div style="border-top: solid 2px #282828; width: 430px; height: 10px"> </div>

 <div data-bind="if: Product">
 <div>
 <h2>Update Product</h2>
 </div>
 <div>
 <label for="productId" data-bind="visible: false">ID</label>
 <label data-bind="text: Product().Id, visible: false"></label>

 </div>
 <div>
 <label for="name">Name</label>
 <input data-bind="value: Product().Name" type="text" title="Name" />
 </div>

 <div>
 <label for="category">Category</label>
 <input data-bind="value: Product().Category" type="text" title="Category" />
 </div>

 <div>
 <label for="price">Price</label>
 <input data-bind="value: Product().Price" type="text" title="Price" />

 </div>
 <br />
 <div>
 <button data-bind="click: $root.update">Update</button>
 <button data-bind="click: $root.cancel">Cancel</button>

 </div>
 </div>

 <div data-bind="ifnot: Product()">
 <div>
 <h2>Add New Product</h2>
 </div>
 <div>
 <label for="name">Name</label>
 <input data-bind="value: $root.Name" type="text" title="Name" />
 </div>

 <div>
 <label for="category">Category</label>
 <input data-bind="value: $root.Category" type="text" title="Category" />
 </div>

 <div>
 <label for="price">Price</label>
 <input data-bind="value: $root.Price" type="text" title="Price" />
 </div>
 <br />
 <div>
 <button data-bind="click: $root.create">Save</button>
 <button data-bind="click: $root.reset">Reset</button>

 </div>
 </div>

</div>

Step 4: Run Application - Retrieve Operation

Step 4: Insert Operation

Step 4: Update Operation

Step 4: Delete Operation

What do you think?

I hope you will enjoy the tips while working with Knockout and Web API. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.


 
Recommended for you
 
About the Author
Shailendra Chauhan

Shailendra Chauhan is an Entrepreneur, Author, Architect, and Corporate Trainer. He has rewarded as Microsoft MVP for his exceptional contributions in Microsoft Visual Studio and Development Technologies.

With more than 7 years in hand experience Shailendra Chauhan is a polymath in the domains of Microsoft .NET technologies and an array of other technologies including JavaScript, AngularJS, Node.js, Ionic and NoSQL Databases to name but a few.

He is the author of some of most popular e-books which encompass technical Interview on Node.js Interview Questions and Answers , ASP.NET MVC Interview Questions and Answers , AngularJS Interview Questions and Answers and LINQ Interview Questions and Answers. Furthermore he is a technical reviewer for book on ASP.NET MVC 4 Mobile App Development. Know more...
 
Free Interview Books
 
1 AUG
NodeJS Development (online)

Thursday 06:00 AM-7:30 AM IST

More Details
25 JUL
ASP.NET MVC with AngularJS Development (online)

Mon-Fri     (07:30 AM-09:00 AM IST)

25 JUL
AngularJS Development (online)

Mon-Fri     09:00 PM-10:30 PM IST

24 JUL
ASP.NET MVC with AngularJS Development (offline)

Sat, Sun     09:30 AM-11:00 AM

24 JUL
AngularJS Development (offline)

Sat,Sun     (08:00 AM-09:30 AM)

2 JUL
ASP.NET MVC with AngularJS Development (offline)

Sat, Sun     (03:00 PM-05:00 PM IST)

27 JUN
ASP.NET MVC with AngularJS Development (online)

Mon - Fri     (07:00 AM-09:00 AM IST)

BROWSE BY CATEGORY
 
SUBSCRIBE TO LATEST NEWS
 
LIKE US ON FACEBOOK
 
+