Saturday, February 23, 2013

Integrating Facebook in ASP Website using C# SDK

If you like it or hate it, you can't get away with the fact that Facebook is present all over the web. Whether it's a complex web application or just a news blog, every site uses Facebook for driving traffic. Integrating your web app or website with Facebook is easy and free. Apart from driving traffic to your site it also makes your web site more social and tailored for the users. You can access user's data from Facebook to simplify or eliminate your own user registration process. If you have a asp.net website you can use Facebook C# SDK for integrating Facebook within your website/web application.

Creating a Facebook App
First of all we need to create an app through which the website will connect with users.
  1. Visit https://developers.facebook.com/apps and click on 'Create New App'.
  2. Fill in the desired App Name and Namespace. Remember these must be unique.
  3. On the basic settings page look for 'Select how your app integrates with Facebook' section and choose 'Website with Facebook Login'.
  4. In the Site URL field, enter your site address. I am working locally, so I added http://localhost:8779/ (Don't forget to put a trailing '/').
Note: Facebook keeps changing the developer interface. So, may be when you're reading this post you have to go through a different set of steps while a creating a new app and configuring it.
Create a new Facebook App

Facebook App Settings

Installing Facebook C# SDK

Next step is to add Facebook C# SDK to your website. Search for 'facebook' in the NuGet Package Manager. Install the latest stable release. In my case it was 6.1.4.
Facebok C# SDK NuGet

Note: Make sure you have a recent version of NuGet if not, download it from here.

Getting Started with code
I have created a simple interface with a button, two labels and a listbox.
Facebook ASP App Design
Design

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FacebookDemo.aspx.cs" Inherits="MyApp.FacebookDemo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" Text="Log in with Facebook" OnClick="Button1_Click" />
        <br />
        <asp:Label ID="Label1" runat="server" Text="Your Email"></asp:Label><br />
        <br />
        <asp:Label ID="Label2" runat="server" Text="Your Friends"></asp:Label><br />
        <asp:ListBox ID="ListBox1" runat="server" Width="200px" Height="200px"></asp:ListBox>
    </div>
    </form>
</body>
</html>

User Authentication
On the click of the button, we allow users to connect with our app and grant the necessary permissions through Facebook's OAuth dialog. For this we create a FacebookClient and through that a login URL. We have to add a few parameters in the login url:
app id,
a url to which users will be redirected,
response type,
and finally the permissions we require from the users.

 protected void Button1_Click(object sender, EventArgs e)
        {
    var loginUrl = fb.GetLoginUrl(new
                {

                    client_id = "your_app_id",

                    redirect_uri = "http://localhost:8779/FacebookDemo.aspx",

                    response_type = "code",

                    scope = "email" // Add other permissions as needed

                });
                Response.Redirect(loginUrl.AbsoluteUri);
  }

This will take the user to Facebook Login page (if already not logged in) and then to our app login dialog. A user can accept or cancel the dialog, in both cases the user will be redirected back to our page.
Facebook OAuth Dialog
OAuth Dialog

Receiving Access Token
Our very next step is to receive an access token so that we can make requests to Facebook Graph API on behalf of the user. When the user is redirected back to our website, an auth code is appended in the URL. We have to exchange that code with an access_token.

protected void Page_Load(object sender, EventArgs e)
    {
  if (Request.QueryString["code"] != null)
            {
                string accessCode = Request.QueryString["code"].ToString();

                var fb = new FacebookClient();

                // throws OAuthException 
                dynamic result = fb.Post("oauth/access_token", new
                {

                    client_id = "your_app_id",

                    client_secret = "your_app_secret",

                    redirect_uri = "http://localhost:8779/FacebookDemo.aspx",

                    code = accessCode

                });

                var accessToken = result.access_token;
              }
    }

First we extract the code from URL then we do a post request to Facebook and exchange the code for an access_token. Also, you can know the expire time for a user access token by querying response.expires which returns the number of seconds until the token expires.

