Tuesday, November 6, 2012

Windows 8 + Salesforce.com Part 1

Over the past year I have written a bunch of articles about interfacing to Salesforce.com and Windows 8 WinRT application, so I thought it was about time to combine the two. This is the first of a series of articles that will show how to write a Windows 8 Win RT application that accesses Salesforce through the REST API.
The first thing you will need to do is setup the REST API in your instance of Salesforce. I covered how to do this in my Salesforce REST API post. Once this setup is done you will get a Consumer Key and Consumer Secret which we will use in a little bit.
To get started with our application,  open up Visual Studio 2012, create a new project and select Visual C#, Windows Store, Blank App (XAML). This will give us a simple base template to build on.
The next step in using the Salesforce REST API is to use OAuth to authenticate to Salesforce. The basic steps for doing this are the same as in the Windows forms app that I described in my original posts, but the details are a little different when implementing the process in a WinRT app. Add a class called sfdcLibrary to the project to hold all the Salesforce access functions, and add the following namespaces:

using System.IO;
using System.Net.Http.Headers;
using System.Runtime.Serialization.Json;
using Windows.Security.Authentication.Web;
using System.Net.Http;

Next add the following private variables to the class

private string clientID = "[Your Consumer Key]";
private string clientSecret = "[Your Consumer Secret]";
private string redirectURL = "resttest:callback";

private TokenResponse accessToken = null;

Be sure to put in the consumer key and consumer secret you got when you setup Remote Access in Salesforce. TokenResponse is a class that will hold all the details that the authentication process sends back. It looks like this.


public class TokenResponse
{
    public string id { get; set; }
    public string issued_at { get; set; }
    public string refresh_token { get; set; }
    public string instance_url { get; set; }
    public string signature { get; set; }
    public string access_token { get; set; }
}

Now we can look at the code for doing the OAuth login, here is the first part

public async Task<bool> LoginSalesforce()
{
    var authURI = new StringBuilder();
    authURI.Append("https://login.salesforce.com/services/oauth2/authorize?");
    authURI.Append("response_type=code");
    authURI.Append("&client_id=" + clientID);
    authURI.Append("&redirect_uri=" + redirectURL);

    var result = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, new Uri(authURI.ToString()), new Uri(redirectURL));

    if (result.ResponseStatus != WebAuthenticationStatus.Success) return false;

First thing you will notice  is the async keyword and the return type of  Task<bool>. These will allow this function to be called asynchronously and are also needed because we will be using async functions. Next we build the URI that is needed to bring up the Salesforce login page to authenticate the user. In the Windows forms application we used a web browser control to handle this, but it turns out to be much easier to do in WinRT by using WebAuthenticationBroker class.


On the WebAuthenticationBroker we call the AuthenticateAsync method. The first parameter just specifies that we don’t want any special options. The second is a URI object  that contains the URI of the page that will do the authentication. When the method is called a new page will be displayed automatically in the application and the web page pointed to by the URI will be displayed so the user can login. The final parameter of the method is used to determine when the login process is complete. It contains the URI that the login page will re-direct to when done, so the AuthenticateAsync function will look for this address to know when to return from the method.

The AuthenticateAsync method will return a  WebAuthenticationResult object that has a ResponseStatus property. This property will have one of three values, Success if the authentication succeeds, UserCancel if the user click the back arrow to cancel the login, or ErrorHttp if there was some sort of HTTP error, for example if the login page could not be found. In this case, if the status is not success we will return false from the function.

If the authentication succeeds we will get something like this back in the WebAuthenticationResult.ResponseData property:

resttest:callback?code=jPrxA6bDXmdSBjzBFDRCwY1D09JvsHbzaL5.ISrdh2PE247HeZH.Qxv4_9p1XwXSMR78xvN8Jw%3D%3D

We need the code so we will use the next two lines to extract it.

string response = result.ResponseData;
string code = response.Substring(response.IndexOf("code=") + 5);

Now we can do the second part of the authentication process

string URI = "https://login.salesforce.com/services/oauth2/token";

StringBuilder body = new StringBuilder();
body.Append("code=" + code + "&");
body.Append("grant_type=authorization_code&");
body.Append("client_id=" + clientID + "&");
body.Append("client_secret=" + clientSecret + "&");
body.Append("redirect_uri=" + redirectURL);
var tokenResponse = await HttpPost(URI, body.ToString());
if (tokenResponse.StatusCode != System.Net.HttpStatusCode.OK) return false;

var data = await tokenResponse.Content.ReadAsStringAsync();
accessToken = Deserialize<TokenResponse>(data);
return true;


The first line contains the URI used to request an access token. Next we build up the body of the request, then call the HttpPost function to get the access token. We will look at this function in a minute. What we get back from the HttpPost function is a HttpResponseMessage object. The HttpPost function doesn’t throw any exceptions if there is an HTTP error so in the next line we need to check the StatusCode property to be sure the request succeeded. If the response succeeded we use the ReadAsStringAsync function to read the data that was returned. Finally we deserialize the JSON data returned from the HttpPost function to create the accessToken object. We will look at the Deserialize function in a minute.

Now lets look at the two helper functions that the login function uses, first HttpPost.

public async Task<HttpResponseMessage> HttpPost(string uri, string body)
{
    var client = new HttpClient();
    var content = new StringContent(body);
    content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
    return await client.PostAsync(uri, content);
}

Just like the login function we are making this one async. It accepts the URI  for the request and the data to be sent in the body of the request and it will return an HttpResponseMessage object. In the Windows forms version we used the WebRequest class but here we will use the HttpClient class which is a little easier to use. First we create an instance of HttpClient. Next we create a StringContent object from the body parameter and then in the next line set the proper ContentType header. Finally we execute the PostAsync method passing in the URI and content then returning the HttpResponseMessage object.

The final function we need to look at is the Deserialize function.

public static T Deserialize<T>(string json)
{
    var bytes = Encoding.Unicode.GetBytes(json);
    using (MemoryStream stream = new MemoryStream(bytes))
    {
        var serializer = new DataContractJsonSerializer(typeof(T));
        return (T)serializer.ReadObject(stream);
    }
}

In the Windows forms app we use the JavaScriptSerializer class to deserialize JSON, but this is not available in WinRT. The alternative is to use the DataContractJsonSerializer. It’s a pretty straight forward function so I am not going to go into the details. Just note that it’s a generic function so T will contain the type that we want to deserialize the Json into.

We now have all the code we need to do OAuth authentication with Salesforce from a WinRT application. In my next post I will show how to retrieve data and then we will get into actually using this code to display the data.

No comments: