Tag Archives: winjs

Adding asserts to WinJS application

Published July 8, 2013 2:49 pm

I have been coding without asserts Windows store application in javascript (WinJS based). Amidst making progress on frameworks for the next application, looking into this was at the back burner. One day, it pinched enough to look around for the solution.

I had been using chai.js for the assertions in the nodejs server code. It is expected to work in browser. hence, gave it a try to use it in WinJS application. It works; the library has right set of apis for the assertions in javascript.

What needs to be done:

  1. download chai.js for browser from here.
  2. Add the file to the vs project
  3. Add script entry into default.html
  4. Add a global variable – assert – in default.js
  5. Use the assert apis in code.

default.html:

<!-- WinJS references -->     
<link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />     
<script src="//Microsoft.WinJS.1.0/js/base.js"></script>     
<script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

<!-- external js libs -->     
<script src="/js/chai.js"></script>

<script src="/js/default.js"></script>

default.js:

 
(function()
{
    ...
    assert = chai.assert;
})();
var assert;

Examples:

 
    assert.isObject(this.options);

    assert.isString(this.options.parameter1);

    assert.deepEqual({ tea: 'tea' }, { tea: 'tea' });
    //  for more examples - refer http://chaijs.com/api/assert/

Azure Table Rest API errors with WinJS application

Published June 7, 2013 11:10 am

If you are using azure SDK to code to its REST API – there are lot of API nuance that is taken care by the SDK. For example – if you are coding nodejs server, or windows store application using c# that uses Azure, nodejs and .net sdk is available. For WinJS, there isn’t azure sdk.

But it shouldn’t be big deal to code directly to the REST API if the basic http lib is available. `WinJS.xhr()` is available to mimics closely what XmlHttpRequest does in the browser. Well, this holds true if the API returns meaningful errors with sufficient contextual details for the error. If that isn’t true, lot of developer(your) time is wasted debugging the error cases. Keep binging to see if other community developer hit similar issue, or parse the http packets sent — for a successful rest api call made by other tool or application – using fiddler or network monitor.

I recently saw two such errors when invoking azure table rest api to query using javascript in WinJS application.

  1. AuthenticationFailed
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <code>AuthenticationFailed</code>
      <message xml:lang="en-US">Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.</message>
    </error>
  2. InvalidHeaderValue
     
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <code>InvalidHeaderValue</code>
      <message xml:lang="en-US">The value for one of the HTTP headers is not in the correct format.</message>
    </error>

AuthenticationFailed was hit when the x-ms-date header was formatted incorrectly. Expected value – Thu, 06 Jun 2013 08:09:50 GMT . Value computed in the code – Thu, 6 Jun 2013 08:20:34 GMT. Note: the difference in ‘0’ prefix for the date. Because of this, the computed stringToSign for the authorization header was incorrect. For details, you can refer here.

InvalidHeaderValue was hit because MaxDataServiceVersion: '2.0;NetFx' header value was missing.

In the first case, if the REST API returned the expected and found ‘stringToSign’ parameter value in the returned error – it would help developer save order of .5 to 1day worth of debugging time. In the second case, if the returned error mentioned the missing header in the error details, again it will save 1-2 hours of debugging time.

Well, you might hit here and cause & solution of the error code for the same api might be different than this – do drop a comment with the cause & solution. If you are a developer coding REST API, do send error codes with sufficient details to save hours of developer time. Thanks for reading so far.

Handling click event on elements within WinJS Listview ItemTemplate

Published May 29, 2013 5:26 pm

Typically – there is need to handle ‘itemInvoked’ event in a ListView. but there are some cases when you are looking for handling click event on a element defined in list view item template. Since item template is rendered multiple times for each item in the list view, how do we do this?

Let’s take an example where item template has two anchors. On click on each anchor, you want to tranverse to another page but parameter passed to the page will differ based on which anchor was clicked.

<div id="itemTemplate" data-win-control="WinJS.Binding.Template">
    <div>
        <h3 class="win-type-ellipsis date cell" data-win-bind="innerText: date"></h3>
        <h3 class="win-type-ellipsis hour cell" data-win-bind="innerText: hour"></h3>
        <a class="win-type-ellipsis counter1 cell" data-win-bind="innerText: counter1" ></a>
        <a class="win-type-ellipsis counter2 cell" data-win-bind="innerText: counter2" ></a>
    </div>
