In
Part I Define a Selection Process the selection criteria was established. This release attempts to use KnockoutJS and BackboneJS under the same scenario to carry out the evaluation. The project used was created using Visual Studio 2012 Express for Web. No database is required for this test. This project can be downloaded at the end of this article.
The Application
The application displays a collection of products and it allows the client to update and create a product.
When the browser requests the URL of the site the client
gets a collection of products from the server. The client can also
get a product for a valid product id. When the product is updated, or
put to the server with updates, the product collection is also refreshed to show the new change. Inside of the "Add New Product" tab a new product can be
posted and this change also refreshes the product collection with the new item added.
In the MVVM pattern the ViewModel is driving all this logic and behavior of the application. The view binds to properties of this ViewModel which in turns exposes data obtained from the Model (server side) entities.
Two solutions will implement the scenarios described above. One implementation will use KnockoutJS and the second one BackboneJS.
The Knockout Solution
The view need to display the collection of products and for this it uses a table HTML element. The body of the table is bound to a an observable collection in the ViewModel shown later.
Pay attention to lines 13 to 21. The code is telling knockout that a property of the ViewModel named "products" is bound to a
foreach loop which in turn copies the section of markup for each element of the collection, in this case each product.
The following ViewModel, when instantiated, loads the collection of products from the server with a GET. Thus far, we are not able to change anything because the product properties are binding to TEXT in the markup. Executing code like that would get us the products from the server and the grid view displays. Not much, but we are on our way.
The code above is self explanatory. It shows that the ViewModel contains a ProductViewModel with properties of the Product (Id, Name, Category, and Weight) and it contains two observable objects: a knockout ObservableArray and a knockout Observable product.
 |
| Details Section |
The Details section contains two tabs: one to search/Display/Update a product and the other to create a new one. To GET a product by its ID the get button is bound to "getById" function of the ViewModel. Note that "
if" a product is returned then the "
if binding" displays the section of markup corresponding to the product in the ViewModel. Note that "product" is used as if a function was being called.
Note the the "click" events of the buttons to GET and PUT, fetch and update respectively, are bound to the "getById" and "update" ViewModel functions respectively.
Get Product By Id
Put Product (update)
Note that line 16 indicates that ajax will send a PUT. We could have used a POST to update the product however that would be using the wrong HTTP verb for the update. Note that inside the ajax success handler , Line 20, there is call to "getAll()". This ViewModel function is responsible for updating the products collection after a successful update and by Knockout magic the product grid is updated.
Get All
this function removes all member of the collection and get them again with $.getJSON and populates the observable array and because the table body is "observing" this collection then Knockout refreshes the table body.
Create a New Product
The html markup content of the create new product tab shown above is simple. Note that the "Add New" product button is bound to the "create" method of the ViewModel.
The code of the create new product function is straight forward. However, note that Line 19 above is not doing a GET to update the ObservableArray products but instead it updates the collection and by doing this the collection also notifies the grid view, the table, that it needs updating and Knockout renders the table again.
How is Everything Started in the Knockout Solution?
The magic kicks in by instantiating the ViewModel and applying the Knockout bindings on this ViewModel. Easy?
The Backbone Solution
A bit of a confession; I started this project in order to learn BackboneJS and with a bit more exposure to the KnockoutJS framework. This means that what I am sharing with you is in a bit of disadvantage vs the Knockout solution and this might influence my decision when grading the level of difficulty between the two implementations.
While the Knockout implementation was very straight forward the Backbone implementation forced me to pick up a pencil and design my views and models. This solution might change later on but this is what I came up with first go. The design went thought some growing pains because I wanted to use the Backbone framework as much as I could and not have markup on the page that was not handled by Backbone.
There are differences on how these framework deal with HTTP verbs and how the Model, the back end entity, is created, updated or deleted. The Knockout solution explicitly implemented the GET with $.getJSON and POST/PUT using $.ajax by sending the respective request type. Backbone is a bit more refined in this sense and implements this mechanism for us and hides it in the lib. However, this has its cons. This means that someone who know jQuery and JavaScript opens a Backbone solution implementation and it turns difficult to know what is going on first view.
Framework Classes
Backbone has six main classes:
- Backbone.Model
- Backbone.Collection (also a Model)
- Backbone.View
- Backbone.Events
- Backbone.Router
- Backbone.History
In this research we are creating objects of the type Model, Collection and View by extending the Backbone classes Model, Collection and View respectively.
The Product Model
As for the Knockout solution, for this solution a Product model is also required.
Important to note how properties of the model are created. the defaults function is executed as soon as the model is instanciated. This is one way to set these properties. Properties can also be added to the model by using "setters" , so we could also write:
It is very important to note Line 9, of our Product Model the Model.url. This is where Backbone is going to GET the resource from when we pass the id to this URL when the model is fetched with Model.fetch(). Model.fecth() delegates to Backbone.sync to save or read the model from the server. Fetch uses by default jQuery.ajax to do the RESTful JSON request, just like Knockout with the difference that Backbone "hides" this from the user; one needs to know this magic trick.
The Product Collection Model
The model property of the collection indicates to Backbone the type that the collection contains, in this case a Product Model. Note the URL of the collection model. This is the URL used by Backbone for the RESTful JSON request PUT/POST when the client calls save() on the Product is not new when we are updating or is new when we are posting a new one.
The Backbone Views
The Views identified for this test application are depicted in the following image:
 |
