Advertisements
//
archives

Kenstone

Kenstone has written 38 posts for Notebook Heavy

Amazon SimpleDB for Windows Phone Part 4 — TVMClient

Today I was made aware that in my series on Amazon SimpleDB for Windows Phone, I had mentioned that part 4 would contain some code samples and talk about encryption. I was confused for a second because I knew there was no part 4 and I thought the series was done. The series is not done. This is part 4 where we’ll show how to decrypt the credentials sent from the TVM. This one goes out to reader @jayborseth.

One thing to note is that since I started the series, an AWS SDK for Windows Phone has been released in beta form. The example I’m about to show does not use this SDK (and I don’t think the SDK has any work with the TVM).

As a refresher, the Token Vending Machine allows for an application to obtain temporary credentials for access to AWS services. In the anonymous way of obtaining credentials, there are 3 steps:

 

Step 1 – Register Device

Here is my code to register the device:

public void RegisterDevice(string deviceId, string tvmKey, Action callback)
{
    IDictionary parameters = new Dictionary();

    parameters["uid"] = deviceId;
    parameters["key"] = tvmKey;

    string queryString = GetParametersAsString(parameters);

    var uri = new Uri(string.Format("{0}/registerdevice?{1}", TvmUrl, queryString));

    var hwr = WebRequest.Create(uri) as HttpWebRequest;
    if (hwr != null)
    {
        hwr.Method = "GET";
    }

    TemporaryTokenPackage tokenPackage = new TemporaryTokenPackage() { DeviceId = deviceId, Request = hwr };

    AsyncCallback responseHandler = (async) =>
    {
        TemporaryTokenPackage temporaryTokenPackage = (TemporaryTokenPackage)async.AsyncState;
        HttpWebRequest request = temporaryTokenPackage.Request;

        HttpWebResponse response = null;
        try
        {
            response = (HttpWebResponse)request.EndGetResponse(async);
            callback(true, null);

        }
        catch (WebException we)
        {
            if (((HttpWebResponse)we.Response).StatusDescription == "Conflict")
            {
                callback(true, null);
            }
            else
            {
                callback(false, we);
            }

        }
    };

    hwr.BeginGetResponse(responseHandler, tokenPackage);
}

Couple of things. Here is my TemporaryTokenPackage which I used to pass pieces of data around the async handlers:

public class TemporaryTokenPackage
{
    public HttpWebRequest Request { get; set; }
    public string DeviceId { get; set; }
}

In the RegisterDevice method, we setup a typical request having a device ID and a tvm key. The tvm key is a Guid string without dashes. So,

tvmKey = Guid.NewGuid().ToString().Replace(“-“, “”);

You set the key and tell the TVM what key you are going to use using this call. The TVM will eventually use that key to encrypt the credentials.

The /registerdevice HTTP call doesn’t do much. If it returns, then you’ve successfully registered the device. If you get any error, you did not register the device and something is wrong. Try again.

Step 2 – Ask for Temporary Credentials

This is the part of the process where you ask the TVM for temporary credentials. If you already have a set of temporary credentials and they haven’t expired, you don’t need to ask for another set. Otherwise, get out your knee pads and beg. Here is how I did it:

public void GetTemporaryCredentials(string deviceId, string tvmKey, Action callback)
{
    string timeStamp = GetFormattedTimestampIso8601(0);
    string signature = Hmac2556Sign(timeStamp, tvmKey);

    IDictionary parameters = new Dictionary();
    parameters["uid"] = deviceId;
    parameters["timestamp"] = timeStamp;
    parameters["signature"] = signature;

    string queryString = GetParametersAsString(parameters);
    var uri = new Uri(string.Format("{0}/gettoken?{1}", TvmUrl, queryString));

    var hwr = WebRequest.Create(uri) as HttpWebRequest;
    AsyncCallback responseHandler = async =>
    {
        var request = (HttpWebRequest)async.AsyncState;

        HttpWebResponse response = null;
        try
        {
            response = (HttpWebResponse) request.EndGetResponse(async);

        }
        catch (WebException we)
        {
            callback(null, we);
        }

        if (IsGoodResponse(response))
        {
            Stream stream = response.GetResponseStream();
            var sr = new StreamReader(stream);

            var responseText = sr.ReadToEnd();
            sr.Close();

            var dataToDecrypt = Convert.FromBase64String(responseText);
            var plainText = Decrypt(dataToDecrypt, tvmKey);

            var temporaryCredentials = AwsTemporaryCredentialFactory.Create(plainText);

            callback(temporaryCredentials, null);

            return;

        }
        else
        {
            string responseText = "noresponse";

            if (response != null)
            {
                responseText = response.StatusCode.ToString();
            }

            callback(null, new WebException("Bad web response, StatusCode=" + responseText));

        }
    };

    hwr.BeginGetResponse(responseHandler, hwr);
}

Step 3 – Decrypt Your New Creds