</div>

To do this, we need to register a wrapper itemTemplate function in code like this. That will enable us to register event handlers for counter1 and counter2 cells.

    listView.winControl.itemTemplate = this._itemTemplate.bind(this);
    _itemTemplate: function itemTemplate(itemPromise)
    {
        var self = this;
        var container = document.createElement('div');
        return itemPromise.then(function onitem(item)
        {
            return itemTemplate.winControl.render(item.data, container);
        }).then(function onrendercompete(c)
        {
            // register event listener
            var counter1Element = c.querySelector('.counter1);
            var counter2Element = c.querySelector('.counter2);
            counter1Element.onclick = self._oncounter1click.bind(self);
            counter2Element.onclick = self._oncounter2click.bind(self);
            return container;
        });
    },

In the event handler, we can use ListView.indexOfElement() method to get the item corresponding to the element clicked.

    _oncounter1click: function oncounter1click(event)
    {
        this._navigateToRequestsPage(event.currentTarget, 'counter1');
    },
    _oncounter2click: function oncounter2click(event)
    {
        this._navigateToRequestsPage(event.currentTarget, 'counter2');
    },
    _navigateToRequestsPage: function navigateToRequestsPage(itemElement, counterFlag)
    {
        var index = hourlyStatListView.winControl.indexOfElement(itemElement);
        var item = this.viewModel.items.getAt(index);
        var hour = item.date + 'T' + item.hour;
        WinJS.Navigation.navigate('/pages/itemDetails/itemDetails.html', { hour: hour, counterFlag: counterFlag});
    }

In summary, we saw how we can use wrapper item template function to register event handlers with elements declared within item template. We also saw the use and relevance of ListView.indexOfElement() function in the scenario.

Integrating your windows store app with https nodejs web service

Published May 16, 2013 12:56 pm

During development, we typically start implementing the web service as a http endpoint. At a later stage in development we need to make it a https endpoint. This is when we need to deal with SSL certificates.

Hosting the nodejs web api server at custom https endpoint like https://myapi.mywebsite.com, buying the SSL certificate for the api subdomain from a certificate authority, getting the required .pfx file from the files given by CA for the https nodejs server are interesting topics by themselves. Today, we are talking about generated a self-signed certificate for the localhost. This enables us to run the https nodejs web server on local machine and test the windows store application to consume the apis. This suffices for the development of the app & service while other things are required for taking the app to production.

I found this helpful tool through bing to generate self signed certificate for locahost, has the nice GUI and gives a pfx file as output. Saves going through the VS command line makecert details unless you already know about it.

https nodejs server is up and running given the localhost pfx file and its password.

var fs = require('fs'),
    https = require('https');

var options = {
    pfx: 'localhost.pfx',
    passphrase: 'your password',
};

https.createServer(options, function (req, res)
{
   ...
}).listen(xyz);

but when my WinJS client WinJS.xhr() calls fails to https://localhost:xyz/
This is because the certificate authority is not trusted by the localmachine – the dev box. The localhost certificate needs to be added to ‘trusted root cas’ using certificate mgr mmc. To do this:

  1. Launch mmc. Add ‘certificates’  MMC snapin. select local computer.
  2. Right click ‘Trust Root Certificate Authorities’-. Follow All Tasks->Import to import the localhost.pfx certificate here.
  3. Follow the instructions in the import wizard

Once done, WinJS client can successfully connect to the https://localhost:xyz nodejs endpoint.

Getting oauth authentication code for windows live account in windows store application

Published May 13, 2013 1:26 pm


We need to add support to login using windows live into the windows store application. The backend web service authenticates the user identity using one of the well known providers – google, facebook and now windows live.

WebAuthenticationBroker comes handy to get authentication code in the windows store app. authentication code is passed to the backend web service. sample code below:

Windows.Security.Authentication.Web.WebAuthenticationBroker.authenticateAsync(
    Windows.Security.Authentication.Web.WebAuthenticationOptions.none,
    // redirect_uri parameter is encodeUriCcomponent('https://login.live.com/oauth20_desktop.srf')
    //  scope can be wl.basic others. refer other scope values here
    // client id is created by adding your application here
    new Windows.Foundation.Uri('https://login.live.com/oauth20_authorize.srf?client_id=&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf&response_type=code&scope=wl.emails'),
    new Windows.Foundation.Uri('https://login.live.com/oauth20_desktop.srf')).then(
       function (result)
       {
           if (result.responseStatus === Windows.Security.Authentication.Web.WebAuthenticationStatus.success)
           {
               var uri = new Windows.Foundation.Uri(result.responseData);
               var code = uri.queryParsed.getFirstValueByName('code');
           }
       }).then(null, function onerror(innerError)
       {
           // handle error
       });

Important notes:

  1. http://login.live.com/oauth20_token.srf api to get token from authentication code fails with 500 internal server error if HTTP POST is used as per documentation. HTTP GET has to be used instead. documentation is out of date. Refer this thread at msdn.

Creating a Bindable object in javascript for Windows store application

Published April 8, 2013 6:57 pm

When I was writing windows store application in c#, it provided

class BindableBase

I was looking for similar way to create bindable object in javascript using WinJS library. WinJS libray does have WinJS.Binding.as() method that can be used to make an object observable through a proxy. but I was looking for a way to make the object itself Observable.

var MyViewModel = WinJS.Class.define(
    function MyViewModel_ctor()
    {
        this._initObservable();
        this.bind('property1', this._onproperty1change.bind(this));
    },
    {
        _onproperty1change: function onproperty1change(newValue)
        {
            // can be used to update properties that are dependent on property1
            // property3 and property4 for example - can be updated here. UI will be 
            // notified if it is binding to these properties
        },
    });

    WinJS.Class.mix(MyViewModel,
        WinJS.Binding.mixin,
        WinJS.Binding.expandProperties({ property1: '', property2: ''}));

With little help from the quickstart and reading the WinJS base.js class helped arrive to this code and understand how it works.

var expandProperties = function (shape) {
    var props = {};
    function addToProps(k) {
        props[k] = {
            get: function () { return this.getProperty(k); },
            set: function (value) { this.setProperty(k, value); },
            enumerable: true,
            configurable: true // enables delete
        };
    }
    while (shape && shape !== Object.prototype) {
        Object.keys(shape).forEach(addToProps);
        shape = Object.getPrototypeOf(shape);
    }
    return props;
};
  1. WinJS.Binding.expandProperties documentation won’t help to understand what it brings. The snippet from the base.js above clarifies that it adds properties for each key specified in the parameter, and the value specified is not used for anything.
  2. WinJS.Binding.mixin object brings the getProperty/setProperty/bind/notify and bunch of other methods for the object
  3. _initObservable() need to be invoked from the constructor to initialize _backingData field. The _backingData object is used to store the property values.
  4. this.bind helps you get notified for a property change, and it can help in scenario like updating dependent properties.
  5. It saves writing boiler plate code for each property in the view model object

Did you need something like this? Have you solved in different way than this?

Uploading image to azure blob from windows store app

Published March 22, 2013 11:11 am


msdn gives quick start to upload image file using background transfer.  but I was looking for way to upload image file using WinJS.xhr() in the javascript app.

Windows.Storage.Pickers.FileOpenPicker.pickSingleFileAsync() returns StorageFille object  whereas WinJS.xhr.send() expects a File DOM object. Essentially, what we need is way to get a w3c File DOM object out of StorageFile object. I found finally the method MsApp.createFileFromStorageFile() to do that.

// url needs to be SAS (shared access signature) url for the blob when the container is protected
// otherwise - it requires putting authorization code in the request. I have talked about in previous post.
// but if the javascript is in the client side - you wont like to put your client secret in the app.
// hence, you need to have some mechanism (your service) to return the sas url for your azure container/blob. 

    var url = '';
    var date = new Date().toGMTString().replace('UTC', 'GMT');
    var data = MSApp.createFileFromStorageFile(storageFile);
    var xhrOptions = {
        type: 'PUT',
        url: blobSasUrl,
        headers: {
            'Content-Type': 'image/jpeg',
            'Content-Length': data.size,
            'x-ms-date': date,
            'x-ms-version': '2009-09-19',
            'x-ms-blob-type': 'BlockBlob',
        },
        data: data,
    };
    WinJS.xhr(options).then(null, function onerror(error)
    {
        // handle error
    });

I see that many of us need to upload images to azure blob containers. If you are one of us, it will help to know little bit more to help you better.