c#

Integrating Facebook C# SDK & Neo4J

Force-Directed Graph

Hello Everyone!! This is my first tutorial and it’s going to be a long one. Bear with me on this because once you’re done with it you would be familiar with various concepts related to totally different platforms, namely, Facebook SDK, ASP.Net with C# and Neo4J Graph DB. Before getting started let us go through the use-case and how are we going to achieve it. Our objective today is to retrieve a logged-in user’s data from Facebook using Facebook SDK for .Net, prepare the retrieved data for storing it in Neo4J Graph DB and then finally visualize that data graphically.

So much for the brief introduction, let’s get down to business. First of all you need to have Visual Studio 2010 or higher installed on your system. You will also need to have Neo4J setup on your system. The download page contains multiple options, go for community version with stable release, i.e. Ne04J 2.0.3. The website contains detailed instructions and tutorials for understanding the basic concepts of graph database. Neo4J uses a special query language, called Cypher . Cypher is a declarative graph query language that allows for expressive and efficient querying and updating of the graph store. Cypher is a relatively simple but still very powerful language. Very complicated database queries can easily be expressed through Cypher. This link provides a detailed explanation and features of Cypher.

Creating a Facebook Application

Before we begin using the Facebook SDK for .NET we must create a Facebook application. To do so navigate to http://developers.facebook.com/apps and click the ‘Create New App’ button. Follow the steps to create an app and note down your AppId for future use.

Installation

Facebook does not provide its own SDK for .NET but allows a third-party SDK for C#. You can find it here. The best way for getting started with Facebook SDK for .NET is to install it using NuGet. You can download it from nuget.org. Use the latest version because the features used in the Facebook SDK for .NET will not work with older versions of NuGet. The NuGet website contains detailed instructions on how to integrate it with Visual Studio. Note: It requires VS 2010 or higher.

Managing Facebook NuGet Package

Create a new ASP.NET Empty Web Site. Name it something appropriate. To add the package to your project right click on the reference folder and select ‘Manage Nuget Packages…’. Search for the package titled ‘Facebook’, select & install it. manage_nuget_packages

Configuring Facebook SDK for .NET

The only setting we need to change is the ‘Site URL’ under the ‘Website’ settings. The Site URL must match the URL you are using for local development. Set this URL to http://localhost:#### where #### is the port you are using for local development. NOTE: There is a bug in the Facebook JavaScript SDK that prevents you from performing logins when running on non-standard ports on localhost in Internet Explorer. You must either use port 80 or test this in a browser other than Internet Explorer.

Making Your First Request

Facebook SDK for .NET makes it very easy to retrieve data from Facebook Graph API. Create a new WebForm inside your website. Let it be called Default.aspx. Open Default.aspx.cs, include the reference by adding

using Facebook;

The following code shows how to call Graph API to retrieve Bishwajeet Kumar’s public information.

var client = new FacebookClient();
dynamic me = client.Get("msg.bishwajeet.kumar");

The result returned by the Get() method is a dynamic object which contains properties like first_name, last_name, user name, id, link, gender, etc. You can view the result of this request by navigating to http://graph.facebook.com/msg.bishwajeet.kumar in your browser. The JSON output is given below.

{
   id: "100000735276467",
   first_name: "Bishwajeet",
   gender: "male",
   last_name: "Kumar",
   link: "https://www.facebook.com/msg.bishwajeet.kumar",
   locale: "en_US",
   name: "Bishwajeet Kumar",
   username: "msg.bishwajeet.kumar"
}

C#’s dynamic objects come really handy in this scenario.

dynamic me = client.Get("msg.bishwajeet.kumar");
string firstName = me.first_name;
string lastName = me.last_name;

I have used C# dynamic object in the above code. A dynamic object is an object that is evaluated only at run-time. It can be actually assumed to be a Dictionary<string, object>.

Accessing User Information

Its time to do something interesting now. We already saw how to make a request for public information using Facebook SDK for .NET. Not all the information of the user is made public. In order to access any information that is not public such as user’s likes, profile details, friend list, or Time Line posts we need to provide a valid access token when making the request.

Obtaining an Access Token

