Facebook C# SDK - Batch Requests

Recently Facebook announced support for Batch Requests in Graph API which allows developers to combine multiple requests into one HTTP request. Soon after the blog announcement on Batch Requests we had posted a temporary solution to make a batch request using older versions of the Facebook C# SDK at codeplex discussion.

As promised starting from v5.0.8, Facebook C# SDK now supports Batch Requests as first class citizens using the Batch() and BatchAsync() methods present in the FacebookClient class. In addition to these methods we have also introduced a new class called FacebookBatchParameter which will make creating batch requests easier.

public object Batch(params FacebookBatchParameter[] batchParameters);
public void BatchAsync(FacebookBatchParameter[] batchParameters, object userToken);
public void BatchAsync(FacebookBatchParameter[] batchParameters);

The FacebookBatchParameter contains 3 main properties called HttpMethod, Path and Parameters which can either be set using the constructors or object initializers (which ever you feel comfortable with).

Here is a sample on how to make a batch request.

var fb = new FacebookClient(accessToken);
var result = fb.Batch(
  new FacebookBatchParameter { HttpMethod = HttpMethod.Get, Path = "/4" },
  new FacebookBatchParameter(HttpMethod.Get, "/me/friend", new Dictionary<string, object> { { "limit", 10 } }),
  new FacebookBatchParameter("/me/friends", new { limit = 1 }) { Data = new { name = "one-friend", omit_response_on_success = false } },
  new FacebookBatchParameter { Parameters = new { ids = "{result=one-friend:$.data.0.id}" } },
  new FacebookBatchParameter("{result=one-friend:$.data.0.id}/feed", new { limit = 5 }),
  new FacebookBatchParameter(HttpMethod.Post, "/me/feed", new { message = "test status update" }),
  new FacebookBatchParameter().Query("SELECT name FROM user WHERE uid="),
  new FacebookBatchParameter().Query(
    "SELECT first_name FROM user WHERE uid=me()",
    "SELECT last_name FROM user WHERE uid=me()"));

If you need to set parameters besides HttpMethod, Path or Parameter you can set it by using the “Data” property as show in third batch parameter where the name and omit_response_on_success is set.

new FacebookBatchParameter("/me/friends", new { limit = 1 }) { Data = new { name = "one-friend", omit_response_on_success = false } }

To make the code more readable, it also support anonymous object as parameters besides IDictionary<string,object>.

Since Batch Parameter supports FQL, we have created helper methods called Query which allows you to easily write a FQL whether it is a single query or multi-query.

Facebook C# SDK also support async version of batch requests by using the BatchAsync method. Asynchronous version is very similar to the synchronous version. (Since batch request is actually a POST request, PostCompleted will be triggered when the async batch request is completed.)

fb.PostCompleted += (o, e) =>
{
  if (e.Error == null)
  {
    var result = e.GetResultData();
  }
};


fb.BatchAsync(new[]
{
  new FacebookBatchParameter {HttpMethod = HttpMethod.Get, Path = "/4"},
  new FacebookBatchParameter(HttpMethod.Get, "/me/friend",new Dictionary<string, object> {{"limit", 10}}),
  new FacebookBatchParameter("/me/friends", new {limit = 1}){Data = new {name = "one-friend", omit_response_on_success = false}},
  new FacebookBatchParameter{Parameters = new {ids = "{result=one-friend:$.data.0.id}"}},
  new FacebookBatchParameter("{result=one-friend:$.data.0.id}/feed", new {limit = 5}),
  new FacebookBatchParameter(HttpMethod.Post, "/me/feed", new { message = "test status update" }),
  new FacebookBatchParameter().Query("SELECT name FROM user WHERE uid="),
  new FacebookBatchParameter().Query(
    "SELECT first_name FROM user WHERE uid=me()",
    "SELECT last_name FROM user WHERE uid=me()")
});

The result returned by a synchronous Batch() method or GetResultData() incase of BatchAsync() is not the exact json result which includes http status code, http headers and the body. The Facebook C# SDK modifies the result and returns IList<object> where the object is either the body or a FacebookApiException. This makes checking for error easier.

If you have 8 batch requests the count of the result would be 8. You can access the particular result using indexers.

var resultList = (IList<object>)result;
var count = resultList.Count; // count == 8
var result0 = resultList[0];
var result1 = resultList[1];
......
var result7 = resultList[7];

There are possibilities for an exception to occur only for a particular request. So make sure to always check that there was no exception for it before processing the result.

if (result0 is Exception)
{
  DoSomethingWithException(result0);
}
else
{
  dynamic user = result0;
  var id = user.id;
  var name = user.name;
}

You can then process the result the same way as you would process it for normal GET,POST,or DELETE method.

Note: The only feature not supported by the Facebook C# SDK on Batch Requests in uploading binary data.

The generic GetResultData<T>() is not supported for Batch Requests.

FacebookCSharpSDK-BatchRequests.zip (670.24 kb)