In the above image the Grid View is the same although it was drown twice. So, this application has 4 Views |
There one view which is not depicted in the image and this is the View of a Product row in the GridView; so this means that a View can be a container for other views.
The Grid View
For the grid view the solution uses templates. Backbone can display views without using templates however are more maintainable, can be reused, etc.
Note the template inside of the script tag starting on line 17 above. Note the syntax required by UnderscoreJS, the template engine used by BackboneJS. Note that the template markup is not wrapped by a tr tag. The view object will "fix" this. In order to build the grid view we need two views: a Product row view and the collection view. The template use to build the grid view indicates that the grid view is rather passive and it only displays, like in the Knockout solution, the collection of products when the page is loaded and when the collection model changes.
Things to note from the above extended views: tagName,
Initilialize, and
render. Starting with RowView; tagName is the view wrapping tag. If we the view definition does not provide one then Backbone defaults the value of the DOM
element el (
$el is the cashed jQuery
el) to a "div" tag. This explains the need for a "tr" element for a RowView. The initialize function is the constructor of the Backbone View. Models (Model and Collection) also have a constructor. For RowView Line 18 is setting the template of the view to the template which is in the markup, and this is the UnderscodeJS at work.
The view is displayed when
render is called.
For the
TableView, pay attention to the constructor (initialize) and note that the view is registering itself to listen to events on its model such as "sync" and "change". The render method of TableView iterates through the collection of models, these are the products, and renders each one of them.
With what we have we could display already the GridView this way:
Line 20 created the ViewModel of the view which is injected in the constructor in line 21. Line 22 fetches the products from the server with a GET using the ProductsList URL and because the View is registered to the "sync" event on the collection, when the event is fired Backbone indicating that the model has been synchronized then the view renders.
This is a taste on how BackboneJS works.
Search and Details/Update View
The details/update view is very simple and it also uses a template. I will omit that part. The ViewModels of these views are a bit more interesting and are using a composite model,
DetailsViewModel, which contains two model properties: a Product and ProductsList. The ProductsList property is to be a reference to the same model created to construct the GridView. The intention is to call fetch() on the grid ViewModel after a product has been successfully updated in the details view.
On
DetailsView note that in the constructor/initialize function the View register to the "sync" event on productGetModel property of the model to render itself. Something new we see is that we can wire events of the view to methods handlers of interest. Note that when an input field is updated the Product model is updated along with the "id" of the model. This is critical so BackboneJS knows that the model is "dirty", isNew() returns false, and it needs to be updated with a PUT. Something new in this View appears inside of the "saveProduct" function, Line 40, where the product is saved with a PUT (because the model is dirty). Note that on the success of the save, Line 51, the reference to the ViewModel of the products table, gridVewModel, is fetched from the server and as a consequence the table refreshes.
The
SearchView sets the id of the Product and it fetches the product. The section of code shows that
SearchView and DetailsView are using the same
ViewModel. Maybe this is telling me that the
SearchView and
DetaillsView should be merged.
Creating a New Product
What is interesting and new in the code above is the "
adding to the collection model using add". Because add on the collection is changing the model a "sync" is fired and as a result the gridView refreshes like magic. Note that this add is local and it is added to the gridVew ViewModel on a save-success on the product. The product save success callback is passing the new product with its Id.
How is the entire thing started in the BackboneJS solution?
WEB API Controller Endpoint
ASP.NET Web API framework makes it very easy to create HTTP Services to create RESTful applications. The magic of this type of application is that RESTful services can be consumed by a wide range of clients and devices; it could be smartphone, tablet, a browser, a cashier at your favorite clothing store, etc.
The Web API end point deals with client HTTP requests using verbs such as GET, POST, PUT, DELETE then the Web API end point sends the response which can be JSON or XML. By default the response returned by the endpoint is in JSON format but the framework can return other formats depending on the format type requested by the client.
The end point controller is borrowed from Mike Wasson tutorials (
http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations). Read this tutorial to get you started. You can also examine the controller and other server side classes by downloading the project used for this research.
When examining the endpoint note that the controller inherits from ApiContoller and that the respective actions are returning a Product or an IEnumerable
. This is awsome! Here is where the framework starts to do lots of good things for us, such as serializing a Product or collection to the response when the respective action returns.Web API Routing in WebApiConfig
Something else you need to note is that routing is no longer in Global.asxa but in WebApiConfig class located in the App_Start directory. We could change all this but I rather keep the defaults new settings.
This project was created using Visual Studio 2012 Express for Web and it is a little more than 4 MB as a zip file. This file has been uploaded to my DropBox drive.

Part III Final Conclusion
This installment is already too long and I might have lost some readers along the way, so the discussion as to which framework should I use to build a client for my ASP.NET MVC Web API solution is going to be in a separate section.
References
- MSDN ASP.NET Web API: http://msdn.microsoft.com/en-us/library/hh833994(v=vs.108).aspx
- KnockoutJS Documentation: http://knockoutjs.com/
- Learn KnockoutJS: http://learn.knockoutjs.com/
- Avoiding Common Backbone.js Pitfalls: Interesting paper about common errors while working with this frame work. http://ozkatz.github.io/avoiding-common-backbonejs-pitfalls.html