Saturday, November 24, 2012

Windows 8 + Salesforce.com Part 3

In my last two posts I showed how to connect to Salesforce.com from a Windows 8 Windows Store application, and then how to retrieve a list of accounts. In this article I will show how to display the accounts.
The first thing we need is a view model class to hold the data we want to display. For an application this simple we could get away without a view model but creating one is a good practice and it does make things easier for more complex applications.

public class AccountsViewModel : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<sfdcAccount> accounts;

    public ObservableCollection<sfdcAccount> Accounts
    {
        get { return accounts; }
        set {
            accounts = value;
                if (PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("Accounts"));
        }
    }
  
}

You will notice that that class implements the INotifyPropertyChanged interface. This is needed so that XAML data binding can detect changes to the object. The implementation of the interface is in the first line, the PropertyChanged event which needs to be called whenever a property of the object changes. The rest of the class is a property that holds an ObservableCollection of sfdcAccounts. In the setter you will see that we raise the PropertyChanged event passing in a reference to the object and a PropertyChangedEventArgs object containing the name of the property. Even though this is an ObservableCollection it only allows the data binding to see when items are added to or removed from the collection. The PropertyChanged event is needed to notify data binding if the actual collection object referenced by the property changes.

Next we need a new page to display the accounts, so from the project select Add/New Item, then select Items Page and change the name to AccountsView.xaml. You will get a message asking to add files to your project, select Yes. To have this page displayed at startup open App.xaml.cs and in the OnLaunched function change MainPage in the following line to AccountsView.

if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))

While we are in App.xaml.cs we need to create an sfdcLibrary object that we can use throughout our application. To do this add the following property

public static sfdcLibrary SFDC { get; set; } 

then add the following line to the App() constructor

SFDC = new sfdcLibrary();

Now lets work on the AccountsView we created earlier. In AccountsView.xaml.cs you will notice that the class inherits from LayoutAwarePage. This is a helper class that is part of the Windows Store Application template which wraps the base Page class and provides help with things like navigation.  The first change we need to make in this file is to add this private variable which will hold the view model

private AccountsViewModel model = new AccountsViewModel();

Next replace the LoadState function with this one

protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    this.DataContext = model;
    if (await App.SFDC.LoginSalesforce())
    {
        var acc = await App.SFDC.ReadAccounts();
        model.Accounts = acc.records;
    }
}

LoadState is called in response to the OnNavigatedTo event which happens whenever a page is displayed.  The first thing we do in this function is set the page’s DataContext property to the view model. DataContext will be used as the base for all the data binding we do on the page. Next we call the LoginSalesforce function to do the OAuth login and if it is successful we read the account list from Salesforce and assign it to the Accounts property of the viewmodel.

We are almost done, the final changes we need to make are in AccountsView.xaml. First in the Page.Resources section change the source to point to the Accounts property of the view model like this

Source="{Binding Accounts}"/>

This will bind the Accounts list in our view model to the GridView which will display the data. Next thing we need is a DataTemplate to be used to display each account.

<DataTemplate x:Key="StandardItemTemplate">
    <StackPanel Orientation="Vertical" Width="200" Height="200" Background="#FF07B3F3"  >
        <TextBlock  Text="{Binding Name}" HorizontalAlignment="Center" Margin="20,10,20,0" FontWeight="Bold" TextWrapping="Wrap" FontSize="20" TextAlignment="Center" />
        <TextBlock Text="{Binding AccountNumber}" HorizontalAlignment="Center" Margin="20,10"/>
    </StackPanel>
</DataTemplate>

The template starts with a 200x200 StackPanel with a blue background. Inside this we have two TextBlocks, the first one will show the Name of the account and the second will show the AccountNumber. Finally we need to change the ItemTemplate property of the GridView to use the template we just defined.

ItemTemplate="{StaticResource StandardItemTemplate}"

StaticResource tells XAML that we are using a resource defined elsewhere in the markup, in this case in our Page.Resources section. StandardItemTemplate is the Key property we defined in the template markup.

If we run the application we will first get a Salesforce login screen. Once the correct username and password are entered all the accounts in the Salesforce instance will be displayed.

image

Now that we have a basic working application I will expand on it in future blog posts.
You can download the full source for this application here. To use this code you will need to put your ClientID and ClientSecret in the sfdcLibrary class.

Saturday, November 17, 2012

Windows 8 + Salesforce.com Part 2

