HAP+ and Uploading to SkyDrive

I recently decided to add SkyDrive upload support to HAP+, and, unlike Google Docs, requires a bit more planning.

With Google Docs, you can upload a file by just asking the user for a username and password (of course you have to do the authentication steps) but SkyDrive requires that the user has used the Live ID services to get authenticated.

So how did I do that?

Quite simply really

Step 1: Register for a Live App ID

Visit http://manage.dev.live.com/ and get an appid

Step 2: Add a reference to the Windows Live js Script

<script src="//js.live.net/v5.0/wl.js"></script>

There is a nice little trick here, the // means use what ever protocol your currently using, so if your https it'll get the https resource. (Useful for HAP+)

Step 3: The client side script to authenticate

Now, after getting my head around the way Live Connect works, it's actually quite nice to work with.  So here's my code on the client side;

WL.init({ client_id: '<%=config.MySchoolComputerBrowser.LiveAppId%>',
          redirect_uri: hap.common.resolveUrl("~/myfiles/oauth.aspx"),
          scope: 'wl.skydrive_update',
          response_type: 'token' });
WL.login({scope: 'wl.skydrive_update' }, function () { console.log("Windows Live Logged In");
   $("#loadingbox").dialog({ autoOpen: true, modal: true });
     type: 'POST',
     url: hap.common.resolveUrl('~/api/MyFiles/SendTo/SkyDrive/') + SelectedItems()[0].Data.Path.replace(/\\/gi, "/").replace(/\.\.\/Download\//gi, "") + '?' + window.JSON.stringify(new Date()),
     dataType: 'json',
     data: '{ "accessToken" : "' + WL.getSession().access_token + '" }',
     contentType: 'application/json',
     success: function (data) { $("#loadingbox").dialog("close"); },
     error: hap.common.jsonError

What does that do, may you ask.  It initializes the Live Connect library with the client_id that you got in step 1, hands it a blank page url that just references the javascript library (yes a blank html page with just that script from step 2 in it).

Once the client is initialized, it asks it to login, asking for skydrive read & write access.  When the user accepts it, I then post the acessToken, and the file path to my WCF JSON api to do the upload (as you can't upload using javascript)

So for the user, they get:

A prompt for their Live ID

Skydrive -1

When the user signs in they then get a prompt for permission for this app to update their skydrive:

Skydrive -2

As soon as Yes is clicked, the upload then starts, so what's happening in these screen shots if the above bit of javascript.

Step 4: The Server Side REST PUT

On the server, the WCF Service then does a HTTP PUT to the Live Connect SkyDrive REST API

        public static void UploadFileToSkydrive(FileInfo file, string accessToken)
            string uploaduri = string.Format("https://apis.live.net/v5.0/me/skydrive/files/{0}?access_token={1}",
                file.Name, accessToken);

            HttpClient httpClient = new HttpClient();

            if (!string.IsNullOrEmpty(hapConfig.Current.ProxyServer.Address) && hapConfig.Current.ProxyServer.Enabled)
                httpClient.TransportSettings.Proxy = new WebProxy(hapConfig.Current.ProxyServer.Address, hapConfig.Current.ProxyServer.Port);

            HttpContent c = HttpContent.Create(file.OpenRead());

            HttpResponseMessage response = httpClient.Put(uploaduri, c);

I got the HttpClient from the WCF REST Starter Kit Preview 2 (you could use the one in MVC 4 as well).

Once this proc has run, the loading box on the clients browser closes and the file appears on SkyDrive.



It took more about 2 hours to figure out what to do with a fresh start.  I did try doing it after I'd done the GoogleDocs call, but I must of had they're authentication method on the brain.


This part of HAP+ will be released in the V8 release scheduled for Summer 2012