This is where, as they say on MTV Cribs, the magic happens. Note that at the start of this method, we’re calculating the signature. This is what we talked about in Part 1. The bulk of this method is setting up the async HTTP call and dealing with the response. If we have a good HTTP response, we know that the TVM sent us something secret and we need to get it out. After encrypting the temporary credentials, the TVM will Base64 encode the result. So we need to decode that data using the .NET framework methods and we simply call Convert.FromBase64String which gives us a lovely byte array. Oh byte array.

This byte array is the raw encrypted credentials and we need to decrypt it. I pass into the Decrypt method the binary data to decrypt and the same tvm key that we used to register the device. Here’s the Decrypt method:

public string Decrypt(byte[] dataToDecrypt, string secretKey)
{
    var secretKeyToUse = DecodeHex(secretKey.ToCharArray());
    var cipher = CipherUtilities.GetCipher("AES/CBC/PKCS7Padding");

    cipher.Init(false, new KeyParameter(secretKeyToUse));

    int size =  cipher.GetOutputSize(dataToDecrypt.Length);
    var results = new byte[size];

    int olen = cipher.ProcessBytes(dataToDecrypt, 0, dataToDecrypt.Length, results, 0);
    cipher.DoFinal(results, olen);

    var result = Encoding.UTF8.GetString(results, 0, results.Length);

    return result;
}

///
<summary> /// Used to decode a plain text key into a key that can be used to decrypt. The data being passed in is assumed to be a
/// series of hex digits and this converts those 2-digit hex bytes into a single byte array.
/// </summary>
/// This is adapated from the org.apache.commons.codec.binary.Hex java source code at http://kickjava.com/src/org/apache/commons/codec/binary/Hex.java.htm
///
///An array of characters containing hex digits
/// A byte array containing the decoded hex data in binary format.
public static byte[] DecodeHex(char[] data)
{
    int len = data.Length;

    if ((len & 0x01) != 0)
    {
        throw new DataLengthException("Odd number of characters.");
    }

    var outresult = new byte[len >> 1];

    // two characters form the hex value.
    for (int i = 0, j = 0; j < len; i++)
    {
        var f = Convert.ToInt32(data[j++].ToString(), 16) << 4;
        f = f | Convert.ToInt32(data[j++].ToString(), 16);

        outresult[i] = (byte)(f & 0xFF);
    }

    return outresult;
}

Unfortunately, the key as we have it in memory is not what the TVM used to encrypt with. We need the DecodeHex method to rearrange the bits until we get a key that is the same format as was used to encrypt. Using this decoded key, we’re using the Bouncy Castle CipherUtilities to do the actual decryption. Assuming this works, we’ll end up with a UTF8 encoded string of decrypted data. But wait! There’s more!

Just having this string doesn’t give us everything. We need to split this packed string into a useable set of credentials. I used a factory to unpack this string into its constituent pieces of data (note that this is nearly identical to how the Andoid SDK sample did it):

public class AwsTemporaryCredentialFactory
{
    private const string AccessKeyName = "accessKey";
    private const string SecretKeyName = "secretKey";
    private const string SecurityTokenKeyName = "securityToken";
    private const string ExpirationDateKeyName = "expirationDate";

    ///
<summary> /// Used to create a set of temporary security credentials from the response provided by the
 /// Token Vending Machine.
 /// </summary>
    ///The response from the Token Vending Machine
    /// A set of temporary AWS credentials
    public static AwsTemporaryCredentials Create(string credentialString)
    {
        AwsTemporaryCredentials credentials = new AwsTemporaryCredentials
                                                  {
                                                      AccessKey = ExtractElement(credentialString, AccessKeyName),
                                                      SecretKey = ExtractElement(credentialString, SecretKeyName),
                                                      SecurityToken =
                                                          ExtractElement(credentialString, SecurityTokenKeyName),
                                                      ExpirationDate =
                                                          AwsTemporaryCredentials.GetExpirationTimeFromMilliseconds(
                                                              ExtractElement(credentialString,
                                                                             ExpirationDateKeyName))
                                                  };

        return credentials;

    }

    ///
<summary> /// Used to extract a piece of data from a json string.
 /// </summary>
    /// This is a C# port of the Java version written by Amazon.com
    ///The raw string to exctract the element from.
    ///the name of the piece of data to extract.
    /// The value of the exctracted element.
    private static String ExtractElement(String json, String element)
    {
        bool hasElement = (json.IndexOf(element) != -1);
        if (hasElement)
        {
            int elementIndex = json.IndexOf(element);
            int startIndex = json.IndexOf("\"", elementIndex);
            int endIndex = json.IndexOf("\"", startIndex + 1);

            return json.Substring(startIndex + 1, endIndex - (startIndex + 1));
        }

        return null;
    }
}

This retrieves a AwsTemporaryCredentials object which I’ve defined as:

