Saturday, November 3, 2007

CanYou? - sample Facebook application

[Update: The source can now be found here. It has been updated to use the latest version of FacebookNET library.]

As you can read from my previous post I have been invited to give a presentation about ASP.NET at Computer Space event. I have picked up the idea about building a Facebook application with ASP.NET. And here it is. It is called "Can You?". Let me explain you the idea behind it.

The Idea

The idea of the app is to utilize your social graph and search through all your friends in order to check can you do particular activity. For example you may want to stay for a couple of nights in France and want to see if some of your friends can help you. The idea is simple and silly, but can be expanded to have more potential if your friends also add the application. Then searching for appropriate connections can be expanded on their friends too. (Note that Facebook did not allow you to recursively get friends of your friends. Only one level down from the currently logged user). You can install the app to your Facebook account from here.

Development of the Idea

I have previously mentioned that there are 2 libraries for building Facebook applications with .NET - Facebook.NET and Facebook Developer Toolkit. The first one is build by no other but Nikhil Kothari, the second by Clarity Consulting. So which to use? Without a doubt the Facebook.NET is the way to go. It has some pretty good server controls that abstract away some of the Facebook plumbing. I'm not going to explain in details Facebook.NET, nor the ways you can build apps for Facebook. You can learn all this in Nikhil's introduction to Facebook.NET post. I encourage you to read it right away. Next time it is best to come to my presentation :)

Now I will focus on the application and how I utilize the library.

Activity Provider

As you have already learned about the idea and probably played with the app let me explain you the implementation details. The application is build on the idea of Activity Providers. Each activity provider holds details about specific activity that the user will be able to do - for example going to foreign country or working at some company. The Activity Provider is based on the provider model introduced in .NET 2.0 and all available activities are picked from the configuration file. Each activity provider must implement:

public abstract ActivityControl GetActivityControl(Page page);

which returns an instance of ActivityControl.

ActivityControl

ActivityControl is very simple. It derives from user control and have a simple event called ActivitySelected defined this way:

public event EventHandler<ActivitySelectedEventArgs> ActivitySelected

ActivitySelectedEventArgs

The event arguments for the ActivitySelected event is simple class that holds the ids of the users which are appropriate (match the condition) for the selected activity.

public class ActivitySelectedEventArgs : EventArgs

{

private readonly List<string> appropriateUids;

public IList<string> AppropriateUids

{

get { return appropriateUids; }

}

public ActivitySelectedEventArgs(IEnumerable<string> appropriateUids)

{

this.appropriateUids = new List<string>(appropriateUids);

}

}

These arguments are then used on the default.aspx page to display the list of friends that can do the work. Let's look at the Default.aspx page.

Default page

In the default page we have a drop down with all available activities. We populate it using a helper class that retrieves them from the configuration file. When an activity is selected we load its ActivityControl in a PlaceHolder. Then when the ActivitySelected event is rose we have a ListView (new class in 3.5 that provides complete control over on the generated markup, something like repeater on steroids; more details for it on ScottGu's blog) that we bind with the appropriate friends. That's it. I would not paste any code or markup. You can look at them in the sample solution.

Now let's examine the two activities that I have created.

Country Activity

This is activity for visiting a foreign country. Let's look at the code and let me explain you what it does:

List<string> appropriateUids = new List<string>();

string selectedCountry = ddlCountries.SelectedValue;

FacebookApplication fbApp = FacebookApplication.GetCurrent(Page);

object queryResults = fbApp.Service.Fql.ExecuteQuery(

string.Format(

@" SELECT uid, hometown_location.country

FROM user

WHERE uid in (

SELECT uid2

FROM friend

WHERE uid1={0}

)",

fbApp.UserID));

foreach (object result in (IEnumerable)queryResults)

{

string country = DataBinder.Eval(result, "hometown_location.country").ToString();

if ( country.Equals( selectedCountry, StringComparison.OrdinalIgnoreCase ) )

{

appropriateUids.Add(DataBinder.Eval(result, "uid").ToString());

}

}

OnActivitySelected(new ActivitySelectedEventArgs(appropriateUids));

First we get the current FacebookApplication object (same technique is used for getting ScriptManager for example). The FacebookApplication is headstone for accessing the Facebook API. Using it we are able to execute FQL (Facebook's SQL like DSL for making queries and return particular projections of the data. This ends up in less traffic and backend parsing) which gets the id and country of all friends of the currently logged user. Then we iterate over the results and check for appropriate data. Have a closer look how we access the results. What Facebook API returns from a FQL query is just a collection of property bags (JSON objects). To handle them Facebook.NET implementation creates an instances of its own internal object:

internal sealed class JsonObject : Hashtable, ICustomTypeDescriptor

As you can see it implements ICustomTypeDescriptor, which provides runtime information about object's properties, methods, etc. This is way we are using the DataBinder.Eval() method to get the required data. In our case this is the country(Note that we can specify the country in a where clause in the FQL).

Work Activity

This one check's whether some of your friends is working in particular company so they can help you work there too.

LINQ sourceI'm posting a screenshot here, because my code highlighting tools breaks on LINQ queries :) As you can see from it here we are using LINQ this time to find did anyone of our friends have ever worked at the selected company. This query will pull the all fields data about the friends. This can be optimized using the second parameter passed to GetUsers() method. It specifies which particular fields you want to be retrieved.

So that's it. You can look at the sample and try to build your own activity that can be plugged into the application.

Download materials

Here is the link to the source code. It has a little bug I'm sure you will find it :) Note that I'm including the source to Facebook.NET, because I have found a small bug in the code and have to fix it.

Presentation is available here. It is in the form of mind map. You have to download and install Bookvar in order to open it.

You can also look at the presentation in our Silverlight based mind map viewer here.

P.S.: Unfortunately I had some problems with the hosting facilities and the application that is uploaded to the server is build on ASP.NET 2.0 and did not have the AJAX stuff I have originally added to the application.

P.S.S.: You can also listen to this .NET Rocks! podcast with Nikhil Kothari talking about Facebook.NET, Script#, life, etc.

5 comments:

Anonymous said...

Nice article. I tried to download it but it loads to a bunch of advertisements. Could you repost a valid download link to the source code? Thank you

ligAZ said...

The source can be found here.

Anonymous said...

Thanks, Mr. Ligaz

Thats nice code, but fail to run the application, due to following error.

Session must have application key and secret before logging in.
To set them in your web.config, use something like the following:



"

Express your views and solution.

Thanks & Regards

Anonymous said...

Session must have application key and secret before logging in.
To set them in your web.config, use something like the following:
<add key= ApiKey value ="YOURApiKEY"
<add key="Secret" value ="YOURSECRET"

Cris Monde said...

We are so thankful that we have those Facebook Application Developer that help us to make Facebook more interactive and help us to use it easily and convenient.