Mobile Zone is brought to you in partnership with:

Den is a DZone Zone Leader and has posted 460 posts at DZone. You can read more from them at their website. View Full User Profile

Flickr API for Windows Phone 7 – Part 3 – The Core – Getting the full token

09.29.2010
| 5840 views |
  • submit to reddit

Now that I've shown you how to create the hashing service to get the signature hash, the application needs to be actually linked to it. This is done by using a service reference, but there are a few interesting moments I would like to highlight in the process of getting the hash.

First of all, make sure that the service is running. The application should already have the correct service reference, so you don't have to worry about it for now - just make sure it is active (you see the WCF Test Client).

Getting the full token is needed when your application is being authorized by the user. Once you've got the short (mini) token, you will need to call flickr.auth.getFullToken to get the full token (you need it in order to perform operations that require authentication). But before going any further, I must mention that I've introduced some modifications to the Authentication class, as well as to the GetSignature method.

Although this change doesn't require deep refactoring, it certainly helps later on. What I did is I declared a delegate inside the class:

public delegate void HelperDelegate();

Now you might be wondering - what is the purpose of this delegate? I talked to Chris McLean (a software developer from Tulsa, OK) today at a Microsoft event about the possibilities to wait for an operation to complete. One of the optimal ways to do this is by creating a delegate, that will basically execute a specific action only when the async action (and in fact, if you take a look at the previous article from this series) is complete. 

Inside the sam Authentication class, I am creating a HelperDelegate instance.

private static HelperDelegate helperDelegateInstance;

Also inside the class there is an instance (that is not set by default) of this delegate:

private static HelperDelegate helperDelegateInstance;

I am adding another (third) parameter to the GetSignature method - an instance of HelperDelegate:

public static void GetSignature(Dictionary<string,string> parameters, string secret, HelperDelegate helperDelegate)

Now, inside the method itself I amactually setting the helperDelegateInstance to helperDelegate:

helperDelegateInstance = helperDelegate;

My method is initiating an asynchronous operation - GetHashStringAsync. For the completion event handler assigned to this method (GetHashStringCompleted), I am calling the delegate (the instance set in the class) right after I set the Signture property:

helperDelegateInstance();

So here is how exactly this delegate will help. When I will call GetSignature, I will actually want the signature to be there before I will be able to perform some other operations (e.g. get the full token). The delegate here is a way to execute a set of actions that are triggered right after the asynchronous operation is completed (therefore, it is called in the completion event handler). When actually calling the method, I can use anonymous delegates to perform actions dependent on Signature:

Core.Authentication.GetSignature(DICTIONARY, SECRET, () =>
{
    // Some action that requires the signature to be there
});

Now, I've added the GetFullToken method to the same Authentication class:

public static void GetFullToken (string miniToken, string signature,string apiKey, HelperDelegate helperDelegate)
{
    helperDelegateInstance = helperDelegate;

    WebClient client = new WebClient();
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
    string URL = string.Format("http://www.flickr.com/services/rest/?method=flickr.auth.getFullToken&api_key={0}&api_sig={1}&mini_token={2}&format=json",
            apiKey, signature, miniToken);
    client.DownloadStringAsync(new Uri(URL));
}

Here you can see a familiar delegate - placed for the same purpose as I described above. However, the async call here is tied to the WebClient instance. Once I have the signature, I am able to generate the full token - I simply have to create a request to:

http://www.flickr.com/services/rest/?method=flickr.auth.getFullToken&api_key=APIKEY&api_sig=APISIG&mini_token=MINITOKEN&format=json

Theresponse will be handled by the completion event handler:

private static void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    try
    {
        JsonObject json = JsonObject.Parse(Core.Json.MakeValidJson(e.Result)) as JsonObject;
        JsonValue value = null;
        json.TryGetValue("auth", out value);
        json = JsonObject.Parse(value.ToString()) as JsonObject;
        json.TryGetValue("token", out value);
        json = JsonObject.Parse(value.ToString()) as JsonObject;
        json.TryGetValue("_content", out value);
        FullToken = value.ToString().Remove(0,1);
        FullToken = FullToken.Remove(FullToken.Length -1,1);
    }
    catch
    { FullToken = null; }
    
    helperDelegateInstance();
}

Since the result I am getting is in JSON format, I am using JsonObject to access that data. It is a member of System.Json. This namespace and library are not accesible by default, so you will have to add a reference to it manually from a location similar to this: C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client.

You probably noticed a method call that I didn't mention anywhere:

Core.Json.MakeValidJson(e.Result)

This method is a member of a separate static class that I created - Json, specifically designed to perform various helper tasks on Json data.

Here is what it looks like:

public static class Json
{
    public static string MakeValidJson(string input)
    {
        input = input.Remove(0, input.IndexOf('{'));
        input = input.Remove(input.Length - 1, 1);
        return input;
    }
}

The need in this method becomes apparent when you see what Flickr returns to a request:

jsonFlickrApi({"auth":{"token":{"_content":"FULL_TOKEN"}, "perms":{"_content":"delete"}, "user":{"nsid":"USER_ID", "username":"Dennis K. Delimarsky", "fullname":"Dennis Delimarsky"}}, "stat":"ok"})
jsonFlickrApi and the parantheses should not be here - by default, it is invalid JSON. The MakeValidJson eliminates these additional elements so that JsonObject can perform the parsing.

Once I obtain valid JSON, I select the needed value in the JSON-formatted tree, remove the quotes (since the value is returned with quotes) and call the delegate (that will be the user action on event completion).

So now you're done with another part of the core engine - you can easily test it out with this code snippet somewhere in the main page:

string apiKey = "YOUR_API_KEY";
string miniToken = "YOUR_MINI_TOKEN";
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("api_key", apiKey);
param.Add("method", "flickr.auth.getFullToken");
param.Add("mini_token", miniToken);
param.Add("format", "json");



Core.Authentication.GetSignature(param, "YOUR_SECRET", () =>
{
    Core.Authentication.GetFullToken(
        miniToken, Core.Authentication.Signature, apiKey, () =>
        {
            Debug.WriteLine(Core.Authentication.FullToken);
        });
});

Make sure the hashing service is running before you attempt to do this. You will get the full token shown in the output window.

If you want to keep up with my project, you can download the current solution (VS2010) at the current development stage, with all classes, methods and delegates - I know sometimes it coulbe be confusing to follow some instructions, but it becomes clear when you see code.

So here's where you can get it.

You can also get the source code (VS2010) for the hashing service here.