public class AwsTemporaryCredentials
{
    public string AccessKey { get; set; }
    public string SecretKey { get; set; }
    public string SecurityToken { get; set; }
    public DateTime ExpirationDate { get; set; }

    ///
<summary> /// Handles converting milliseconds since 01-01-1970 into a useable DateTime.
 /// </summary>
    ///The number of milliseconds since 01-01-1970 as a string
    /// A DateTime that is 01-01-1970 plus the number of milliseconds
    public static DateTime GetExpirationTimeFromMilliseconds(string milliseconds)
    {
        long longMillseconds;
        Int64.TryParse(milliseconds, out longMillseconds);

        return GetExpirationTimeFromMilliseconds(longMillseconds);

    }

    ///
<summary> /// Handles converting milliseconds since 01-01-1970 into a useable DateTime.
 /// </summary>
    ///The number of milliseconds since 01-01-1970
    /// A DateTime that is 01-01-1970 plus the number of milliseconds
    public static DateTime GetExpirationTimeFromMilliseconds(long milliseconds)
    {
        var ticks = milliseconds*TimeSpan.TicksPerMillisecond;
        var correctedDate = new DateTime(1970, 1, 1).Add(new TimeSpan(ticks));
        return correctedDate;
    }

}

So there you go. 3 steps necessary to obtain temporary credentials from the Token Vending Machine (using the anonymous method). Once we have a set of temporary credentials, we can use those credentials just as we would with a “normal” set of credentials to utilize Amazon AWS services. Tired yet?

Questions? Comments? Confused? Drop a comment below if you need any help. Don’t forget to follow me on Twitter @kenstone.

Advertisements

Time to Pick an Ultrabook

I’m in the market for a new laptop. I want an Ultrabrook as I feel like my 2011 Macbook Pro is just too heavy. I’d like to park that machine and start using a super lightweight laptop as my daily driver. I want a good screen, solid battery, and I don’t want to pay a ton. My new startup is paying for this machine, so it can’t be too expensive.

So Many Choices

I looked at product specs from Engadget to determine how I want to proceed. I’ve picked a few options to limit the scope of my search as the Ultrabook options are vast. Some specs that are facts are listed (Screen, RAM, SSD, Price), but the Windows 7 battery life results are from Engadget (i.e., not manufacturer provided).

 

Macbook Air

This is an obvious choice and it’s hard to say no. I use a 2011 Macbook Pro right now that’s issued from my day job, so I have some experience with this product line. I like the keyboard a lot and the battery does last. The looks are appealing, but it comes at a price. Given that I want to run Windows 7 or Windows 8, if I run BootCamp, I’d also be on the hook for a license to run Windows, which is not included with the Mac.

Screen: 13.3″, 1440 x 900
RAM: 4 GB
SSD: 128 GB
Price: $1,299 (not including Windows 7 license, newegg.com)
Battery Life: 4:12

 

Asus Zenbook UX31

Sure does look like a Macbook Air, doesn’t it? Meh. I’m not so interested about that super tapered edge, but this machine does look sharp. It’s got some advantages that are clear. It’s $250 less than a Macbook Air and that’s significant. $50 wouldn’t have been so bad, but $250 on a budget is a lot. There’s been some talk about the keyboard and the trackpad. It sounds like the trackpad has been fixed, but that some people don’t like the keyboard. I tried this keyboard out at a retail store and I didn’t seem to have any trouble with it in my tests.

Also, look at the battery life. These are Engadget’s numbers running Windows 7. The Zenbook lasts 89 minutes longer. Again, that’s significant. 5 or 10 minutes wouldn’t have made a dent in my decision, but 89? Cra-a-a-zy.

Screen: 13.3″, 1600 x 900
RAM: 4 GB
SSD: 128 GB
Price: $1,049 (newegg.com)
Battery Life: 5:41

Lenovo Ideapad U300s

I like the looks of this machine and I’ve always known Lenovo machines to be solid, well built products. Their current offering also comes in a silver finish, but unlike the other two, it is the same thickness all the way across the body. This machine has the lowest resolution of the three and that’s a problem. I’m using this machine for Visual Studio, light Photoshop and Illustrator, and writing. Those are some beefy programs that like to take up room, so the widest resolution possible is necessary. The Lenovo comes in last place in this spec.

Screen: 13.3″, 1366 x 768
RAM: 4 GB
SSD:
Price: $1,049 (newegg.com)
Battery Life: 5:08

So What’s it Gonna Be?

From this perspective, it seems clear. The Asus Zenbook UX31 is the winner. The only thing holding me up right now is that the next revision of the machine is about to be released. So do I wait? Or just go for it? Hopefully this won’t be a decision I need to make, but time is running out until I need to make the purchase as my decision will be forced. If I was doing iOS development, perhaps the Air would have won, but with that extra $250, I can buy a printer that is so badly needed and some other startup necessities. What would your decision be?

Be sure to follow me on twitter @kenstone

Me and My Lumia 900 – a pseudo-review