This is the second part of a series of posts on how to create a Windows 8 WinRT application that uses the Salesforce REST API. In the first part I showed all the code needed to authenticate to Salesforce. In this post I will show how to to retrieve data from Salesforce. In part 3 we will pull all the pieces together a display the data.
First thing we need is an object model to hold the data we retrieve from Salesforce. For the purposes of this application we will read a list of Accounts. Let’s start with a class to hold a single Account:

public class sfdcAccount
{       
    public sfdcAttributes Attributes { get; set; }

    public string Id { get; set; }
    public string Name { get; set; }
    public string AccountNumber { get; set; }
    public string Type { get; set; }
    public string Phone { get; set; }
    public string WebSite { get; set; }
    public string Industry {get; set;}
    public string BillingStreet { get; set; }
    public string BillingCity { get; set; }
    public string BillingState { get; set; }
    public string BillingPostalCode { get; set; } 
    public string CustomerPriority__c { get; set; }
 }

The first property is of type sfdcAttributes and will be used to hold meta-data about the record, we will look as this class next. The rest of the properties are a selection of fields from the Account record. There are more fields then this in Salesforce but this is a good group to work with. Here is the sfdcAttributes class that holds the type of the record and it’s unique URL. This can be used with any Salesforce object, not just the Account.

public class sfdcAttributes
{
    public string Type { get; set; }
    public string Url { get; set; }
}

Finally, we need a class to hold the meta data that is returned when we query for a group of records.

public class sfdcCollection<T>
{
    public bool done { get; set; }
    public int totalSize { get; set; }
    public string nextRecordsUrl { get; set; }
    public ObservableCollection<T> records { get; set; }
}

I made this a generic class so that it can be used for a collection of any Salesforce object, for example sfdcCollection<sfdcAccount> for a collection of accounts. The records property will hold the collection of sfdcAccounts. In the Windows forms application I made this a List<T> but to facilitate XAML data binding I have made it an ObservableCollection<T> which allows the binding system to detect changes to the collection. You will need to include the System.Collections.ObjectModel namespace to use the ObservableCollection.

In the last post we created a class called sfdcLibrary to hold all our Salesforce related code. We will add the following property and constructor to this class.

public string VersionUrl { get; set; }

public sfdcLibrary()
{
    VersionUrl = "/services/data/v26.0";
}

The Salesforce REST supports multiple versions of the API, so whenever you make a call to the API you must use the URL for the appropriate version. This variable will allow us to specify the version we want to use in one place. In this case we will hard code it to v26.0 of the API.

Now that we have an object model to hold the data we want to display we need some code to read it from Salesforce.


public async Task<sfdcCollection<sfdcAccount>> ReadAccounts()
{
    var query = accessToken.instance_url + VersionUrl + "/query?q=SELECT id,accountNumber,name,BillingStreet,BillingCity,BillingState,BillingPostalCode,CustomerPriority__c,Type,Phone,WebSite,Industry from account";

    var resp = await HttpGet(query);

    sfdcCollection<sfdcAccount> accts = null;

    if (resp.StatusCode == System.Net.HttpStatusCode.OK)
    {
         accts = Deserialize<sfdcCollection<sfdcAccount>>(await resp.Content.ReadAsStringAsync());
    }
    return accts;
}

This function will read all the Account records from your Salesforce instance, and return them in an sfdcCollection of sfdcAccounts (the Task<> is needed  because this is an async function). Reading all the records isn’t really practical in a real world application since it might return a very large number of records, but it is ok for the purposes of this demonstration.

In the first line of the function we build the URI to query for the Account fields we want. The URI starts with the instance URL, we then appends the version URL to this and finally the SOQL query.  The second line uses the HttpGet function to get the results of the query in the form of an HttpResponseMessage object, we will look at HttpGet in a second. Finally we check the HTTP status from the request and if it was successful  we use the Deserialize function which I showed in the last post to turn the JSON response into a object model we can work with.

The final function we need to look at is HttpGet.

public async Task<HttpResponseMessage> HttpGet(string uri)
{
    System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
    client.DefaultRequestHeaders.Add("Authorization", "OAuth " + accessToken.access_token);

    return await client.GetAsync(uri);
}

This works pretty much the same as the HttpPost function I showed in the last blog post.

We now have all the code we need to authenticate to Salesforce and read back a collection of Accounts. In the next post I will show how we display the Accounts.

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.