The second part of my project on writing Facebook applications in C# and the .NET Framework is regarding the unhelpfulness of the data types returned by the Facebook API.
In Part I we setup a Master Page which initiated an API session with Facebook, thereby authenticating your application. Furthermore, this part also showed how to expose the API service from the Master Page to the Sub Page. In this part, we'll write a couple of helper functions that return more helpful data types for some of the commonly used functions when writing Facebook apps.
The first of these helper functions will actually to be to do with testing your application. As you will be able to see if you read the "documentation" (cough) on Test Accounts there is no formalised test procedure and it is all a bit of a nightmare. Therefore, I decided to implement a little bit of test functionality of my own. Observe the following method:
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
namespace myApp{
public class FacebookFunctions
{
public static IList<long> getAppFriends(facebook.API api, bool testMode)
{
IList<long> friends = null;
if (!testMode)
{
friends = api.friends.getAppUsers();
}
else
{
friends = new List<long>();
friends.Add(xxxxxxxxx);
friends.Add(xxxxxxxxx);
}
return friends;
}
}
}
If you replace the "xxxxxxxx"s with two of your real friends and then call the method with testMode (which is set inside the Master Page - although you could move this to web.config with little extra effort) set to true, this method will pretend that 2 of your friends have added your application, which is a handy test routine. So, the way to call this method from inside a sub-page is:
IList<long> friends = FacebookFunctions.getAppFriends(Master.fbService.API, Master.testMode);
The second tip I'll present here is a reworking of api.users.getInfo.
One of the keys to writing scalable apps lies in making as few API calls as possible, so it therefore makes sense to call the handy users.getInfo method with one of the overloads that supports returning mutiple users in one go; you don't want to make 10 calls to get info for 10 users.
Unfortunately, the way it is returned means that there is no easy way to then get the user with the specified ID from the returned method. Here's a version that will return a nice generic dictionary for easy user lookups:
public static Dictionary<long?, facebook.Schema.user> getUsers(facebook.API api, List<long> userIds)
{
IList<facebook.Schema.user> friendsInfo = api.users.getInfo(userIds);
Dictionary<long?, facebook.Schema.user> users = new Dictionary<long?, facebook.Schema.user>();
foreach (facebook.Schema.user user in friendsInfo)
{
users.Add(user.uid, user);
}
return users;
}
As per before, to call from a sub-page:
List<long> friends = new List<long>();
friends.Add(1);
friends.Add(2);
Dictionary<long?, facebook.Schema.user> userInfo = FacebookFunctions.getUsers(Master.fbService.API, friends);
In the next part, we'll look at how you should store data because, quite frankly, the Facebook Data Store and .NET do NOT get along well together.