For the purpose of security, Facebook provides Access Tokens for uniquely identifying users. The Access Token changes dynamically every hour, or so. We are going to start by obtaining an access token from Facebook’s Graph API tool. You can easily find the tool at https://developers.facebook.com/tools/accesstoken/.

Retrieving User Data

Since we have obtained an access token, we can make request for user’s private data. Do keep in mind that since we did not request any special permission, we will not be able to access most of the user’s data. We will be discussing about the special permissions later.

var accessToken = "place your access token here";
var client = new FacebookClient(accessToken);
dynamic me = client.Get("me");
string myDetails = me.about;

Note: “me” is a special variable that indicates that we are making the request in the context of the user who’s access token was provided in the above request.

We will be using the above technique for all kinds of requests, such as, friend lists, likes, Timeline posts and many more. However, the type of data you wish to request from the user depends upon the type of permission you have requested from the user. For further details regarding permissions, feel free to browse https://developers.facebook.com/docs/facebook-login/permissions/v2.0#permissions.

Obtaining Access Token from Facebook

As already discussed, Facebook does not discloses user’s credentials, instead it allows you to obtain access tokens for the user to access your application. The access token includes the type of permission you have the request from the user.

In order to obtain an access token from the user, we must present them with an authentication dialog. This dialog varies depending on the device for which your application is built. Regardless of the device choices we are actually presenting the user with a Facebook login page.

Requesting an Access Token from a Website

In order to get an access token from your users on a website you must use the either the Facebook JavaScript SDK or perform what is called Server Flow Authentication. In this tutorial we will use the Facebook JavaScript SDK to perform authentication. The Facebook JavaScript SDK will handle all the details of displaying the login dialog, requesting permissions, and parsing the authentication cookie for the access token.

Adding the Facebook JavaScript SDK to Your Site

Add the following code right after the <body> tag on your web page.

<script>
        window.fbAsyncInit = function () {
            FB.init({
                appId: 'YOUR_APP_ID', // AppID goes here
                status: true, // check login status
                cookie: true, // enable cookies to allow server to access session
                xfbml: true, // parse XFBML
                version: 'v2.0' //Graph API version
            });

        // Initialization code goes here
        };

        // Load SDK Asynchronously
        (function (d, s, id) {
            var js, fjs = d.getElementsByTagName(s)[0];
            if (d.getElementById(id)) { return; }
            js = d.createElement(s); js.id = id;
            js.src = "//connect.facebook.net/en_US/all.js";
            fjs.parentNode.insertBefore(js, fjs);
        } (document, 'script', 'facebook-jssdk'));
</script>

Don’t forget to set the appId variable equal to the AppID of the Facebook application you created at the beginning of this tutorial.

Authenticating a User

We now have Facebook JavaScript SDK installed on our application. It’s time to create a Facebook Login button and place it on our web page. Add the highlighted code in your webpage.

</pre>
<form id="form1">
<div class="fb-login-button" data-send="true" data-width="600" data-show-faces="true" data-max-rows="5"></div>
</form>
<pre>

After the user has authenticated and authorized our application, we need to obtain the access token. For this we need to add the below JavaScript immediately after the // Additional initialization code goes here comment in the JavaScript we added earlier.

FB.Event.subscribe('auth.authResponseChange', function(response) {
    if (response.status === 'connected') {
        // the user is logged in and has authenticated your
        // app, and response.authResponse supplies
        // the user's ID, a valid access token, a signed
        // request, and the time the access token
        // and signed request each expire
        var uid = response.authResponse.userID;
        var accessToken = response.authResponse.accessToken;

        // TODO: Handle the access token here

    } else if (response.status === 'not_authorized') {
        // the user is logged in to Facebook,
        // but has not authenticated your app
    } else {
        // the user isn't logged in to Facebook.
    }
});

After obtaining the access token, we need to send it to the server. There are multiple ways of doing this but the easiest way is to perform an HTTP POST with the access token and redirect our user to a new page. Once we obtain the token from the server, the easiest way is to store it in the Session State and letASP.NET play with it. In order to do this place the below client-side JavaScript just after the // TODO: Handle the access token here comment in the previous step.