Make no mistake, I am a Windows Phone fanboy. I’m not a phone reviewer, but wanted to give a few notes on my transition from a Samsung Focus to the Nokia Lumia 900.

Pros

Beauty

The aesthetic beauty of this phone is undeniable. I find myself taking it out in public more than usual just so people can get a glimpse of it (we are talking about phones, right?). The cyan colored body reflects light differently so it seems to color shift as I go from cloudy daylight to office flourescent to homey incandescent. The hand feel is, in a word, solid. It’s as if the phone is invoking Paul Hogan, “Heh. That’s not a phone. That’s a phone.

There are no parts that give way to pressure, like a battery compartment would. Nor does the screen give in when pushed. It pushes you. Having one completely smooth side unblemished by plasticky buttons feels anthropomorphically delightful.  If you haven’t read the book, Universal Principles of Design by William Lidwell, you should. In it, you’ll see so many things that Nokia got right about this phone listed in that book.

Soft Keys

One of my biggest complaints about the Samsung Focus was the soft keys found on all Windows Phones; they seemed so sensitive! Any fleeting touch would trigger them and, because of the bottom curve of the phone, you would constantly be in proximity to them while holding the phone. Anyone with a meaty thumb pad knows what I mean. My kid would be watching Netflix and in a flash be back at the home screen.  She’s really good at knowing how not to hold the phone, and she’s not even three.

The Lumia 900, in contrast, has the squared off bezel and additional room between the bottom of the phone and the buttons. This bezel not only gives something meaty to hold on to (particularly in landscape mode), but keeps your hands from hitting those buttons accidentally. Beyond that, the buttons seem less sensitive and thus less prone to tossing you over to cute animal land in Bing. That bezel is your home row and it gives your hands something to do without fear of blowing the whole thing up. It’s another design feature that helps users feel safe while using the device. You, my friendly tech geek cohort will hear your mom say, “Oh no! What did I do?” less when you loan her your phone.

Nokia Apps

The Nokia apps that I installed are App Highlights, Nokia Drive, Creative Studio, and Nokia Maps. I don’t live is a super populated area, so I’m unable to test some of the features of the Nokia Maps. My biggest plus is the Nokia Drive app which finally gives turn-by-turn driving. The Bing maps directions are great, but I really disliked having to keep tapping the screen to go to the next step. Creative Studio does the same thing with photo filters that a hundred other do, so maybe Nokia can sell that to someone for $1 billion some day.

Bigger Screen

Yup, it’s got a bigger screen than the Samsung Focus did. As a developer, I’m grateful that the resolution requirement hasn’t changed yet. I figure it will someday, but until then, I don’t need to change any of my artwork. I get to see everything a little bigger (and, if I’m being honest, I need to see things a little bigger lately).

Others

I have a Jabra CRUISER (which I highly recommend) that I use in my car to control my phone and talk hands-free. I’ve noticed that the Lumia connects to the bluetooth noticeably faster than my Focus did. And Visual Voicemail is here! I have my voicemail forward  to Google Voice where it is transcribed and sent back, so I’m not likely to use this feature much as I am not fond of voicemail. Voice Quality: every time I think the voice quality is a little weak, I realize my ear is not near the earpiece. So that’s straight up user error and the quality is superb when I’m in the zone.

Cons

It wasn’t until after I had pre-ordered the 900 that I realized it didn’t have the same curved glass screen of the Lumia 800 , which I was really looking forward to. Not only is it not curved glass, but the screen has a lip on it before stopping abruptly into the curve of the body. Instead of a dead flat surface, it has a rim. It probably works well enough to keep your beverage contained when you need an impromptu coaster (what else am I gonna use the gorilla glass for?) I’m guessing this was a cost consideration to get the phone down to the $99 street price, so I suppose its understandable. But I don’t have to like it.

This is not a con of the phone, but of the upgrade process in general. Moving from one phone to another phone is much more difficult than it should be. Things get lost. In my case, game data, SMS messages, and settings.

Conclusion

Yes, you should go out and get a Lumia 900. Now. Tomorrow. Especially now that it looks like they’re giving $100 credits to all purchasers before April 21. Get one for your mom and dad. And one for your spouse and probably a kid or two.

*drops the mike*

*picks the mike back up*

Don’t forget to subscribe to my blog and follow me on Twitter @kenstone. Let’s get that follower count above 100!

WordPress on Azure – Troubleshooting Setup

So you want to try installing WordPress on Windows Azure? You want to store your media files in Azure Storage? Good idea. It’s certainly more work than paying a 3rd party to host it for you, but let’s give it a go. First off, let’s set some ground rules. This is not an advanced troubleshooter. This is a guide that helps to clear up some of the confusing parts of the existing documentation for the absolute Azure newb.

Basic Setup