Getting User Information
After getting the access token, our work is mostly simplified. Let us find user's id,name and friend list. All these come under the basic info and we don't need ask for a permission. As we asked for the permission to access email id of the user we can easily extract it along with name and id. So here's the extended codind after the previous part.
protected void Page_Load(object sender, EventArgs e)
        {
   if (Request.QueryString["code"] != null)
            {
                string accessCode = Request.QueryString["code"].ToString();

                var fb = new FacebookClient();

                // throws OAuthException 
                dynamic result = fb.Post("oauth/access_token", new
                {

                    client_id = "your_app_id",

                    client_secret = "your_app_secret",

                    redirect_uri = "http://localhost:8779/FacebookDemo.aspx",

                    code = accessCode

                });

                var accessToken = result.access_token;
                var expires = result.expires;

                // Store the access token in the session
                Session["AccessToken"] = accessToken;

                // update the facebook client with the access token 
                fb.AccessToken = accessToken;
    
                // Calling Graph API for user info
                dynamic me = fb.Get("me?fields=friends,name,email");

                string id = me.id; // You can store it in the database
                string name = me.name;
                string email = me.email;

                Label1.Text = name + "(" + email + ")";

                var friends = me.friends;

                foreach (var friend in (JsonArray)friends["data"])
                {
                    ListBox1.Items.Add((string)(((JsonObject)friend)["name"]));
                }

                Button1.Text = "Log Out"; //Changin the button text to Log Out

                FormsAuthentication.SetAuthCookie(email, false);
            }
 }

Facebook C# SDK ASP .NET
OAuthException - #100
At this moment (i.e the code is still present in the url), if you reload the page you will experience an OAuthException - #100 "This authorization code has been used.".
What's happening is, we are again exchanging the code for an access token on the page load. Facebook could return us the already generated access token but it doesn't. Rather it perceives a call to generate a new access token. You can track this Facebook bug here.
So what we could do and actually we should do is check if the user is already signed in i.e look for the session variable we stored when the user signed in. So, here's a better a page_load method.

protected void Page_Load(object sender, EventArgs e)
        {   
            // Check if already Signed In
            if (Session["AccessToken"] != null)
            {
                Label4.Text = Session["AccessToken"].ToString();

                // Retrieve user information from database if stored or else create a new FacebookClient with this accesstoken and extract data again.
                var fb = new FacebookClient(Session["AccessToken"].ToString());

                dynamic me = fb.Get("me?fields=friends,name,email");

                string email = me.email;
                Label1.Text = email;               

                var friends = me.friends;

                foreach (var friend in (JsonArray)friends["data"])
                {
                    System.Diagnostics.Debug.WriteLine((string)(((JsonObject)friend)["name"]));
                    ListBox1.Items.Add((string)(((JsonObject)friend)["name"]));
                }

                Button1.Text = "Log Out";

            }
            
            // Check if redirected from facebook
            else if (Request.QueryString["code"] != null)
            {
                ...
            }
 }

User Cancels Login Dialog
What if the user clicks on 'Cancel' rather than 'Go To App'. The user will still be returned to our site but instead of code there would be 3 other parameters in the url namely error, error_reason, error_description. Taking this to account, here's a modified page_load event.

protected void Page_Load(object sender, EventArgs e)
        {   
            // Check if already Signed In
            if (Session["AccessToken"] != null)
            {
                ...
            }
   
            // Check if redirected from facebook
            else if (Request.QueryString["code"] != null)
            {
               ...
            }

            else if (Request.QueryString["error"] != null)
            {
                string error = Request.QueryString["error"];
                string errorReason = Request.QueryString["error_reason"];
                string errorDescription = Request.QueryString["error_description"];
            }

            else
            {
                // User not connected
            }
        }

Here's the output received when the user clicks on 'Cancel': YOUR_REDIRECT_URI?error_reason=user_denied&error=access_denied&error_description=The+user+denied+your+request.

Logout
You may also want to allow the users to logout and hide all the social details. In this sample app, as you have noted earlier the text for Login Button changes to Log Out when the user logs in. So, through the button's text we can know if the user wants to Log In or Out.

protected void Button1_Click(object sender, EventArgs e)
        {
            if (Button1.Text == "Log Out")
                logout();
            else
            {
                var fb = new FacebookClient();

                var loginUrl = fb.GetLoginUrl(new
                {

                    client_id = "your_app_id",

                    redirect_uri = "http://localhost:8779/FacebookDemo.aspx",

                    response_type = "code",

                    scope = "email" // Add other permissions as needed

                });
                Response.Redirect(loginUrl.AbsoluteUri);
            }
        }

        private void logout()
        {
            var fb = new FacebookClient();

            var logoutUrl = fb.GetLogoutUrl(new
            {
                access_token = Session["AccessToken"],

                next = "http://localhost:8779/FacebookDemo.aspx"

            });
   
            // User Logged out, remove access token from session
            Session.Remove("AccessToken"); 

            Response.Redirect(logoutUrl.AbsoluteUri);
        }

Avoiding OAuthException
An OAuthException may occur if you try to use a expired access token. Access token may expire in the following cases:
> The token expires after expires time (2 months is the default for server-side auhentication flow & 2 hours    for client-side auhentication flow.).
> The user changes his password.
> The user de-authorizes your app.
> The user logs out of Facebook.

