ASP.NET Web API: Knockout JS – Simple example of GET, POST, PUT and DELETE

In this article I will not describe of what the knockout is and etc. because about knockout there are many information in web, for instance here and here Steve Sanderson explaining of how to use this framework in ASP.NET Web API application. The goal of this one is to show pure code and shortly explain how it’ works without deeply explanation, i.e. validations and etc.

1) Let’s create ASP.NET Web API application and delete all unused code.

2) Add jquery-1.11.1.min and knockout-3.1.0 libraries to our project

 bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-1.11.1.min.js"));

 bundles.Add(new ScriptBundle("~/bundles/knockout").Include("~/Scripts/knockout-{version}.js"));

3) Create UserController

    public class UserController : ApiController
    {
        // GET api/<controller>
        [ResponseType(typeof(IEnumerable<User>))]
        public IHttpActionResult Get()
        {
            return Ok(UserFakeRepository.GetAll());
        }

        // GET api/<controller>/5
        [ResponseType(typeof(User))]
        public IHttpActionResult Get(int id)
        {
            return Ok(UserFakeRepository.GetById(id));
        }

        // POST api/<controller>
        [ResponseType(typeof(User))]
        public IHttpActionResult Post(User user)
        {
            return Ok(UserFakeRepository.Insert(user));
        }

        // PUT api/<controller>/5
        public void Put(User user)
        {
            UserFakeRepository.Update(user);
        }

        // DELETE api/<controller>/5
        public void Delete(int id)
        {
            UserFakeRepository.Delete(id);
        }
    }

 

this ApiController does next:

Get() – gets all users.

Get(int id) – gets user by id.

Post(User user) – this method like insert, so you need to call this one if you want to create new entry in a DB.

Put(User user) – this method like update, call this one if you want to update existing entries.

to do request directly to the API you can use POSTMAN extension for Google Chrome:

(all data returns / sends in JSON)

postman

4) Add UserFakeRepository to simulate our database

    public class UserFakeRepository
    {
        public static User GetById(int id)
        {
            return new User { Id = 1, FirstName = "Sergey", LastName = "Boiko", Age = 26 };
        }

        public static IEnumerable<User> GetAll()
        {
            var res = new[]
            {
                new User { Id = 1, FirstName = "Sergey", LastName = "Boiko", Age = 26 },
                new User { Id = 2, FirstName = "Bob", LastName = "Williams", Age = 30 },
                new User { Id = 3, FirstName = "Jony", LastName = "Thomas", Age = 14 },
                new User { Id = 4, FirstName = "Alan", LastName = "Jackson", Age = 42 },
            };

            return res;
        }

        public static User Update(User entity)
        {
            //TODO: Add your amazing code
            return entity;
        }

        public static User Insert(User entity)
        {
            //TODO: Add your amazing code
            return entity;
        }

        public static bool Delete(int id)
        {
            //TODO: Add your amazing code
            return true;
        }
    }

5) Add User entity

    public class User
    {
        public int Id { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public int Age { get; set; }
    }

6) At the bottom of /Home/Index.cshtml add script.

This is the yummiest part :) UsersViewModel it’s nothing more than simple JavaScript class that has methods, in current example we have only CRUD ones, and knockout init part.

Interesting moment in the our ViewModel:

ko.observableArray() – initialize an empty observable array to be able in future to detect changes of our model. Please, read more here about this one. Observables things helps us to build powerful dynamically UI with writing of JavaScript code as minimum as possible. So we can track any changes with our users lis.

And after DOM is ready, initializeknockout binding with ViewModel

ko.applyBindings(new UsersViewModel());

@section scripts
{
    <script language="javascript">

        //When the DOM is loaded, call the ko.applyBindings() and pass in a new instance of the UsersViewModel:
        $(document).ready(function () {
            ko.applyBindings(new UsersViewModel());
        });

        //Create a user view-model class:
        function UsersViewModel() {

            var self = this;
            var baseUri = "http://local.test-knockout-stuff.com/api/user";
            self.users = ko.observableArray(); // Init an empty observable array

            self.create = function (formElement) {
                $.post(baseUri, $(formElement).serialize(), null, "json")
                    .done(function (o) {
                        self.users.push(o);
                    });
            }
            self.update = function (user) {
                $.ajax({
                    type: "PUT",
                    url: baseUri,
                    data: user
                });
            }
            self.remove = function (user) {
                // First remove from the server, then from the view-model.
                $.ajax({
                    type: "DELETE",
                    url: baseUri + '/' + user.Id
                }).done(function () {
                    self.users.remove(user);
                });
            }

            // Adds the value and notifies observers
            $.getJSON(baseUri, self.users);
        }
    </script>
}

 

7) On the /Home/Index.cshtml add next html code

Here we can see html code with knockout instructions. All knockout things are in data-bind attribute. Btw. to be able to clearly see knockout code, I strongly recommend you to set (for instance) yellow color to highlight knockout regions, please, take a look on the snapshot below.

VS options

Take a look how you can simply bind our ViewModel to the html.

<div data-bind="foreach: users">
    <h3 data-bind="text: $data.FirstName + ' ' +$data.LastName"></h3>
    <div><input type="text" data-bind="value: $data.Age" /> </div>
    <input type="button" value="Update" data-bind="click: $root.update" />
    <input type="button" value="Remove Item" data-bind="click: $root.remove" />
</div>

<hr />

<form data-bind="submit: create">
    <div>First Name:</div>
    <div><input type="text" name="FirstName" /></div>
    <div>Last Name:</div>
    <div><input type="text" name="LastName" /></div>
    <div>Age:</div>
    <div><input type="text" name="Age" /></div>
    <button type="submit">Add</button>
</form>

All knockout things happens within data-bind attribute.

data-bind = foreach – will generate html blocks for each user

data-bind = click – will bind button actions with proper user entry and you will be able to delete or update record in DB.

data-bind = value – will bind property of each user with html

So, as you can see, knockout really does all dirty work, with pure jQuery it would madness :)

P.S. When you will be test this example, do not forget change this http://local.test-knockout-stuff.com/api/user url to your, if you will start application from VS, you have to set url like http://localhost:55521/api/user

Source code with demo: TestKnockoutStuff.rar (Visual Studio 2013)