The go to guide for setting up WordPress on Azure is located at http://azurephp.interoperabilitybridges.com/articles/how-to-deploy-wordpress-using-the-windows-azure-sdk-for-php-wordpress-scaffold. There’s a few prerequisites so make sure you read the entire document first before getting to work. It’s like a food recipe with a few sub-recipes. Essentially here are the steps flattened into a single list:

  1. Install PHP
  2. Install Azure Dev Environment
  3. Update your PATH to point to the PHP folders
  4. Setup Windows Azure SDK for PHP
  5. Create an Azure Hosted Service
  6. Create an Azure Storage Account
  7. Setup your SQL Azure DB
  8. Download WordPress scaffold
  9. Run the scaffolder
  10. Create the project
  11. Package WordPress project
  12. Deploy to Azure
  13. Setup your WordPress installation.
  14. Configure Windows Azure Storage Plugin

Those are the main steps smashed together into one list. However, there can be a few gotchas in going through the documentation.

3. Update your PATH to point to the PHP folders:

I had to do more than what the documentation said. Here are the two locations I needed to add to my path:

C:\Program Files\Windows Azure SDK for PHP\bin
C:\Program Files (x86)\PHP\v5.3

9. Run the scaffolder

Here the directions can confuse. Under the “Parameters” section, “sync_account” and “sync_key” are listed as required for the scaffolder. As far as I can tell, putting the data in here does nothing. You still need to put them in during step 14. So, try leaving it out. I put mine in there, but I don’t think it did any good.

There is one more caveat. The directions say, “NOTE: Inside of this storage account you will need to create a public container called ‘wpsync’“. Unfortunately, the directions do not say HOW to do this. If you are brand new to this, this will keep you hung up for a bit.

Create a container the Azure Storage Account called wpsync

What you want to do is download Azure Storage Explorer and install that. Put in your storage account name and the primary access key. Using that tool, create a container called ‘wpsync’. That’s all you need to do in this tool.

That being said, the screenshot provided in the guide shows a different container name in use. So, who knows. Just create the wpsync container. It works.

Permissions

At this point, I got all the way through step 14. But then, as I tried to upload media to the blog, I got an error that caused a few days of trouble:

The uploaded file could not be moved to E:\sitesroot/wp-content/uploads/2012/04

You can follow the discussion on this problem on the codeplex discussions site: http://phpazure.codeplex.com/discussions/349701

Essentially this problem comes down to permissions on the virtual machine. The recommendation by the guide author is to enable remote desktop on your WebRole and check permissions. I’m not sure you need to do this, which is why I didn’t include it in the steps list above. If you want to, here is a good documention on how to enable remote desktop:

http://azurephp.interoperabilitybridges.com/articles/enable-remote-desktop

I did this and found a couple things. First, when I reuploaded the deployment package over the top of the existing one, my E drive would be replaced with an F drive. Yet WordPress was still looking to drop temporary files into an E drive. For me, the way around it was to make sure that I deleted and recreated the deployment when updating. This clearly has issues for production instances, so I’m not sure what to recommend in a production setting. If you’re running the recommended 2 instances, simply restarting each instance individually may solve it.

Through that discussion, the recommendation came to update your install-php-impl.cmd file (located at “WordPress\WebRole\bin\install-php-impl.cmd” wherever you ran the scaffolder). Change the line:

CALL icacls ..\wp-content /grant "NETWORK SERVICE":F /T

to

CALL icacls %RoleRoot% /grant "NETWORK SERVICE":F /T

After redeploying the package with this change, my uploads worked. BE WARNED: I have no idea how this change affects proper security on your instance. Overall, I’m unsure of how the permissions for WordPress need to be set, so don’t complain to me if you end up with a security gap.

Importing

If you’re moving a blog from wordpress.com to Azure, you probably want to import your content. I wanted to give this a go and it sort-of worked for me. Here are the steps:

  1. Download the importer plug-in
  2. Place it in the plug-ins folder on your machine
  3. Repackage and redeploy
  4. Activate the importer in the plug-in folder and give it a go.

My blog isn’t that big yet, so I was surprised when even I had problems importing. Essentially, I think the connection timed out before the import had completely succeeded. I ended up running the importer again and all the content seemed to get moved over the second time. YMMV.

Like this post? Be sure to comment or follow me on Twitter @kenstone

A .NET Developer’s Introduction to node.js – Part 1

Nearly my entire professional career has been devoted to developing on Windows platforms, specifically the .NET framework. But every developer needs to stand up and stretch once in a while and expand their body of knowledge to stay current and limber. Lately, one of the hotspots in the software scene has been node.js, a JavaScript based system for creating highly scalable internet applications. This is the story of a C# .NET developer learning node.js to do something useful.

A took a brief look last night and I’m going to try to use node.js to update my FitBit weight statistics. Node.js is just JavaScript and therefore is not that big of a strech (since I use JavaScript everyday in my job), and that’s a good thing. It gives me some room to grow without going too far out there.

Installing node.js

