Tech Blog

Jay's Technical blog

Metro Nuggets: Cloud-based File Contracts helper - UriBasedStorageFile

28 March 2012
Jay Kimble

[WARNING! This is an archived post and as such there may be things broken/missing here.. you have been warned.]

I have been doing a series of posts around my adventures in creating a cross-platform Dropbox library for Windows Phone and WinRT. I actually have a working API at this point, so of course the next step is to look into implementing a File Open Contract.

One of the first things you will notice is that you have to return set of IStorageFile back to the caller. So you have to essentially hand back a mechanism that the caller can use to open your file from the cloud (without the caller necessarily needing to know anything about that). At least this is my understanding at this point. I might have to pre-download my files (something I will be testing very soon).

Regardless, I thought it would be nice to go ahead and implement IStorageFile based on an URI. So I have created (and am letting you tinker with) this class. Here’s what happens with it. You call the constructor of my class with a URI that can be used to access the file (aka download the file), and my class builds up a read-only file that the file system thinks is a regular old file (BUT there are a bunch of things unimplemented, so you won’t be deleting files for instance). You can even control how the class acts when an unimplemented function is called (it can silently fail or generate an exception).

Let’s see some code:

var cloudFile = new UriBasedStorageFile(
new Uri(someUrl, UriKind.Absolute),
"Application/text", // optional mime type (default is "application/octet-stream")
"test.txt", // optional file name (default last part of the path)
true); // Ignore Not Implemented items
var file = await cloudFile.CopyAsync(Windows.Storage.KnownFolders.DocumentsLibrary);

Yep, that’s 2 lines of code to copy a file from a URI to a file. Pretty cool hunh?

Implementation details (stuff I learned)

Implementing this interface is a little difficult. Well, not majorly so, but there are some gotchas. First of all, I am used to working with Tasks, something that you will get very familiar/comfortable with when/if you get into the Async stuff. The interface requires that you return IAsyncActions and IAsyncOperation<T>s. If you look at Task you will see that it implements this at some level, but casting does not work. After digging a bit I discovered an extension (which is a part of System). Essentially you can call your functions that return Task and Task<T> and then call AsAsyncAction() or AsAsyncOperation() on the returned Task to get it cast to the appropriate type.

Design

So, here’s what I did with this class. I implemented the interface and then call individual methods that  return Task based equivalents and then use the AsAsync___ extension methods mentioned above. My actual methods are virtual and protected (which means you could derive a new class from them and override the missing functionality and get a something that is closer to fully functioning). I’ll actually be doing this with my Dropbox implementation so I can pass Dropbox-based files to the OS and things will act like these are actual files on the file system. Pretty cool, hunh?

By the way, none of this is done yet. If you want to help out, let me know.