// Do a post to the server to finish the logon
var form = document.createElement("form");
form.setAttribute("method", 'post');
form.setAttribute("action", 'http://localhost:xxxx/MyFacebookApp/FacebookLogin.ashx');

var field = document.createElement("input");
field.setAttribute("type", "hidden");
field.setAttribute("name", 'accessToken');
field.setAttribute("value", accessToken);
form.appendChild(field);

document.body.appendChild(form);
form.submit();

Next step is to create a handler to receive the token and redirect the user. W’ll be using a Generic Handler to this. Create a new Generic Handler by right clicking on your project in Visual Studio >> Add New Item >> Select ‘Generic Handler’ from this list. Name it “FacebookLogin.ashx”.

public class FacebookLogin : IHttpHandler, System.Web.SessionState.IRequiresSessionState {

    public void ProcessRequest(HttpContext context) {
        var accessToken = context.Request["accessToken"];
        context.Session["AccessToken"] = accessToken;

        context.Response.Redirect("http://localhost:xxxx/MyFacebookApp/UserDetails.aspx");
    }

    public bool IsReusable {
        get { return false; }
    }
}

Using the Access Token

Now that we have successfully saved the access token to the session state we can make requests on behalf of that user when they are browsing our site.

var accessToken = Session["AccessToken"].ToString();
var client = new FacebookClient(accessToken);
dynamic result = client.Get("me", new { fields = "name, id, birthday" });
string name = result.name;
string id = result.id;
DateTime birthday = DateTime.Parse(result.birthday);

We are more concerned over determining the various likes of the user and their categories. Facebook Developer page provides Graph API Explorer tool for trying out your Get() requests. It’s always a good practice to verify and perfect your requests before incorporating in your application.

For our application, we will be making two Get() requests. One, for getting the basic details of the logged-in user, and the second for retrieving the likes of the user. Add the following code in your UserDetails.aspx.cs page.

var accessToken = Session["AccessToken"].ToString();
var client = new FacebookClient(accessToken);

dynamic myInfo = client.Get("me/", new { fields = "id, birthday, name" });
dynamic myLikes = client.Get("me/likes?limit=150", new { fields = "category, name, created_time, id" });

Notice the limit modifier in the above request. By default, Facebook Graph API returns only 25 results. In order to retrieve more results we use the limit modifier and provide the number of results you want to get. The result returned by the second request is of the following structure.

{
  "data": [
    {
      "category": "Computers/internet website",
      "name": "Android and Me",
      "created_time": "2014-01-22T20:48:53+0000",
      "id": "115561868082"
    },
    {
      "category": "School",
      "category_list": [
        {
          "id": "365182493518892",
          "name": "School"
        }
      ],
      "name": "St. Karen's High School",
      "created_time": "2013-10-30T16:55:31+0000",
      "id": "461179170627960"
    },
    {
      "category": "Musician/band",
      "name": "Deep Purple (1968-1976)",
      "created_time": "2013-09-25T15:41:11+0000",
      "id": "192121640808384"
    },
    {
      "category": "Tv show",
      "name": "The Simpsons",
      "created_time": "2013-09-24T16:10:49+0000",
      "id": "29534858696"
    }
  ]
}

The result above was returned as dynamic array which has been converted to JSON format and then Serialized to give it structure with intended formatting.

Since we have retrieved the data which we wanted, it’s time to address the elephant in the room. Yes, creating Nodes & Relationships, storing, indexing and retrieving data using Neo4J Graph Database.


Unless you want to be bleeding edge, it’s recommended to download the Major Stable Community Version. Make sure to get the Windows specific download. Follow the directions on the download page and open up a command prompt with administrator privileges to start your newly installed Neo4j server. Once you have started the server, you can browse to your web admin interface at http://localhost:7474. From there, you can use the Data browser page to create nodes and relationships. In the console tab, you can query your database using Cypher or traverse the graph using Gremlin. You can even send HTTP requests to the REST API if you want to learn about how to talk to Neo4j from other tools. In the Indexes tab, you can create indexes for fast retrieval of nodes or relationships. I will talk more about indexes later. You are now ready to setup Neo4jClient.