A Bing search for node.js brought me to nodejs.org where I clicked “Download” and then, since I’m on Windows 7, I clicked “Windows Installer”. The installation was as easy as it gets. There are no options. Just run the .msi and away it goes. At the end of the installation, it says to open a command prompt and type node to get started. I did this and this is what I got:

Great! Now what? Off to nodejs.org to read the documentation.

Someday We’ll All Say ‘Goodbye World’

I knocked out the standard HelloWorld example put forth by the documentation on their synopsis page:

var http =  require('http');

http.createServer(function (request, response) {  response.writeHead(200, {'Content-Type': 'text/plain'});  response.end('Hello World'); }).listen(8124);

console.log('Server running at http://127.0.0.1:8124');

After opening my web browser, I pointed it to http://127.0.0.1:8124, and sure enough, there on the screen are….those words.

Now what? More documentation? Pfft. No. Lets just start writing code and see what happens. It’s on to the npm registry to find some existing code to connect to FitBit. Npm is a package manager for node and it’s the easiest way to get different modules required by your software onto your machine. In .NET speak, think of it as NuGet and a way to get all those external references into your project. I searched for FitBit and find fitbit-js over on GitHub.

Over on the GitHub page, the README says to install it like this:

npm install fitbit-js

And here’s what I got:


Giant fail.

I wasn’t really surprised because on the npm page, fitbit-js was listed as good for node.js version >= 0.2 and < 0.5. Since I had just installed node, the version I have is 0.6.13. So, it looks like the package manager is keeping me from installing it that way. That’s probably good, but a little annoying.

Next, I tried just copying the fitbit_client.js file into the node/node_modules/npm/lib folder.

Then, using the example from the fitbit-js project, I try to see if it works as is.  Nope. Or rather, the test is looking for a module called ‘express’. But I don’t see that anywhere. So time to start looking around. A hint on stackoverflow lets me know that I need to install express via the npm. I did, and, voila, I now had express. (Note, the Appendix 1 of the node.js documentation  suggested a few useful packages that are often used). Let’s try the client again.

Now it can’t find connect. Okay. Npm to rescue again. That works, but I do get a warning — something about node 0.5 again.

Hmm. We’ll see if this works anyways.

At this point, I got a little stuck as the syntax for loading up the fitbit_client module was a little unfamiliar. Rather than digging too deep into it (that’s for another time), I instead decided to fork the repository from GitHub and see if that worked.

I edited the package.json to allow me to remove the < 0.5 version limitation and try ‘npm install’ in the fitbit-js folder. That works. I edit the test.js file in the example folder to include my secret key for my fitbit stuff. However, at this point, there is a slight bug in the fitbit-js example.

Keeping Up With the Nodes

The version of the test.js I forked had the following line of code in the setup:

app = express.createServer(connect.bodyParser(),                            
                           connect.cookieParser(),
                           connect.session({secret: 'session'}));

However, when we try to hit the page, this is the error we get:

Error: connect.cookieParser("secret") required for security when using sessions

I’m fairly confident that the original author didn’t post broken code, so I’m assuming that something must have changed in the post 0.5 version timeframe. I just changed the above line to:

app = express.createServer(connect.bodyParser(),
                           connect.cookieParser('session'),
                           connect.session());

I retried the url and was redirected to the FitBit oAuth page asking me to authorize my account to my app. Now we’re talkin! I agreed and got a PIN number to put back into the node.js app. What? It was supposed to redirect me back to the app I used and go from there!

It turns out, I was missing something in the FitBit application setup. I needed to tell FitBit that my application was a browser based app, and I gave it my callback url for it to call me back. Once that was done, I was given the display URL which I clicked on and was able to retrieve some JSON.

Fork and Pull

I had forked the fitbit-js repository, so I committed my changes to make it work with node.js 0.6.13 and pushed them back up to GitHub and submitted a pull request. This sample doesn’t really do much right now; it only retrieves my FitBit activity for a specific date. In the next entry, we’ll work on putting some data into FitBit.

Announcing – St. Patrick’s Photo Booth for Windows Phone

Just in time for St. Patrick’s Day on Saturday, I’d like to announce the release of St. Patrick’s Photo Booth on the Windows Phone Marketplace. Similar to the highly popular North Pole Photo Booth, this springtime version features St. Patrick’s Day and other Irish themed props. It uses the same face detection to automatically place a hat on your photo which you can easily swap out for others. Zoom, rotate, flip, lock, and delete props with simple finger gestures.

Speech Bubbles

New for this version is the addition of editable speech and thought bubbles. Just drop one onto your photo, double-click on it, then use the on-screen keyboard to write something clever.

Collaboration

This time around, I collaborated with Justin from Adkins Software Development on some new features such as integration into the photo hub and enabling a trial mode. Expect to see more in the future from this collaboration. Check out his app, WP7 Tracker, in the Marketplace.

So go check it out! It’s a fun app for a night of green beer and jig dancing!

Integration Test ASP.NET Web API with StructureMap

