Hopefully by now you have had a chance to read parts one and two of this series. In part three we are going to look at how to get the offerings using one of the most popular client side scripting technologies, knockoutjs. This is fully supported by microsoft’s NuGet so it is very easy to add to your project.

Thanks to the jquery revolution, a plethora of client side technologies and techniques have come down the pipe in recent years. One of the great benefits of this is allowing for a much more robust and interactive experience with your app as everything lives in the browser. Visual changes, or data binding in knockout’s case, don’t require a server side refresh so the experience is seamless. With the power of client devices ever increasing, yes even your phone is pretty powerful these days, doing this processing on the client reduces server burdens as well. There are some arguments against this, but the purpose of this blog is to not get into the server side / client side battle. We want to make our SDK accessible to as many technologies and developers as we can, and we want to make it as easy as possible to do so.

With that, let’s dig into the details of using knockout to get the offerings using the App Orchestration API. I started off with the same MVC windows auth type solution that I used in part two. This was because we still need a back end to talk to make ajax calls against.

First off, we need to add the knockout the _layout.cshtml. I am not sure why when I added knockout via NuGet that this wasn’t done automatically. Maybe it is not supported or I just missed that part. Anyway, it is easy to add it. I just put some script tags in the head section.

    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - My ASP.NET MVC Application with Knockout</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
        <script src="@Url.Content("~/Scripts/jquery-2.0.0.js")"></script>
        <script src="@Url.Content("~/Scripts/knockout-2.2.1.debug.js")"></script>
        <script src="@Url.Content("~/Scripts/home-viewModel.js")"></script>
    </head>

Once knockout is in, I need to setup my view model. (See here for more details on this) You will see I added it above already. Now you might want to have each model only loaded on your specific page. The easiest thing to do for demo purposes was to just put it in the layout, but if you have a more complex application you might want to do something different.

The view model has several parts. The definition of the model:

    // This is the view model for the home page
    var viewModel,
        getOfferings;

    viewModel =  {
        Title : ko.observable("Home Page"),
        Message : ko.observable("Using Knockout to do client side scripting."),
        Offerings : ko.observableArray([{ Name: 'Offering1', IconUrl: 'IconUrl1' }, { Name: 'Offering2', IconUrl: 'IconUrl2' }])
    };

And a function to get the offerings:
getOfferings = function () {

    $.ajax({
        type: "POST",
        url: "Home/GetOfferings",
        traditional: true,
        success: function (result) {
            if (result.HasError === true) {
                alert(result.Error);
            } else {
                viewModel.Offerings(result.OfferingModels);
            }
        },
        error: function (jqXhr, textStatus, errorThrown) {
            alert(errorThrown);
        }
    });

    return true;
};

All this is wrapped up in a document function to start it all up, with a bindings call to start it up. You might want to add subscribes and computeds for more complicated models. See the knockout tutorials for more on this.

Now to use knockout in your web page, you just add data-binding calls to your tags. I setup a simple binding for the title and message that you saw were in the model. It’s as easy as this:

<hgroup class="title">
    <h1 data-bind="text: Title"></h1>
    <h2 data-bind="text: Message"></h2>
</hgroup>

In part two I used a razor foreach to map each offering to a row in the table. In knockout world this done by either a direct foreach binding, or a template binding using a foreach. In this case I used a templeted foreach:
<table width="100%" id="tblOfferings">
    <thead>
        <th style="text-align: left; width: 5%">Offering</th>
        <th style="text-align: left; width: 95%"></th>
    </thead>
    <tbody data-bind="template: { name: 'offering-template', foreach: Offerings }">
    </tbody>
</table>

<script type="text/html" id="offering-template">
    <tr class="" id="trd">
        <td>
            <img data-bind="attr: { src: IconUrl }" /> 
        </td>
        <td>
            <label style="vertical-align:middle; text-align: left;" data-bind="text: Name"></label>
        </td>        
    </tr>
</script>

In the end it will look like all the other pages in the previous parts:

On the backend, everything is the same as the previous example, but the index method is basically empty and the logic to get the offering is moved to an ajax call that returns the offerings in the json format.

        [HttpPost]
        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public async Task<JsonResult> GetOfferings()
        {
            try
            {
                var offeringsTask = ApiContext.Offerings.GetAsync();
                var offerings = (await offeringsTask).ToList();

                return Json(new
                {
                    OfferingModels = (from offering in offerings
                                      select new 
                                      {
                                          Id = offering.Id,
                                          Name = offering.Name,
                                          IconUrl = Url.LargeIconUrl(offering.Icon.Id),
                                      }).OrderBy(ad => ad.Name).ToList(),
                }, JsonRequestBehavior.AllowGet);
            }
            catch (Exception e)
            {
                return Json(e.Message, JsonRequestBehavior.AllowGet);
            }
        }

And that is it. You see that a lot this is the same logic as was used in part two. That makes switching to the client side easier and the learning curve less steep as the hard part is figuring out what you want to do, not how to do it.

Stay tuned for the forth part in the series, coming in a few weeks, using a pure client side approach via Angular.