As you have done earlier with Facebook Third-Party installs using NuGet; We will be installing Neo4JClient. You can install Neo4JClient by managing NuGet packages on your project or by running the following command in the Package Manager Console:

Install-Package Neo4jClient
Brief Overview of Neo4j and Neo4jClient

Indexes

Indexes are created for fast retrieval of information at a later point. This is extremely useful when querying a graph database on the order of millions of nodes. Manual traversal is slower and less efficient. One of the advantages of graph databases is speed and it is important to utilize indexes to increase speed.

Full text vs. Exact

A full text index is for searching on a node’s properties text, allowing partial or complete text to be searched. For example, if you have a set of nodes representing the Star Wars movies, if you search for nodes in the Movie index with a name like “Star Wars” with a full text index, you will get all nodes containing the text “Star Wars” in the name property.

However, an exact index requires that you search on a node’s properties text with exact text. For example, if you have a set of nodes representing the Star Wars movies, if you search for just the text “Star Wars” in an exact index, it will not return anything because there are no nodes with just the text “Star Wars”

Relationship Properties

In addition to adding properties to nodes, relationships can also have properties. This can be helpful if you are trying to better describe a relationship. If you want a more complex data model, you can add a payload class to your relationship class to store properties on your relationship. This is often referred to as attributes of a relationship in graph theory.

Once Neo4JClient is installed, we can reference it in our on-going application.

using Neo4jClient;
using Neo4jClient.Cypher;

Nodes, Relations & Indexes

Before we get down to coding we must decide on which Entities would act as a node in our graph, the relationship between them and on what your indexes would be based on. For our application, the logged-in Facebook User, his Likes and the Category of the like will be acting as Nodes.

Relationship between these entities could be formed as:

User->[interest_area]->Category-[includes]->Like

In the above two cases, interest_area and includes are the two relationships binding out three entities.

We will be creating indexes on out three entities i.e. User, Like & Category.

Now, we will be creating our three Entities and define their properties and initiate their relationships.

/// <summary>
/// Summary description for User
/// </summary>
public class User
{
    public string Id { get; set; }
    public string Birthday { get; set; }
    public string Username { get; set; }

    public User()
	{
		// TODO: Add constructor logic here
	}
}

public class Interest_Relationship : Relationship, IRelationshipAllowingSourceNode<User>, IRelationshipAllowingTargetNode<Category>
{
    public static readonly string TypeKey = "interest_area";

    public Interest_Relationship(NodeReference targetNode)
        : base(targetNode)
    { }

    public override string RelationshipTypeKey
    {
        get { return TypeKey; }
    }
}

We create similar classes for Likes and Category

/// <summary>
/// Summary description for Likes
/// </summary>
public class Likes
{
    public string Category { get; set; }
    public string Name { get; set; }
    public string Created_Time { get; set; }
    public string Id { get; set; }

    public Likes()
	{
		// TODO: Add constructor logic here
	}
}
///
/// Summary description for Category
///
public class Category
{
    public string Category_name { get; set; }

    public Category()
	{
		// TODO: Add constructor logic here
	}
}
public class Includes_Relationship : Relationship, IRelationshipAllowingSourceNode<Category>, IRelationshipAllowingTargetNode<Likes>
{
    public static readonly string TypeKey = "includes";

    public Includes_Relationship(NodeReference targetNode)
        : base(targetNode)
    { }

    public override string RelationshipTypeKey
    {
        get { return TypeKey; }
    }
}

All the above three files should reside in the App_Code folder for your website.

We now return back to our UserDetails.aspx.cs page. First off all we need to create a Graph-Context object. After creating the object we will connect to it.

GraphClient neo4jclient = new GraphClient(new Uri("http://localhost:7474/db/data"));
neo4jclient.Connect();

We will be now creating indexes on the three entities.

var accessToken = Session["AccessToken"].ToString();
var client = new FacebookClient(accessToken);

dynamic myInfo = client.Get("me/", new { fields = "id, birthday, name" });
dynamic myLikes = client.Get("me/likes?limit=150", new { fields = "category, name, created_time, id" });