One of the best new features of ASP.NET Web API is the ability to self host. This means that inside of our integration test, we can create a web server in memory, work with the web server through a web client (in memory as well), and not have IIS running on the box or on some other server to test. It’s all done “in-house”.

I’m using Nunit for testing and StructureMap for Inversion of Control (IOC).  I’ve got two projects. The first is a MVC 4 Application with a Web API ApiController. The second project is a standard test project with Nunit. I’m on Visual Studio 11 on Windows 7. Let’s dig in. First, the controller I’m trying to integration test:

public class DrinkLogsController : ApiController
{
	private readonly IDrinkTrackerContext _context;

	public DrinkLogsController(IDrinkTrackerContext context)
	{
		_context = context;
	}

	[ValidationActionFilter]
	public HttpResponseMessage PostDrinkLog(DrinkLog value)
	{
		.
		.
		.
		// Code for the post handler goes here. It's not relevant to the discussion at hand.

	}

}

So what do we have? A typical ApiController for a entity called DrinkLogs. This controller is taking in an IDrinkTrackerContext which in reality is actually an instance of a DbContext. But since we’re using IoC and interfaces, the controller doesn’t really know much about the implementation of what we’ve passed in. No tight coupling here! There’s a POST handler that’s taking in a new DrinkLog and doing something with. We don’t care what it’s doing really. At least not for the purposes of this blog entry. Now let’s look at the test harness.

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using System.Web.Http.SelfHost;
using DrinkTracker.Core.Model;
using DrinkTracker.WebAPI;
using DrinkTracker.WebAPI.Controllers;
using DrinkTracker.WebAPI.Filters;
using NUnit.Framework;
using Newtonsoft.Json;

namespace DrinkTracker.Test

{
	[TestFixture]
	public class DrinkLogApiIntegrationTest
	{

		[Test]
		public void Post_Drink_Log_With_No_Drink_Failure()
		{
			var baseAddress = "http://localhost:8080/";

			var selfHostConfig = new HttpSelfHostConfiguration(baseAddress);

			selfHostConfig.Filters.Add(new ValidationActionFilter());
			selfHostConfig.Routes.MapHttpRoute(
			    name: "DefaultApi",
			    routeTemplate: "api/{controller}/{id}",
			    defaults: new { id = RouteParameter.Optional }
			);

			selfHostConfig.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;

			var container = IoC.Initialize();
			var resolver = new SmDependencyResolver(container);

			selfHostConfig.ServiceResolver.SetResolver(resolver.GetService, resolver.GetServices);

			var server = new HttpSelfHostServer(selfHostConfig);
			var client = new HttpClient();
			server.OpenAsync().Wait();

			client.BaseAddress = new Uri(baseAddress);

			var newLog = new DrinkLog { PersonId = 1, LogDate = DateTime.UtcNow };

			var postData = new StringContent(JsonConvert.SerializeObject(newLog), Encoding.UTF8, "application/json");

			var r = client.PostAsync("api/drinklogs", postData);

			Assert.That(r.Result.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));

		}

	}
}

Before I get too far explaining this test, it’s imperative to note that in order to use self hosting, you need to setup an http url namespace resolution. This is described in detail over on the Asp.Net website. Go read that, do what it says, and come back.

Too lazy to go check it out? Here’s what it says: you need to open up a developer command prompt and execute the following command (with elevated privledges):

netsh http add urlacl url=http://+:8080/ user=machine\username

Now let’s look at the test code. Right off the bat we’re setting up a location for the server to listen at. Then, using that address, we can create a HttpSelfHostConfiguration. This is where we’ll put all the secret sauce. You’ll need to do all your MVC setup work that would normally be done in the Global.asax or in the App_Start folders (where StructureMap for MVC is setup) of your MVC project. Easy enough to just go look at your MVC project and see what you’re setting up. In my case, I’m registering an ActionFilter and a Route. Set this here because the Global.asax is part of the ASP.NET runtime which we’re not really going through. I also set the IncludeErrorDetailPolicy to always to make sure I get back detailed information about any problems.

Now we move on to the IoC. Like I said, I’m using StructureMap because that’s what I’ve been using for MVC for a couple years. You could use your own flavor of IoC such as Ninject or Unity, but what’s important in this code snippet is that you get a reference to an IDependencyResolver.

Lets assume that I’ve got StructureMap setup as I want it inside the MVC project. In this case, calling IoC.Initialize() will setup StructureMap just as its setup in the MVC project. The SmDependencyResolver gives an IDependencyResolver we so longingly need which we then use to set the ServiceResolver on the HttpSelfHostConfiguration.

The hard part is done now. It’s all smooth sailing from here on out. We setup the HttpSelfHostServer passing it the configuration we so lovingly crafted earlier. Use server.OpenAsync().Wait() to put the server into a zen state of acceptance of all connections on the address we specified earlier.

