Creating a ToDo list with djondb, ASP.Net Web API and Knockout JS

Intro

In this post, we are going to create a sample ToDo list application using djondb, the enterprise class NoSQL database. The purpose of this article is to show how to use djondb in a Windows environment with .NET framework.

Setting up

First of all, install djondb, here is a video that shows how to do it: http://www.youtube.com/watch?v=Or-DzRTbZpc

Then, install install djondb’s C# driver for Windows. There is also a video for this: http://www.youtube.com/watch?v=ZaKxTLfkJeY.

Now we are running djondb in a Windows environment. Pretty simple.

Designing the application

We want to build a ToDo list. We want to:

  1. Add a task
  2. Retrieve all tasks
  3. Remove a task
  4. Complete a task from the ToDo list

We’ll create a web client using Twitter bootstrap and Knockout.js. We’ll create a REST services layer using ASP.Net Web API with .Net Framework 4.5. And, obvious, we’ll use djondb to store the tasks of the ToDo list.

The image below depicts the architecture of the application:


Designing the data model

We just want to store the task name, the creation date and a flag that indicates if the task is already completed or not.


task: {
  completion: 0,
  rawDate: "2012-12-10T03:19:56.77Z",
  task: "Write a blog"
}

Creating visual studio 2012 solution

We’ll create a new solution with a couple of projects. One project is a console application project that will host the services and the other one is a ASP.Net project that is the client that consumes the services.

Actually, there is no need for the client to be an ASP.NET project because it only will contain an HTML page. I’m doing this just for using the IIS Express web server automatically and save time creating the virtual folder and that stuff.

The console application project is the host that will contain the ASP.Net Web API REST services. I’m doing this for showing you how to host REST services without the need of IIS. I could also create a ASP.Net Web API project for doing this, but this kind of project also creates all the view elements, and I don’t really need that, because my client is not ASP.Net, it is just a plain HTML client.

Let’s see the structure of the Visual Studio 2012 solution:

Repository pattern

Let’s open the console application project and implement the Repository pattern for access the data store. Notice that I’m not using a structured class model, I’m just interchanging JSON data. This is important. Some times there is no really need for having a structured class model in the application because we only want to transport some data to and from the data store. There are some other scenarios where we do want to perform some logic that require us to me more structured and to do some business logic. This is certainly not the case.

So, basically we want to implement the following interface:


    public interface ITaskRepository
    {
        JArray GetAll();
        JObject Get(string id);
        JObject Add(JObject item);
        void Remove(string id);
        void Update(string id, JObject item);
    }

As we saw in the djondb’s c# driver installation video, we need to add the reference to the driver in this project.

Let’s see the code for the GetAll method. Notice that is as simple as get all the data from a namespace, create a JSON array with that, and pass it forward. Do we need more? Not in this case.


        public JArray GetAll()
        {
            var items;
            DjondbConnection connection = DjondbConnectionManager.getConnection(_connString);

            try
            {
                connection.open();
                BSONArrayObj res = connection.find(_dbName, _nsName, "");

                items = JArray.Parse(res.toChar());

                return items;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (connection != null && connection.isOpen())
                    DjondbConnectionManager.releaseConnection(connection);
            }
        }

REST Services layer

Let’s create the controller that inherits from ApiController. And let’s look at the Get method that will retrieve all the tasks from our ToDo list:


    public class TaskController : ApiController
    {
        private static readonly ITaskRepository _todolist = new TaskRepository();

        public JArray Get()
        {
            try
            {
                var items = _todolist.GetAll();
                Console.WriteLine("Get()> {0}", items.ToString());
                return items;
            }
            catch
            {
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            }
        }
        ...
    }

Pretty simple, just pass the JSON array. We are also printing it out to the console just for watching the data that is traveling.

Now we have to create the main that will host the HTTP server that will attend all the REST requests. We are not going to explain this, it’s really very simple, just see the code. You’ll notice that we have included a Message Handler calledd CorsHandler. If you don’t do this, you’ll get some cross domain errors when you try to consume the REST services from the Knockout.js client. The error message you’ll get is this one:


XMLHttpRequest cannot load http://localhost:50123/api/Task/. Origin http://localhost:32359 is not allowed by Access-Control-Allow-Origin.

So we just copied the implementation of CorsHandler from Carlos Figueira blog: http://blogs.msdn.com/b/carlosfigueira/archive/2012/02/20/implementing-cors-support-in-asp-net-web-apis.aspx. And it works sweet.

At this point we can test the services layer using the browser or using a better tool such as Chrome’s simple REST Client or Chrome’s Advanced REST Client. Just run the console application, open the browser and point to the following URL: http://localhost:50123/api/Task. You’ll see an empty list, but you can use the REST client for doing posts to create some sample data.