So, you must surround the piece of code which makes the use of access token with a try catch block.

    try
    {
        dynamic me = fb.Get("me?fields=email");

        Label1.Text = email;
    }
    catch (FacebookOAuthException ex)
    {
        // Access Token expired, Ask the user to Login again
    }

These were just sample examples on how to work with the sdk. It's up to you, how you incorporate these pieces of code in a real world web application and make the most out of Facebook.

Let your friends know that you are developing a Facebook App by sharing this article :P

UPDATE
Must read the second part, A Sample Facebook App using Facebook C Sharp SDK.

24 comments:

  1. Before some days, I tried to work with Facebook SDK but after a little bit work, I gave it up as I was really struck and could not find guidance. But now reading your tips, i feel that it was easy.

    ReplyDelete
  2. This simple little tutorial really helped me, thanks! One correction though... GetLoginUrl should _not_ include the client_secret value. If this Url is being presented to a user to (which it should be, since they need to be taken to FB to authorize the access) then it'll expose the client secret to the user. GetLoginUrl just appends any value you send it to the query string, it's not smart enough to filter out something like the client secret. Reference: http://stackoverflow.com/q/15139516/328193

    ReplyDelete
    Replies
    1. Good catch with that. I blindly followed the developer's tutorial. Sorry for spreading some poor knowledge.
      The article is now updated. So you can trust the codes as always.

      It's not a little tutorial though :P

      Delete
  3. Very good tutorial and really helps you to get started. Thanks!

    ReplyDelete
  4. Vary nice & useful article...
    Lots of thanks!!!!!!!!!!!!!!!!!!!!!!!

    ReplyDelete
  5. thanks friend the only guide that has worked after 4 days looking. thank you very much

    ReplyDelete
  6. Hello,
    nice tutorial, one query :
    if user login on website using facebook and logout, so it should logout from website only not logout facebook.com? how could get it done.
    Pl suggest.

    thanks

    ReplyDelete
    Replies
    1. There is no way a user can logout from app only and doesn't even makes sense(you might be interested in reading more about OAuth protocol). So if you want to disconnect a user from your app only then don't call the fb.GetLogoutUrl, just delete the session values.

      Delete
  7. Thank you for this, But how do I get the users Profile Picture and use it with my image

    ReplyDelete
  8. very nice,thanks!

    ReplyDelete
  9. If I login, I will see only my details, if my friend login he will see his.

    How can implement this.and get the details,name ,email,etc

    ReplyDelete
    Replies
    1. That's what this tutorial do. Try it out someone else's account.
      And to extract more details about this user, follow up this tutorial: A Sample Facebook App using Facebook C Sharp SDK.

      Delete
  10. i am working on this app and included all files but getting namespace dynamic , jsonarray,facebookclient couldnot be found.I am working on vs 2008 and couldnot integrate nuget in my project kindly help me in removing these error

    ReplyDelete
  11. very good tutorial my friend. but i need user likes. i've done it with me/likes but returning data with 25 limit and paging stuff. how can i send limit parameter?

    ReplyDelete
    Replies
    1. Try:
      dynamic me = fb.Get("me?fields=friends,name,email,likes.limit(100)");

      Delete
  12. Can I integrate this in c# windows form without using asp.net ?

    ReplyDelete
    Replies
    1. This link may help you : http://stackoverflow.com/questions/16443948/facebook-integration-with-c-sharp-desktop-application

      Delete
  13. please help me i have error

    This app is in sandbox mode. Edit the app configuration at http://developers.facebook.com/apps to make the app publicly visible.

    ReplyDelete
    Replies
    1. If your app is completed and ready to be used by everyone, you need to disable the sandbox mode.
      To disable sandbox mode:
      1 Navigate to https://developers.facebook.com/apps
      2 Click on Edit App
      3 Navigate to Settings > Basic from the left sidebar.
      4 Set 'Sandbox Mode:' to 'Disabled'

      If your app is still in development and not ready for public use, you can restrict it's usability only to certain users like Testers and Developers. You can add users(developer/admins/testers) by visiting Settings > Developer Roles.

      Delete
  14. If I dont want to use this line - FormsAuthentication.SetAuthCookie(email, false);
    What will happen?

    ReplyDelete
  15. Good Tutorial,

    I can not understand what this line is returning
    Request.QueryString["code"] ????

    kindly make combine all code together at one place at the end.

    Thanks

    ReplyDelete
    Replies
    1. Facebook redirects user back to our website with the auth_code added in the url with key 'code'. This code later is used to receive an access token.

      You can download the whole code in the second part of this tutorial.
      A Sample Facebook App using Facebook C Sharp SDK.

      Delete