Thursday, January 31, 2013

Knockout Web API SPA

This is just to explore the new technologies in the Microsoft .Net and Javascript communities. The Web API allows for a lightweight web services tier, while Knockout provides productivity in the browser side. Most of this technique I found in tutorials on www.asp.net and other like sites. I am not feigning originality here.
I am describing the building of a SPA - Single Page Application.
I have built a quick application which performs CRUD operations on the single table using Knockout, Web API, and NHibernate data layer.
Here is the browse data view of the application. There are links to edit, delete and add new items. Also it does paging, because the table is large.

Here is the Edit data view :


How is it built?

A standard MVC project is created in C#, selecting the WEB API project template along the way. A Project Reference is added to the data layer project.


There are 3 main components needed to get a UI running : a Controller class, a Javascript file, and an HTML View file.


The HTML View


References to the various script libraries are added

It is easiest is to build the View and then animate it with code. The View I have above contains edit and list sections which are hidden and shown alternatively, using the JQuery “Hide” and “Show” commands. Just to explain the syntax, here is the relevant part of the Edit section :
And the pertinent code for the List section :
The edit and delete links are accomplished with Knockout Bindings as shown here:

The data paging functionality is also done with Knockout bindings :
The Scripting
Knockout implements the ViewModel part of the MVVM architecture which means we have to code this in the javascript for the html page. Here is my example ViewModel which works in the single page application :
This ViewModel contains objects for the single item and the list of those items.
The Controller code
This is a class which implements the API methods to return data for Knockout to display. The WEB API uses convention to determine which method to execute. Objects are posted intact to the methods, and parameters passed with names are converted to querystring. If passed without name to a GET function, then the value just becomes part of the path "API/THING/1/" for example. Posts and Deletes are translated into methods with those names.

Wednesday, January 16, 2013

Windows 8 RSS Reader Continued

All I added to the template provided by Visual Studio is here : In the HTML document, I did very little except add a ListView, and a WinJS Binding Template for items in the list. I added an Article element for the Blog entry detail pane. The code was added to the existing JS file provided as below :
    // To get the data from the website
                getFeeds(blogPosts, null); 

    // To expose the data to the page.
                var publicMembers =
                    { blogItems: blogPosts };

                WinJS.Namespace.define("DataRSS", publicMembers);

   // To finish setting up the page for view
    args.setPromise(
                WinJS.UI.processAll()
                .done(function () {

   // Add event handlers for the controls
                    var button1 = document.getElementById("bttnMore");
                    button1.addEventListener("click", buttonMoreClick, false);


                   var myList = document.getElementById("myRSSItems");
                   myList.addEventListener("selectionchanged", _selectionChanged);
                }));

Then there is specific acquire and data parsing code for the blogs. First get the data, saving the most recent post date into a variable:
function getFeeds(blogs, after) {

    // To Get more items need to login.
    // // http://www.google.ca/reader/atom/feed/http://forums.corvetteforum.com/external.php?type=RSS2&n=50

    var urlString =
        "http://forums.corvetteforum.com/external.php?type=RSS2";

    var today = new Date();

    today.setDate(today.getDate() - 1);

    var dataPromise = acquireSyndication(urlString, today.toLocaleString());
    
    dataPromise.done(
        function completed(articlesResponse) {

            var lastDate = null;

            lastDate = getPostsAfter(articlesResponse, blogs, after);

            var lastToday = new Date(lastDate);

            // populate a SPAN on the page with the recent date.
            spLastPub.innerText = lastToday.toLocaleString();
        });

}

The RSS feed won't give but the most recent 15 items unless you login to Google
function getPostsAfter(xmlDoc, blogs, afterDate) {

    var articleSyndication = xmlDoc.responseXML;

    if (afterDate != null) {
        var aftDate = new Date(afterDate);
    }

    var posts = articleSyndication.querySelectorAll("item");

    var lastPublished = null;

    for (var postIndex = 0; postIndex < posts.length; postIndex++) {
        // debugger;

        var postTitle = posts[postIndex].querySelector("title").textContent;
        var postLink = posts[postIndex].querySelector("link").textContent;
        var description = posts[postIndex].querySelector("description").textContent;
        var published = posts[postIndex].querySelector("pubDate").textContent;
        var contentEncoded = posts[postIndex].querySelector("encoded").textContent;

        if (postIndex == 0) {
            lastPublished = published;
        }

        var compareDate = new Date(published);

        if (afterDate == null ||
            compareDate > aftDate) {
            blogs.push({
                title: postTitle,
                subtitle: postLink,
                desc: description,
                pubDate: published,
                content: contentEncoded
            });
        }

    }

    return lastPublished;
}
The function for acquiring the feed asynchronously was generously provided in the tutorial, so I used it verbatim :
function acquireSyndication(url, modified) {

    return WinJS.xhr(
        {
            url: url,
            headers: { "If-Modified-Since": modified }
        });

}
The only way to get full coverage of the blog without the login overhead, was to provide a button which would update the list with any new entries since the original opening of the page :
 function buttonMoreClick(arg) {

        getFeeds(blogPosts, spLastPub.innerText);
    }
The Microsoft article is here - http://msdn.microsoft.com/en-us/library/windows/apps/jj663506.aspx

Tuesday, January 15, 2013

My First Windows 8 Store application

I am learning to write code in Windows 8 and wanted an application for reading CorvetteForum.com. While there are other products for reading RSS feeds, I wanted a full application for just this one feed. Here are some screen shots of the user interface :
This app is from the Visual Studio 2012 project template Javascript - Windows Store - Blank Application.
There is a lengthy tutorial about how to write a full blog reader, however I wanted to learn the parts without just pasting a huge code volume and not having time to read it all. I wanted to do alot of my own coding.