Prabir's Blog

open source geek and lover of all tech  

(This feature requires Facebook C# SDK v5.5 at minimum)

Facebook C# SDK supports a wide variety of .NET framework ranging from .NET 3.5/4.0, Silverlight 4.0/5.0 and Windows Phone. Two months back we introduced support for Developer Preview version of .NET 4.5 with Facebook C# SDK v5.3 which allows you to take advantage of async/await and Task Parallel Library – TPL (You can read more on it here) and couple of weeks back we introduced support for TPL in Silverlight 5 with v5.4. With v5.5 we are introducing support for creating Windows Metro Style Apps. (Couple of weeks back I tweeted (@prabirshrestha) about porting SimpleJson (JSON library) and FluentHttp.Core (mockable HTTP web request wrapper for .NET) to WinRT which has made it a breeze to port Facebook C# SDK to WinRT.)

Since Windows 8 has not even hit BETA stage we will not be providing compiled binaries of Facebook.dll nor be distributing it via NuGet (package manager for .NET) anytime soon.

You will need a copy of Windows 8 Developer preview with Visual Studio 11 (express edition is supported) installed in order to compile Facebook.dll compatible with Windows 8 Metro apps. A new solution file called “Facebook-WinRT.sln” has been added in the Source folder. There is also a new sample “CS-WinRT.sln” which demonstrates authenticating the user and getting access token and then making Get/Post/Delete requests to Facebook server using async/await.

Here is a hello world example:

public async FacebookHelloWorld()
{
    try
    {
        var fb = new FacebookClient();
        dynamic result = await fb.GetTaskAsync("4");
        txtName.Text = result.name;
    }
    catch(FacebookApiException ex)
   {
       // catch facebook exceptions
   }
   catch(Exception ex)
   {
     // catch other non facebook exceptions: like no internet connection
   }
}

Happy New Year and have fun writing a Facebook Metro App and don’t forget to apply for Window 8 First Apps Content.

(This feature requires Facebook C# SDK v5.4 at minimum)

Now that Silverlight 5 has hit the RTW build, it is now time to officially release Facebook C# SDK build for Silverlight 5. Starting with Facebook C# SDK v5.4 we will be shipping the compiled libraries for Silverlight 5 (We will continue to support Silverlight 4 for few upcoming months, and would highly recommend you to update to Silverlight 5 if possible as you can take advantage of some new stuffs that has been baked in to take advantage of Silverlight 5).

With v5.3 we introduced support for Task Parallel Library (TPL) in .net 4.0 builds, and now with v5.4 we are now bringing it to Silverlight 5. You can read in details about TPL features in Facebook C# SDK at What's new in v5.3. This post will be specific to Silverlight 5.

A new sample called “CS-SL5-OutOfBrowser.sln” has been added which demonstrates the use of dyanmic and TPL with Silverlight 5.

Here is a sample graph api request under Silverlight 4:

var fb = new FacebookClient(_accessToken);

fb.GetCompleted += (o, e) =>
                        {
                            if (e.Error == null)
                            {
                                // make sure to reference Microsoft.CSharp if you want to use dynamic
                                dynamic me = e.GetResultData();

                                Dispatcher.BeginInvoke(
                                    () =>
                                    {
                                        picProfile.Source = new BitmapImage(new Uri(string.Format("https://graph.facebook.com/{0}/picture", me.id)));

                                        ProfileName.Text = "Hi " + me.name;
                                        FirstName.Text = "First Name: " + me.first_name;
                                        LastName.Text = "Last Name: " + me.last_name;
                                    });
                            }
                            else
                            {
                                Dispatcher.BeginInvoke(() => MessageBox.Show(e.Error.Message));
                            }
                        };
fb.GetAsync("me");

Here is the same code in Silverlight 5 using Task Parallel Library. (the above code will continue to work in Silverlight 5 without any changes to your existing Silverlight 4 code base.)

private TaskScheduler _ui;
private FacebookClient _fb;

public MainPage()
{
    InitializeComponent();

    _ui = TaskScheduler.FromCurrentSynchronizationContext();
    _fb = new FacebookClient("access_token");

    WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
}

private void GraphApiGetExample()
{
    _fb.GetTaskAsync("me").ContinueWith(
        t =>
        {
            if (t.IsFaulted)
            {
                MessageBox.Show(t.Exception.GetBaseException().Message);
                return;
            }

            dynamic me = t.Result;
            picProfile.Source = new BitmapImage(new Uri(string.Format("https://graph.facebook.com/{0}/picture", me.id)));

            ProfileName.Text = "Hi " + me.name;
            FirstName.Text = "First Name: " + me.first_name;
            LastName.Text = "Last Name: " + me.last_name;

        }, _ui);
}

We have added XTaskAsync methods in FacebookClient and FacebookOAuthClient so you can start taking advantage of TPL in silverlight 5. In this example we are making using of TaskScheduler so we can get rid of Dispatcher.BeginInvoke method. These will make your code cleaner and more maintainable. Another advantage of using TPL is that you can call multiple XTaskAsync methods on the same FacebookClient instance and it will call the callback (ContinueWith) correctly.

There are bunch of goodness in using Facebook Client with TPL, but rather then repeating I would recommend you to read my previous post on What’s New in v5.3 which talks in details about TPL in Facebook C# SDK.

Most of you by now might have got the hands on Visual Studio 11 Developer Preview and have been playing around with the new async/await features of .net 4.5. If you have been following me on twitter @prabirshrestha, you might have noticed that I had posted a sample library called “Facebook.Extensions.Task” in github earlier this year for those who wanted to play with the Async CTP. The good news is that starting with v5.3, async/await is now a first class citizen.

Some you might feel reluctant to update to a developer preview of .net 4.5 to use these new features. Well, you guys are not out of luck. Since Task Parallel Library is supported in .net 4.0 you guys can start playing with it now.

You can checkout the sample called “CS-WinForms-AsyncAwait.sln” which demonstrates the usage of async in Graph Api, Legacy Rest Api, Fql, Fql multi-query and even progress and cancellation support.

Moving to Asynchronous methods with Async/Await

Here is the hello world of Facebook. First using the synchronous method.

private void GraphApiExample()
{
	try
	{
		var fb = new FacebookClient();
		dynamic result = fb.Get("4");
		string name = result.name;
		Console.WriteLine(name);
	}
	catch (FacebookApiException ex)
	{
		Console.WriteLine(ex.Message);
	}
}

And here is the async equivalent method.

async private void GraphApiAsyncExample()
{
	try
	{
		var fb = new FacebookClient();
		dynamic result = await fb.GetTaskAsync("4");
		string name = result.name;
		Console.WriteLine(name);
	}
	catch (FacebookApiException ex)
	{
		Console.WriteLine(ex.Message);
	}
}

Only 3 simple changes required to convert synchronous method to asynchronous methods.

  1. add “async” keyword in the method.
  2. change fb.Get() to fb.GetTaskAsync()
  3. add await before fb.GetTaskAsync() methods.

The best part is that your workflow for async methods will now remain same as in synchronous methods with no callbacks. Handling exceptions just got easier for async methods.

(There are tons of new interesting stuffs you can do with async. In the upcoming days and weeks, I will be blogging more on this. In the mean time you can see all the features in “CS-WinForms-AsyncAwait.sln” sample.

Multiple async calls on the same FacebookClient instance

One of the common complains we have received from the folks who use Async methods was that they need to create a new instance of FacebookClient for each different async method calls. Though this is by design, we have improved it for XTaskAsync methods. Now you can call TaskAsync methods on the same instance of FacebookClient. (In order to maintain backward compatibility, XAsync() methods will still require new instance while XTaskAsync() won’t.)

This is now possible staring from v5.3

async private void GraphApiAsyncExample()
{
	var fb = new FacebookClient();
	dynamic result1 = await fb.GetTaskAsync("4");
	dynamic result2 = await fb.GetTaskAsync("5");
}

CancellationToken support

With the introduction of CancellationToken in .net 4.0 with Task Parallel Library, we now have a unified way to cancel a Task in .net.

You will need to add an extract catch block to handle OperationCancelledException. Here is a sample code showing how to cancel a Facebook request.

CancellationTokenSource _cts;

async private void btnUpload_Click(object sender, EventArgs e)
{	
	try
	{
		_cts = new CancellationTokenSource();
		
		var fb = new FacebookClient();
		dynamic parameters = new ExpandoObject();
		// code emited for brevity.
		dynamic result = await fb.PostTaskAsync("me/videos", parameters, _cts.Token);
	}
	catch(FacebookApiException ex)
	{
		MessageBox.Show(ex.Message);
	}
	catch(OperationCanceledException ex)
	{
		MessageBox.Show("Upload Cancelled");
	}
}

private void btnCancel_Click(object sender, EventArgs e)
{
	if (_cts != null)
		_cts.Cancel();
}

Note: Unlike XAsync() event based async methods, you shouldn’t call CancelAsync method to cancel the XTaskAsync methods, but rather use the CancellationToken.

Since XTaskAsync methods can execute on the same instance of FacebookClient you can either use the same cancellation token or different cancellation token depending on your requirements.

Upload Progress Reporting

If you are using .net 4.0 you will need to continue using UploadProgressChanged event handler as described in http://blog.prabir.me/post/Facebook-CSharp-SDK-Upload-Progress.aspx

But if you are using .net 4.5 you can use the new methods that were introduced to simplify the asynchrony in .net 4.5 using IProgress<T>.

Here is the sample showing the usage of both cancellation and upload progress reporting.

CancellationTokenSource _cts;

async private void CancellationAndProgressSupport()
{	
	try
	{
		_cts = new CancellationTokenSource();
		
		var fb = new FacebookClient();
		dynamic parameters = new ExpandoObject();
		// code emited for brevity.
		
		var uploadProgress = new Progress<FacebookUploadProgressChangedEventArgs>();
		uploadProgress.ProgressChanged += (o, args) => progressBar1.Value = args.ProgressPercentage;
		
		dynamic result = await fb.PostTaskAsync("me/videos", parameters, null, _cts.Token, uploadProgress);
	}
	catch(FacebookApiException ex)
	{
		MessageBox.Show(ex.Message);
	}
	catch(OperationCanceledException ex)
	{
		MessageBox.Show("Upload Cancelled");
	}
}

private void btnCancel_Click(object sender, EventArgs e)
{
	if (_cts != null)
		_cts.Cancel();
}

There are new overload methods for BatchTaskAsync and PostTaskAsync that includes IProgress<FacebookUploadProgressChangedEventArgs> as a parameter.

What about my investments in event based XAsync() methods?

No worries. We have no plans to remove them and will remain there although XTaskAsync() methods would be the recommended way to go. (Internally XTaskAsync methods actually makes use of XAsync methods. This also means that any patch applied to .net 3.5 will also be propagated to .net 4.5 builds. In the near future I will blog about how to convert your old event based apis to use the new Task Parallel Library features.)

If you are still using the FacebookApp class which was marked [Obsolete], make sure to change it to FacebookClient/FacebookWebClient as we are now removing it from .net 4.5 builds although it will still be available for .net 3.5 and .net 4.0 builds.

Asynchrony with ASP.NET MVC4

Internally since Facebook.Web.Mvc.dll in .net 4.5 build does not use any new features of MVC4, it still references MVC3. A binding redirect in web.config is enough to tell Facebook.Web.Mvc.dll to use MVC4.

With ASP.NET MVC 4, you can now execute asynchronous methods easily inside of MVC Actions.

[AsyncTimeout(2500)]
[HandleError(ExceptionType = typeof(TaskCanceledException), View = "TimedOut")]
[FacebookAuthorize(Permissions = ExtendedPermissions, LoginUrl = "/Account/LogOn?ReturnUrl=~/")]
async public Task<ActionResult> Index()
{
	dynamic result = await _fb.GetTaskAsync("me");
	ViewBag.me = result;

	return View();
}

Attributes will continue using the synchronous methods, while you can call the asynchronous versions inside the Action. You can also add a default time out using AsyncTimeout action filter which is part of ASP.NET MVC. Incase the action times out, you can handle the error using HandleError action filter which is again a part of ASP.NET MVC.

FQL using Graph Api

Facebook recently supported issuing FQL queries using the Graph Api. Starting from v5.3 the Facebook C# SDK will be using the Graph Api instead of Legacy Rest Api to perform fql queries.

Here is how you would execute the query method in Graph Api without using Query helper methods.

var fb = new FacebookClient("access_token");
dynamic parameters = new ExpandoObject();
parameters.q = "SELECT name, uid FROM user WHERE uid = me()";
dynamic result = fb.Get("fql", parameters);
Console.WriteLine(result);

You would then get a result which looks similar to this:

{"data":[{"name":"Prabir Shrestha","uid":123456}]}

There are two stuffs to notice from using the legacy rest api.

  1. The result is wrapped in “data”
  2. uid is of type long instead of string

But if you execute the FQL methods using the Query() method as below.

var fb = new FacebookClient("access_token");
dynamic result = fb.Query("SELECT name, uid FROM user WHERE uid = me()");
Console.WriteLine(result);

It will remove “data” and return the value of data in order to maintain compatibility with previous versions of the sdk. The result will now look as follows:

[{"name":"Prabir Shrestha","uid":123456}]

If you use Query() methods make sure you handle the type of the ids correctly. It is same for multi-query – “data” is automatically removed. Make sure to handle this breaking change when updating to v5.3.

Removed dependency from CodeContracts

Though code contracts is an awesome tool, we have decided to remove it due to lack of early support for new releases of Visual Studio/ .net Framework.

Channel.html

There will be a new nuget package called “Facebook.channel” which will contain the channel file for Facebook Javascript SDK. (Facebook.xd_receiver will no longer be maintained.) You can read more about the channel file at https://developers.facebook.com/docs/reference/javascript/. In short, channel file address some issues with cross domain communication in certain browsers. Since this is a beta release it is not yet available from nuget.org. You will need to manually add it from “Build\NuGet\Facebook.channel\Content\fbchannel.ashx.pp”

You can then initialize the Facebook Javascript SDK using the following code.

<div id="fb-root"></div>
<div class="fb-login-button" data-show-faces="true" data-width="200" data-max-rows="1" perms="user_about_me"></div>
<script type="text/javascript">
    window.fbAsyncInit = function () {
        FB.init({ appId: '@Facebook.FacebookApplication.Current.AppId', channelURL: '@Request.Url.Scheme://@Request.Url.Authority@Url.Content("~/fbchannel.ashx")', cookie: true, xfbml: true, oauth: true });
        FB.Event.subscribe('auth.login', function (response) { window.location.reload(); });
        FB.Event.subscribe('auth.logout', function (response) { window.location.reload(); });
    };

    (function(d){
        var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
        js = d.createElement('script'); js.id = id; js.async = true;
        js.src = "//connect.facebook.net/en_US/all.js";
        d.getElementsByTagName('head')[0].appendChild(js);
    }(document));
</script>

The above code is taken from Facebook.JavascriptMvcWebsite nuget package. It loads the Facebook Javascript SDK asynchronously and also uses the new HTML 5 Facebook login button instead of XFBML. (https://developers.facebook.com/docs/reference/plugins/login/). The Javascript SDK is also initialized with the channelURL.

New OpenGraph Samples

We have also added a new Sample called “CS-AspNetMvc3-JsSdk-OpenGraph.sln” demonstrating the use of Open Graph based on the PHP sample https://developers.facebook.com/blog/post/564/ with slight modifications.

New OAuth 2.0 sample with FormsAuthentication

Another new sample called “CS-AspNetMvc3-WithoutJsSdk.sln” has been added which demonstrates the use of OAuth 2.0 with ASP.NET Forms Authentication. The sample also includes prevention of Cross Site Request Forgery (CSRF) attacks and Open Redirection Attack during login.

(Since .net 4.5 is in Developer Preview status, we will not be distributing the compiled binaries. You will need to grab the source code and build it manually.)

Though this release updates the minor version number there are tons of new cool features. Make sure to read the CHANGES.txt before updating.

If you want to catch up with the latest updates make sure to like us on our official Facebook Page - https://www.facebook.com/csharpsdk or follow us on twitter at @csharpsdk

This blog post is gonna be all about codes and how you can use FacebookClient class to make synchronous requests to the Facebook server. But first …

The basics

To access most of the protected resource in Facebook, you require access token. You can read more about it on how to get the access token in this post.

Install-Package Facebook

Graph Api (GET)

var fb = new FacebookClient();

var result = (IDictionary<string,object>)fb.Get("4");

var id = (string)result["id"];
var name = (string)result["name"];
var firstName = (string)result["first_name"];
var lastName = (string)result["last_name"];
var link = (string)result["link"];
var username = (string)result["username"];
var gender = (string)result["gender"];
var male = (string)result["locale"];

Passing Parameters

var fb = new FacebookClient();

var parameters = new Dictionary<string, object>();
parameters["fields"] = "id,name";

var result = (IDictionary<string, object>)fb.Get("4", parameters);
var id = (string)result["id"];
var name = (string)result["name"];

Note:

  • Cast to IDictionary<string, object> if it is a json object,
  • Cast to IList<object> if it is is a json array,
  • Cast to string, long, double or boolean accordingly depending on the json primitive types, or
  • use dynamic without explicitly casting. (supported only in frameworks where dynamic keyword is supported.)

Using dynamic

var fb = new FacebookClient();

dynamic result = fb.Get("4");

var id = result.id;
var name = result.name;
var firstName = result.first_name;
var lastName = result.last_name;
var link = result.link;
var username = result.username;
var gender = result.gender;
var male = result.locale;

Passing parameters the dynamic way.

(Use ExpandoObject instead of IDictionary<string, object>)

var fb = new FacebookClient();

dynamic parameters = new ExpandoObject();
parameters.fields = "id,name";

dynamic result = fb.Get("4", parameters);
var id = result.id;
var name = result.name;

Graph Api (POST)

var fb = new FacebookClient("access_token");

dynamic parameters = new ExpandoObject();
parameters.message = "Hello World!"

dynamic result = fb.Post("me/feed", parameters);
var id = result.id;

Graph Api (DELETE)

var fb = new FacebookClient("access_token");

dynamic result = fb.Delete(id);

Legacy REST API

Unlike graph api, you need to only pass parameters and make sure you set the “method” in the parameter.

var fb = new FacebookClient();

dynamic parameters = new ExpandoObject();
parameters.method = "users.getInfo";
parameters.uids = "4";
parameters.fields = new[] { "name", "first_name", "last_name" };

dynamic result = fb.Get(parameters);

FQL

var fb = new FacebookClient();

string query = string.Format("SELECT name FROM user WHERE uid='{0}'", 4);
dynamic result = fb.Query(query);

FQL-MultiQuery

var fb = new FacebookClient();

string query0 = string.Format("SELECT first_name FROM user WHERE uid='{0}'", "4");
string query1 = string.Format("SELECT last_name FROM user WHERE uid='{0}'", "4"); ;

dynamic result = fb.Query(query0, query1);
var result0 = result[0].fql_result_set;
var result1 = result[0].fql_result_set;

Batch Requests

Well … this one requires a whole new blog post. So here it goes

Getting user profile picture

Lot of devs have been asking how to retrieve the user profile picture. You don’t need to use FacebookClient to retrieve the picture. Just get the user id and generate the url for the picture.

string profilePictureUrl = string.Format("https://graph.facebook.com/{0}/picture", user_id);

Using Access Token

Most of the above samples were shown without using the access token, but most of the api requests requires using the access token. You can set the access token in the following ways.

var fb = new FacebookClient("access_token");

or you could also use the AccessToken property.

var fb = new FacebookClient();
fb.AccessToken = "access_token";

Using Application Access Token

There are times when you need to use the application access token instead of the user access token.

var oauthClient = new FacebookOAuthClient
                        {
                            AppId = "app_id",
                            AppSecret = "app_secret"
                        };
						
dynamic result = oauthClient.GetApplicationAccessToken();
string appAccessToken = result.access_token;

or you could also use the application access token as

string appAccessToken = string.Concat(appId, "|", appSecret);

or use the overload constructor of FacebookClient. The below code also sets the app access token automatically for you using the above method.

var fb = new FacebookClient("app_id", "app_secret");

OAuth 2.0 -  exchange code for access token

FacebookClient supports parsing only json responses. Due to this reason “oauth/access_token” token will not work when using FacebookClient.Get(“oauth/access_token”). Instead you will need to use a method in FacebookOAuthClient.

var oauthClient = new FacebookOAuthClient
                        {
                            AppId = "app_id",
                            AppSecret = "app_secret",
                            RedirectUri = new Uri("http://redirecturi.com")
                        };
						
dynamic result = oauthClient.ExchangeCodeForAccessToken("code");
var accessToken = result.access_token;

Handling Exceptions

If you want to create apps that are error free, make sure to catch exceptions that are thrown when you make requests to the facebook server.

try
{
    var fb = new FacebookClient();
    dynamic result = fb.Get("4");
    var name = result.name;
}
catch (FacebookApiException ex)
{
}
catch (Exception ex)
{
}

You could also catch more generic FacebookApiException and take actions accordingly.

try
{
    var fb = new FacebookClient();
    dynamic result = fb.Get("4");
    var name = result.name;
}
catch (FacebookApiLimitException ex)
{
}
catch (FacebookOAuthException ex)
{
}
catch (FacebookApiException ex)
{
}
catch (Exception ex)
{
}

v5.2 is out and its all about support for the new Javascript SDK with OAuth 2.0 enabled and the best part of it is that you require no server side changes to your existing code. Just update Facebook C# SDK to v5.2 and set oauth:true in your Javascript and it works out of the box.

Before you start typing “Update-Package FacebookWeb” here are some internals that you should be aware of.

1. Support for Javascript SDK with OAuth 2.0 enabled

First of all make sure you have enabled oauth during FB.init. You can read more on this at https://developers.facebook.com/blog/post/525/ (If you would like to continue using the Javascript SDK without oauth support, it is fine too as v5.2 still supports the old cookie format.)

FB.init({
   appId : YOUR_APP_ID,
   // other parameters,
   oauth : true
});

First difference internally is to understand the new cookie format used. The old Javascript SDK or the new Javascript SDK with oauth disabled, sets the cookie name as “fbs_<app_id>” while the new Javascript SDK uses “fbsr_<app_id>” when the user authorizes your app. Internally Facebook C# SDK checks for the new “fbsr_<app_id>” cookie first, if found it creates the session from the specified cookie else reverts back to the old “fbs_<app_id>” cookie. This way your existing code still works with oauth disabled, so no fear when updating your existing codes to v5.2.

Here is a big difference with the old and the new cookie. The new cookie doesn’t contain the access token but rather contains only code, which you can then exchange for access token. But Facebook C# SDK makes your life easier. Whenever you call the AccessToken property in the FacebookSession, the SDK is smart enough to retrieve the access token automatically for you if it hasn’t been set yet.

Here is a sample code on how it exchanges code the access token. Notice that it use FacebookApplication.Current to get the app_id and app_secret, so make sure to set the correct FacebookApplication either programmatically or using web.config file.

var oauthClient = new FacebookOAuthClient(FacebookApplication.Current);

var parameters = new Dictionary<string ,object>();
parameters["redirect_uri"] = null;

dynamic result = oauthClient.ExchangeCodeForAccessToken(code, parameters);

Make sure you set the redirect_uri as null in parameters and not oauthClient.RedirectUri = null; This is to maintain backward compatibility as redirect_uri is set to “http://www.facebook.com/connect/login_success.html” if oauthClient.RedirectUri is null.

FacebookSession is cached per request for optimal performance. This means it will call ExchangeCodeForAccessToken only once for the particular request as you can see the traffic in fiddler for the sample “CS-AspNetMvc3-JsSdk”.

image

This allows you to continue using your existing code without any changes even when oauth 2.0 is enabled in the new Javascript SDK.

[FacebookAuthorize]
public ActionResult Index()
{
    var fb = new FacebookWebClient();
    dynamic me = fb.Get("me");
    ViewBag.me = me;
    return View();
}

2. New Samples

All the samples have been rewritten with detailed comments and instructions. This will help you get started. You can now click “build.cmd” from the source code to build the dll files and then run the sample solution files. (Please do not use build.cmd to build dll files and use it in production, the recommend way is still to use rake. build.cmd is meant for samples only without installing ruby and rake.)

Even though you may be a web developer or silverlight or windows phone 7 developer make sure to check out “CS-WinForms.sln” samples. It includes samples showing graph api, legacy rest api, fql, fql muti-query and batch requests in both synchronous and asynchronous way.

There are a bunch of new changes in v5.2. Make sure to read CHANGES.txt for more details before updating.