Also, my description of building a File Open Contract may be incomplete. Like you I am learning this stuff. There might be a future post where I state that everything I knew is wrong. As far as the Open contract goes, at this point I am assuming that I will need to hand back the object and the caller will be able to open up the file. I am hoping that the caller will not need any kind of Internet access defined, but if that happens I will be rewriting these classes a little (so that this isn’t required.

So here’s the link to where the project lives: https://bitbucket.org/DevTheo/metrodropbox/overview
Here’s the link to where the file lives: https://bitbucket.org/DevTheo/metrodropbox/src/3617e9282c60/Common/IStorageFile

Oh yeah, the code from the last couple Metro Nuggets can be found here as well. (there have been some updates. For instance the Windows Phone WebAuthenticationBroker object has changed a little due to a bug I discovered).


Metro Nuggets: WebAuthenticationBroker an oAuth solution

20 March 2012
Jay Kimble

[WARNING! This is an archived post and as such there may be things broken/missing here.. you have been warned.]

A few years ago I worked for a company that sponsors the Facebook C# SDK. I wrote a number of the initial demos and answered questions on StackOverflow for the project. I know what our users’ biggest challenge: getting an AccessToken.

In terms of oAuth getting an AccessToken for an App is the equivalent to logging in. Essentially you are authenticating and getting permission from the user. As previously mentioned, I am building a Dropbox client for Windows8 Metro. Dropbox has a new oAuth style library which is (or at least appears to be) the recommended manner to communicate with Dropbox programmatically. So, my new Windows8 Metro/WinRT library needs to communicate in this manner. We will not go into the ins and outs of oAuth, but the first steps are pretty critical for you to understand. Here’s what they are (provided you don’t have an AccessToken, yet):

  1. Get a RequestToken (this is a temporary key/secret) for your application
  2. Redirect user to specific URI –inside of a browser window of some sort-- to logon and accept your app (you can provide an optional redirect URI which the user gets sent to after authenticating and accepting your app)
  3. Detect that the user has accepted your app, and get an AccessToken (a more permanent key/secret) using the request token

The next steps after this are to first save off the AccessToken and then use the AccessToken when making requests to the REST API. There’s a lot wrapped up in this, but the 1st step and the 3rd step are simply calls to the REST API (they are signed in a manner outlined by the oAuth spec, but let’s not get too heavy into that). That middle step is problematic for people. Constructing the URI is easy, but monitoring the Browser can be a problem for some reason.

Enter the WebAuthenticationBroker
Microsoft solved this for us in Metro/WinRT. They have a gizmo called the WebAuthenticationBroker. Essentially this manages the process for step 2. The challenge is that sometimes an oAuth service will return additional data that we need in the QueryString of the call to our callback URI (yep, we need to do that). Cutting through all that can be a little work –especially when all you really want to be able to do is make a call to a service and use a third party API to facilitate that. Here’s what it looks like:

WebAuthBroker

Essentially a chromeless browser window appears on the screen. Now I fully expect that Dropbox will be detecting the Windows8 Metro UI and will give us a slightly different UI (right now you have to scroll over to the login). A couple additional important items here. If you look closely you will see 2 links at the top of the WebAuthenticationBroker’s control. The one on the right restarts the process presumably taking the user back to the original URI. The one on the left allows the user to simply say “let’s go back to the app.”

The code for this is awesome! I can’t stress how cool it works. Basically you do an await on the WebAuthenticationBroker. It returns you an object that indicates whether the user canceled, an error occurred, or we successfully got to the target URI. If we got to the target URI then we also get the additional data passed in with that request via another property. Here’s the pertinent snippet of code from my library:

String DropBoxUrl = await GetAuthorizeUri(endUrl);
System.Uri StartUri = new Uri(DropBoxUrl);
System.Uri EndUri = null;
if(!String.IsNullOrEmpty(endUrl))
    EndUri = new Uri(endUrl);
Debug.WriteLine("Navigating to: " + DropBoxUrl);
WebAuthenticationResult WebAuthenticationResult;
if(!String.IsNullOrEmpty(endUrl))
    WebAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
                                        WebAuthenticationOptions.None,
                                        StartUri,
                                        EndUri);
else
    WebAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
                                        WebAuthenticationOptions.None,

											
											