Creating the UI

Finally, let’s create the Web client. We need Twitter Bootstrap and Knockout.js. We need to create a todoTask “class” that holds the properties of a single task. And a taskViewModel “class” that represents the list of tasks from the ToDo list.

This is the code for the todoTask model:


function todoTask(id, task, rawDate) {
            var self = this;
            self._id = id;
            self.task = task;
            self.rawDate = rawDate;
            self.completion = ko.observable(false);

            self.date = ko.computed(function () {
                var day = rawDate.getDate();
                var month = rawDate.getMonth() + 1;
                var year = rawDate.getFullYear();
                var dateFull = month + '/' + day + '/' + year;
                return dateFull;
            });

            self.completeTask = function () {
                var isDone = self.completion() ? 0 : 1;

                $.ajax({
                    type: "PUT",
                    url: serverUrl + self._id,
                    data: { _id: self._id, task: self.task, completion: isDone },
                    success: function () {
                        if (self.completion() == false)
                            self.completion(true);
                        else
                            self.completion(false);
                    },
                    failure: function (errMsg) { console.log(errMsg); }
                });
            };
        }

And this is the code for the taskViewModel that represents the task collection:


function taskViewModel() {
            var self = this;
            self.newTask = ko.observable('');
            self.tasks = ko.observableArray([]);

            self.completedTasks = ko.computed(function () {
                var total = 0;
                var i = 0;
                for (i; i < self.tasks().length; i++) {
                    if (self.tasks()[i].completion() == false) {
                        total++;
                    }
                }

                return total;
            });

            self.addTask = function () {
                var newTask = new todoTask("", self.newTask(), new Date());
                newTask.completion(false);

                $.ajax({
                    type: "POST",
                    url: serverUrl,
                    data: ko.toJSON(newTask),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (retData) {
                        newTask._id = retData["_id"];
                        self.tasks.push(newTask);
                        self.newTask('');
                    },
                    failure: function (errMsg) { console.log(errMsg); }
                });
            }

            self.removeTask = function () {
                var removedTask = this;

                $.ajax({
                    type: "DELETE",
                    url: serverUrl + removedTask._id,
                    success: function () {
                        self.tasks.remove(removedTask);
                    },
                    failure: function (errMsg) { console.log(errMsg); }
                });
            }

            $.getJSON(serverUrl, function (allData) {
                var mappedTasks = $.map(allData, function (item) {
                    var newTodoTask = new todoTask(item["_id"], item["task"], new Date(item["rawDate"]));
                    newTodoTask.completion(item["completion"]);
                    return newTodoTask;
                });

                self.tasks(mappedTasks);
            });

And now let's create the HTML to bind to the Knockout objects:


<div id="content" class="span12">
                <form data-bind="submit: addTask">
                    <h2 class="form-todo-heading">ToDo List</h2>
                    <input type="text" name="task-input" id="task-input" data-bind="value: newTask" class="input-block-level" placeholder="What needs to be done?" />
                </form>

                <div class="todos">
                    <ul id="todo-list" data-bind="foreach: tasks">
                        <li>
                            <div class="todo">
                                <div data-bind="css: { completed: completion() == true }">
                                    <a href="javascript:void(0)" class="checkbox" data-bind="click: completeTask"></a>
                                    <span class="todo-text" data-bind="text: task"></span>
                                    <span class="todo-date" data-bind="text: date"></span>
                                    <a href="javascript:void(0)" class="todo-destroy" data-bind="click: $root.removeTask">&times;</a>
                                </div>
                            </div>
                        </li>
                    </ul>

                    You have <b><span class="tasks-left" data-bind="text: completedTasks()"></span></b> tasks to do
		            &nbsp;&nbsp;<b><span data-bind="visible: completedTasks() == 0">- its beer time!</span></b>
                </div>
            </div>

Running the sample application

First, start djondb server. Just run djondb_win.exe from the installation folder, the default is: C:\Program Files (x86)\djondb:


C:\Program Files (x86)\djondb>djondb_win.exe
INFO: djondbd version 0.120121125 is starting up.
INFO: Starting network service. port: 1243
INFO: DBController initializing. Data dir
INFO: Accepting new connections

Then, run the console application project from Visual Studio:


Running on http://localhost:50123/api/Task
Hit ENTER to exit...

And finally run the client application also from Visual Studio in the browser:

Download the code

You can download the code from my GitHub repository.

Posted in djondb application, NoSQL Samples and tagged .
Loading Facebook Comments ...

Leave a Reply

Your email address will not be published. Required fields are marked *