Then it’s just standard HttpClient stuff. In this case, passing in a JSON representation of the new DrinkLog. Since this test is specifically testing to make sure that if the caller forgets a piece of data on a POST, we return a BadRequest HttpStatusCode. Once that’s tested, we’re golden. Or, more appropriately, all green.

If your Result.StatusCode is 500, Internal Server Error, check the error detail. If you see an error like “No parameterless constructor defined for this object.”, then your IoC isn’t setup correctly. Set a breakpoint in your constructor to confirm to yourself that you’re not setup correctly. This is ususally caused by not telling the IoC system about your bindings. Fix that, try again. If it still doesn’t work, ask a question.

Happy Web APIing.

United Pixelworkers T-Shirts for February-March 2012

Man, these United Pixelworkers folks are killing it lately. Last month they released a new version of their web site and it. is. awesome. Unfortunately for me, I totally missed the sale last month. But not this month. This month they had 15 different shirts up for sale. I think I’m still partial to the idea of guest designers and so I’m drawn to that over the the different region ones the have up. I picked up the “alignment” one by Evan Stremke.

You’ve got until Monday to get in on this month, so move yourself over to unitedpixelworkers.com to get your own t-shirt ordered.

PLUS: Don’t forget to check out my t-shirt at tshirtheavy.com.  

Announcing – Windows 8 T-Shirt

Just in time for the Consumer Preview release of Windows 8 on February 29, the Windows 8 inspired “Touch Me” T-Shirt is now available for purchase in my online store at tshirtheavy.com. I designed this shirt myself and it is clearly inspired by Windows 8 (note, that this shirt is not endorsed by Microsoft nor is it official in any way — but it is super cool).

It was printed up by the fine folks at acmeprints.com and they’re handling fulfillment. It’s a fine quality garment made of 90% cotton and 10% polyester. In heather grey, the bright green shows off the metro style tiles on the new Windows 8.

Go get yourself a shirt. All proceeds to go a good cause. My kid’s college fund.

Analysis: One Month of Downloads on Windows Phone Marketplace

North Pole Photo Booth Download Graph

What you see is a graph of the downloads of the North Pole Photo Booth for its first month on the Windows Phone Marketplace (actual download numbers have been removed as they are not relevant to the discussion). Since this app was intended as a Christmas holiday themed app, this graph is perfect as it shows the effective lifespan of an app from launch to the main event — Christmas.

We Three Peaks

There are three primary peaks that jump out at us. The first is the launch peak, a very common and expected shape. I also purchased advertising on the windowsphonegeek.com App Wall for one month, but am unable to assess its impact given that the campaign started on the same day as launch. It got caught up in the launch peak. This was a good day for the app and got it off to a good start.
 
 The second peak is the downloads after the app was featured on wmpoweruser.com. This was the first time I’ve had an app written up there and, while the bump was expected, the magnitude of the bump was not. The peak is higher than the launch peak! Very impressed. Note to self, make sure all future apps are showcased on wmpoweruser.com. I also submitted stories for review on other sites (wpcentral.com, wp7applist.com) but it did not get picked up on any other site, so there are no more peaks to look at until the main event. I can say that the ad revenue generated for the app was highest on this day, so the people attracted by the site were high quality to advertisers compared to the other peaks.
 
 The 3rd and final peak is Christmas day. Ah Christmas. This peak is bigger than the other two and I assume are new phone users. That peak begs so many questions. This app was a holiday themed app and so was applicable to the day. Do all apps exhibit a similar peak? It was also a free app, so what does a paid app look like on Christmas? I hope people had fun using the app with their friends and family and that it put a smile on some faces.
 
 

O Holy Marketplace

One other thing to notice is the relatively flat download count in the weeks leading up to Christmas. This is only interesting because of what’s missing. No spikes. I say this because the Windows Phone Marketplace was featuring a couple Christmas themed apps every day for weeks. But North Pole Photo Booth never got chosen. A competitor got chosen twice. In fact many of the apps that were featured did so twice. Also, despite what the guidelines say, most of the featured Christmas apps were paid apps. I’m not sure anyone can say for sure why something gets chosen or doesn’t, but I assume that there would be some decent spikes had it been picked up.
 

Silent Night

The downloads for this app fell off sharply after Christmas day. Ad revenue went way down. This is not unexpected as it’s a Christmas app and Christmas is over. We’ll take a look next year to see how it ramps up again. Overall, I’m pleased with the app and it beat my expectations and so I’ll call it a success. It made it into the top 2% of all apps and was positioned nicely among photo apps. However, I’m not quitting my day job anytime soon.

Questions or comments? Let me know. Don’t forget to follow me on twitter (@kenstone) for more bits and pieces of my awesomeness. Also, follow my new blog, Trash My Stuff, where I’ll cronicle the sale and disposal of many of my unnecessary possessions.

Advertisements

I'm Ken Stone. I'm an indie developer with a focus on .NET and Windows Phone development. I have a day job, but everything I say is mine alone.

TechEd 2012July 11th, 2012
Let the learning begin.