if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success ||
    (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.UserCancel && WebAuthenticationResult.ResponseData != null))
{
    Debug.WriteLine(WebAuthenticationResult.ResponseData.ToString());
    var accessToken = await GetAccessToken();
}
elseif (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
{
    Debug.WriteLine("HTTP Error returned by AuthenticateAsync() : " + WebAuthenticationResult.ResponseErrorDetail.ToString());
}
else
{
    Debug.WriteLine("Error returned by AuthenticateAsync() : " + WebAuthenticationResult.ResponseStatus.ToString());
}

I try to get an AccessToken regardless of whether the user canceled or not because if the programmer didn’t specify an EndUri then I need to assume the user might have simply closed the WebAuthenticationBroker control via the link (back to app).

Anyway, this is a very cool mechanism. I don’t have to attach this code to the UI in any manner. It simply injects itself into the UI all on its own.

Windows Phone compatibility object
I have also mentioned that I am back-porting this library to Windows Phone. In the process I realized that I needed a mechanism like this one. In fact after looking at this one, I have to say that this is the way it SHOULD be done. I haWebAuthBroker-WPd arguments with a few folks back in the day with the FB C# SDK in that I thought we should provide the mechanism. I was shot down (mainly because there were too many scenarios to handle.. that project provides Facebook to everything). Anyway, going back to that SHOULD be done. I realized that there should be a mechanism like this for Windows Phone. I have done that. Warning: it does rely on the Async CTP (truth be told this is what sold me on Async), BUT the code for Windows Phone is the same as the code above. To the right is a scrren shot of the the same code running on the Windows Phone emulator (using my compatibility object):

As you can see Dropbox knows the Windows Phone browser and presents a nicer dialog. You can also see that I have the same links in the project, etc. My underlying object injects it’s UI on top of the current page, so you don’t need to add anything other than the 3 files to your code to get this. There’s still work to be done.

I am attaching an early release of this to this post (but will probably bundle my compatibility plugins into an open source project (or at least will be exposing the source code repository publicly). I need to figure out a few more things before I can call this close to done, but feel free to play around with it (and if you spot any bugs or fix them.. let me know).


Metro Nuggets: Async is your friend

20 March 2012
Jay Kimble

[WARNING! This is an archived post and as such there may be things broken/missing here.. you have been warned.]

I’m in the process of exploring the Metro-Style Win8 API. If you’ve done much looking you probably have discovered that the new Async is everywhere! This is not a bad thing as your code is much cleaner and easier to read. The downside though is that creating something that is compatible between say Win8 Metro and Windows Phone (the original metro) can be difficult.

Luckily there is still a CTP of the Async stuff that works with Windows Phone (and it has a GoLive license, so you can use it). CTP sounds scary (it did to me too). If you are deciding to do install the Async CTP, you might want to go here --http://blogs.msdn.com/b/lucian/archive/2011/11/01/async-ctp-v3-installation.aspx-- and read up.. since I am betting you –like I-- have some VS patches that will prevent you from installing it). To get it installed you need to temporarily uninstall the Silverlight 5 tools and any Visual Studio patches after say December.. if you look at the link it will get you started (there are a couple forum posts that were helpful to me).

Now you are ready to play. I’m sure by now you have seen the syntax, but let’s make some comparisons (and we’ll use WIndows Phone code and an example on a class that I have rarely seen discussed: HttpWebRequest):

Here’s the old way (warning there is a lot of code here):

  1:// Pretend like Item info below just contains a couple pieces of info:
  2://  like Uri, Method, and possible a filename to save to --in IsoStorage
  3:void downloadSomething(UriInfo item) {
  4:     var webReq = HttpWebRequest.CreateHttp(UriInfo);
  5:     webReq.Method = item.UriMethod;
  6:     WebRequests.Add(item, webReq);
  7:// If we were passing post values to the routine we would need to
  8:// Begin getting the request stream with a callback and then End Getting
  9:// the request stream (this is bad enough.. don't want to overcomplicate things)
 10:     webReq.BeginGetResponse(ResponseCallback, item);
 11: }
 12:protectedvoid ResponseCallback(IAsyncResult ar) {
 13:     IFileItem item= (IFileItem) ar.AsyncState;
 14:     var webR = WebRequests[item];
 15:     var resp = (HttpWebResponse) webR.EndGetResponse(ar);
 16:
 17:if (resp.StatusCode == HttpStatusCode.OK) {
 18:// We could also do the whole Begin/End on the Response Stream
 19:// (with another calllback)
 20:using (var strm = resp.GetResponseStream()) {
 21:             var buffer = newbyte[4096];
 22:             item.BytesDownloaded = 0;
 23:// If the file exists we need to delete it (BTW, using Jay's IsolatedStorage Facade which looks like System.IO.File, Directory, FileInfo, and DirectoryInfo -- "PS" stands for persisted storage)
 24:if (PSFile.Exists(item.DestinationNameAndPath))
 25:                 PSFile.Delete(item.DestinationNameAndPath);
 26:
 27:// We should actually check to see if the path exists for this file..
 28:// BTW, this uses my Isolated Storage Facade classes
 29:// (so PSDirectory == SystemDirectory, but just against IsolatedStorage)
 30:if (!String.IsNullOrEmpty(System.IO.Path.GetDirectoryName(item.DestinationNameAndPath)) && !PSDirectory.Exists(System.IO.Path.GetDirectoryName(item.DestinationNameAndPath)))
 31:                 PSDirectory.CreateDirectory(System.IO.Path.GetDirectoryName(item.DestinationNameAndPath));
 32:
 33:using (var fs = PSFile.Create(item.DestinationNameAndPath)) {
 34:                 var fileLength = item.ActualSize;
 35:do {
 36:int count = strm.Read(buffer, 0, 4096);
 37:if (count < 1)
 38:break;
 39:                     fs.Write(buffer, 0, count);
 40:                     item.BytesDownloaded += count;
 41:                 } while (true);
 42:             }
 43:             item.BytesDownloaded = item.ActualSize;
 44:         }
 45:     }
 46://else
 47:// We got an error or something. Normally I notify the end user of this (this is left up to you to do on your own)
 48:
 49: }


New Way:

  1:publicstatic async Task<string> simpleHttpPost(string url)
  2: {
  3:     var uri = new Uri(url);
  4:
  5:     HttpWebRequest client = HttpWebRequest.CreateHttp(uri);
  6:     client.Method = "POST";
  7:
  8:     var response = (HttpWebResponse) (await client.GetResponseAsync());
  9:     var _lastResultCode = response.StatusCode;
 10:
 11:if ((int)_lastResultCode < 400) {
 12:using (var strm = (new StreamReader( response.GetResponseStream())))
 13:return await strm.ReadToEndAsync();
 14:     }
 15:
 16:return"";
 17: }

Admittedly when giving examples you try to keep the code similar for comparison sake. I decided to simply grab some code from my new project and from an old project. Please forgive me. I will do my best to highlight the big differences here.

The old way with HttpWebRequest was that you did a Begin____(callbackFunction) for nearly everything. The callback function must (among other things) call End______() to actually get what you were looking for (this could be the RequestStream, so you could make a post and push post variables, or it could be the response, or the ResponseStream – the ResponseStream at least has a synchronous version which I used above). Because this was going on you could use delegates and not lose context, but the execution order was jumbled.. so essentially you created a delegate for each callback (so the code came first) then you would call the Begin which would go out do the activity and then make calls into your code that was previously defined.. it is very ugly and hard to follow what is happening…

The new way introduces the use of the await or Await (in VB) keyword. When I first saw this I thought it was a gimmick, but the reality is that our APIs can be cleaner. You get the ability to simply suspend execution of your code while you wait for something to come back. You do have to mark your function with the async (or Async in VB) Keyword and use Task<T> as a result.

I really feel like the second example is much cleaner and easier to follow. At the very least you know what order things are happening..

An Added Benefit
Let’s make a not so contrived example to show you something else that is pretty cool. Let’s assume that we have an app whose first action is to run out to a service of some sort and get some data that will be databound to the UI. Meanwhile we have a few additional things that need to be done (so we don’t want to be prevented by the download)..

  1:protectedvoid setupMainPage() {
  2:     getData();
  3:// Next line will happen before the getData call fully completes
  4:// this is because we are not "await"ing the return
  5:     doSomethingElse();
  6: }
  7:protected async void getData() {
  8:     var result = await simpleHttpPost(new Uri("http://someDomain.com/someService"));
  9:     var dataObject = deserializeObject(result); // turns json string into object
 10:this.DataContext = dataObject;
 11: }

So essentially we can fire things off and when they complete they will continue running. We don’t have to await everything.

Preview of Future posts
At present I am building a new Dropbox client library for Windows8 and am retrofitting it for Windows Phone. To do this I had to create some compatibility objects for Windows Phone to make this happen. I actually also had to create some helper objects that do things like HTTP because they are very different and I wanted to avoid compiler directives as much as is possible. I will be writing about all of this in the coming weeks. I will eventually be speaking at a combines Tampa Bay Windows Phone UG and Tampa Bay Windows Dev UG meeting about all of this.


Windows8 CP: Almost there!

02 March 2012
Jay Kimble

[WARNING! This is an archived post and as such there may be things broken/missing here.. you have been warned.]

So this is more of a review and less of a techy post. Yesterday as I was exploring Win8, I discovered 2 apps in the store that are important in my mobile world: EverNote and the YouVersion Bible.

You see, I have a daily routine where I bring up YouVersion on my Acer Iconia (Android) Tablet (before this I used an iPad2.. before that I had a less techy way of doing this). I read a little scripture and then note a couple verses and then I bring up EverNote paste in the scriptures and write a few notes for myself as well as do some general journaling. It helps to keep my thoughts together before I go full force in my day.

I was stoked because I could possibly move entirely to Windows 8. I actually started checking prices on Tablets that would run Win8, and I was thinking I could have my tablet experience with the full power of Windows.. this would be more than cool!

Now I tried this with the developer bits, but the desktop EverNote didn’t bring up the keyboard appropriately, I gave up and went back to my iPad at the time..

So this morning I tried it. You can guess by the post’s title that something didn’t work. I was actually able to not only bring both apps up, but pin the Bible on the left hand side. Where things failed was EverNote. It let’s you edit notes, but I could not change the notebook I was saving too. It seems to default to a Notebook I set up to do a knowledge transfer to my job (as I was leaving the company). I also couldn’t figure out how to edit after I had accidently closed the notebook. I will have to wait for an update to EverNote before I can really use this.

Oh yeah, I will also be wanting the YouVersion guys to update their app and give me offline bibles (otherwise I have to have wifi always which in the morning isn’t too much trouble).

Beyond this fact I am liking the evolution of the OS from the Developer Bits. I have read some stuff about how the OS isn’t necessarily intuitive in all respects, and I would concur. I have watched all the intro videos, so I know to swipe up to get app’s menu or swipe on the right hand side to get the charms or to swipe left to bring in an already running app.. and I figured out the whole swipe down to be able to throw your app off screen (shutting it off).