GraphClient neo4jclient = new GraphClient(new Uri("http://localhost:7474/db/data"));
neo4jclient.Connect();

//Create Indexes
neo4jclient.CreateIndex("user", new IndexConfiguration() { Provider = IndexProvider.lucene, Type = IndexType.fulltext }, IndexFor.Node); // full text node index
neo4jclient.CreateIndex("like", new IndexConfiguration() { Provider = IndexProvider.lucene, Type = IndexType.exact }, IndexFor.Node); // exact node index
neo4jclient.CreateIndex("category", new IndexConfiguration() { Provider = IndexProvider.lucene, Type = IndexType.fulltext }, IndexFor.Node); // full text node index

As you can see we have created Full-Text Node Index for User and Category entities while Exact Node Index for Like entity. Scroll above to the Grey box to learn the difference.

Let’s create our nodes. First create an object on User class. Always use Cypher query to communicate with Neo4J. Analyze the code for creating a User node below and similarly create Category and Like nodes.

 //Create User Node
 User facebookUser = new User() { Id = myInfo.id, Username = myInfo.name, Birthday = myInfo.birthday };

var userRef = neo4jclient.Cypher
  .Create("(user:user {param})")
  .WithParam("param", facebookUser)
  .Return<User>("user")
  .Results
  .Single();

For creating Like nodes, iterate through the dynamic variable myLikes, returned by Facebook Graph API.

Creating Category nodes is a two-step process. If you have noticed, we do not have direct access to the Category list. We need to prepare a list containing all distinct Category types. Since we have already created Like nodes, firing a simple cypher on graph db makes it easy.

//Get Distinct Category Nodes
var resultCategory = neo4jclient.Cypher
    .Match("(likes)")
    .Where("likes:like")
    .Return<String>("DISTINCT likes.Category").Results;

Since now we do have the list of categories, we can iterate through it creating Category nodes. While iterating through the categories, we can create relationships between our three nodes. Refer the below code to do this.

//Get Distinct Category Nodes
var resultCategory = neo4jclient.Cypher
    .Match("(likes)")
    .Where("likes:like")
    .Return<String>("DISTINCT likes.Category").Results;

if (resultCategory != null)
{
    foreach (dynamic category in resultCategory)
    {
        //Creat Category Nodes
        Category likeCategory = new Category() { Category_name = category };
        var categoryNode = neo4jclient.Cypher
            .Create("(cat:category {param})")
            .WithParam("param", likeCategory)
            .Return<Category>("cat")
            .Results
            .Single();

        //Create User->Category Relationship
        neo4jclient.Cypher
            .Match("(a:user),(b:category)")
            .Where("a.Username='"+ facebookUser.Username +"' and b.Category_name='" + category + "'")
            .Create("(a)-[r:interest_area]->(b)")
            .ExecuteWithoutResults();

        //Create Category->Like Relationship
        neo4jclient.Cypher
            .Match("(a:category),(b:like)")
            .Where("a.Category_name='" + category + "' and b.Category='" + category + "'")
            .Create("(a)-[r:includes]->(b)")
            .ExecuteWithoutResults();
    }
}

Once you have followed and completed all of the above instructions, your job is nearly done. If you run your application at this moment, your webpage would not display anything because we have not yet visualized it. But having said that, if you still want to have a sneak-peek at what we have achieved so far, go to http://localhost:7474/. Click on the ‘Data Browser’ tab and fire the below cypher query.

MATCH (A:user)
RETURN A

The above cypher should return a single node. If you click on the node, you can view all its properties. Since it is a graph database you must be thinking of visualizing the data graphically. We will do it just now. After you have clicked on the node, go the top-right corner of the page. Choose the one which says “Switch to View Mode” on hovering. Clicking on it will give you a similar graph as below.

webadmin1

Clicking on the nodes will expand them, if you have configured their properties correctly. You can even create your own graph styles. Click and drag the nodes & relationships to play with them.

webadmin2

I hope this tutorial has been informative and up to your requirements. Feel free to post any comment or questions. I’ll be more than happy to help you out.

Cheers 🙂