Click here to Skip to main content
15,881,248 members
Articles / Programming Languages / C#

FriendTracker - A Winforms Application that Interacts with Facebook

Rate me:
Please Sign up or sign in to vote.
4.85/5 (6 votes)
3 Jul 2013CPOL13 min read 27.6K   2K   21   8
How to interact with Facebook using Facebook SDK for .NET version 6.x
In this article, you will learn how to create and use the FriendTracker application for Facebook.

Introduction

OK, I have to admit it: I'm a control freak! When somebody unfriends me on Facebook, I want to know who it is. Don't tell me that none of you have ever wondered that as well?

Previously, I had an Excel sheet with all my friends, and every now and then, I would check it against my friend list on Facebook. That is - needless to say - a big job that can take quite some time.

Several times, I had thought of writing an application that could do the job for me, but I didn't really think that I could be bothered spending my time doing that. It would definitely take longer than updating the Excel ark once or twice, but an application can be run as often as you like, so in the end, it could be worth it, time-wise.

The other day, I happened to stumble over the Facebook SDK for .NET, and I thought: "Well, maybe it's time to see if I can crack that nut once and for all". And so I set out on my journey towards building the ultimate Facebook application for Windows (Dramatic, right?).

Before You Start

First of all, before you start on your application, you need to do a few things on Facebook to get access to the Facebook API.

Start by going to https://developers.facebook.com/apps. Click the "Create New App" button:

Image 1

Fill in the appropriate information and create the app. Afterwards, you can see that it's created like this:

Image 2

Make a note of the App ID/API Key and the App Secret, because you're going to need them for your application. Also note the Sandbox Mode which should say "On". That means that your new application is only visible to the users you want it to be visible to. When your development is all done and the application is ready, you should switch off the Sandbox Mode.

To learn more about the Sandbox Mode and Application Roles, you can visit this link.

Creating Your .NET Project

First of all: Make sure that you have NuGet installed. If you haven't, you can get it from: http://nuget.org/.

Then create a new .NET Winforms application in the language of your choice (I use C#). Right-click the application's project node in the Solution Explorer and select "Manage NuGet Packages...". Click "Online" and enter "Facebook" in the search box. Install the "Facebook SDK for .NET" by Outercurve Foundation. IMPORTANT: The version number should be higher than 6.0.

Image 3

Important Code

I'm not going to go into detail with all the code, just the parts that have to do with Facebook. As for the rest, you can see the code in the downloadable project files.

Before we can do anything with Facebook, we need to authenticate ourselves to get an Access Token. While we're developing the application, we can create a temporary Access Token using this tool.

Using a developer access token is useful in certain cases, because it will allow you to access the Facebook API without having to go through the normal user authentication. But that access token is going to expire every once in a while, and we will need to create a new one and update our application with that.

When the application is done, we get the access token by authenticating a valid Facebook user, so I might as well skip the temporary developer access token and explain how to authenticate the user.

Before we do that, we need to make sure that we have the Facebook information we need. I created two Application Settings for the App Id and the App Secret and wrapped them in a read-only property:

C#
public string ApplicationId
{
    get { return Properties.Settings.Default.ApplicationID; }
}
public string AppSecret
{
    get { return Properties.Settings.Default.ApplicationSecret; }
}

We also need to specify what permissions we require of Facebook. I decided not to put that in the settings file. There is a certain logic to it that you put the App Id and the App Secret in a settings file, because you may need to create a new app declaration on Facebook against which your Winforms client should work. Having the settings in the settings file will allow you to modify them without rebuilding your EXE.

But if we put the permissions in the settings file, anybody could modify them and thus maybe get your application to behave strangely or not at all. It could also be that you develop a new version of your application that requires more permissions, and if you deploy the EXE without updating the settings file (like you would normally do if you didn't know better), the app wouldn't work properly.

I didn't want that of course. So for the permissions, I put them in a string constant in the code. That way, the correct permissions are always available to the application:

C#
private const string ExtendedPermissionsNeeded = "email,offline_access";

The "email" permission allows us to access the user's email address, which the application will need for the email sending functionality (see further down).

The "offline_access" is really an old permission that should now be depreciated. But it was necessary earlier, so I have chosen to include it anyway, just in case.

For more information on permissions, please see:

Authenticating the User and Getting User Information

Now were ready to authenticate our application user to Facebook. To do that, we need to generate a Login Url:

C#
private string GenerateLoginUrl()
{
    dynamic parameters = new ExpandoObject();

    parameters.client_id = ApplicationId;
    parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";
    parameters.response_type = "token";
    parameters.display = "popup";

    if (!string.IsNullOrWhiteSpace(ExtendedPermissionsNeeded))
        parameters.scope = ExtendedPermissionsNeeded;

    var fb = new FacebookClient();

    Uri loginUri = fb.GetLoginUrl(parameters);

    return loginUri.AbsoluteUri;
}

That code is more or less self-explanatory. We declare the parameters needed and use the FacebookClient object located in the SDK to generate the login URL. When that is done, we add a WebBrowser control (I call it loginWebBrowser) to the application and navigate it to the loginurl:

C#
loginWebBrowser.Navigate(loginUrl);

Then, we handle the WebBrowser Navigated event to check if the authentication went well:

C#
        private void LoginWebBrowserNavigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            if (loginWebBrowser.Visible)
            {
                var fb = new FacebookClient();

                FacebookOAuthResult oauthResult;
                if (fb.TryParseOAuthCallbackUrl(e.Url, out oauthResult))
                {
                    if (oauthResult.IsSuccess)
                    {
                        _accessToken = oauthResult.AccessToken;
                        _authorized = true;
                    }
                    else
                    {
                        _accessToken = "";
                        _authorized = false;
                    }

                    if (_authorized)
                    {
                        fb = new FacebookClient(_accessToken);

                        dynamic result = fb.Get("me");
                        _currentName = result.name;
                        _currentEmail = result.email;
                        userNameLabel.Text = string.Format("Facebook User: {0}", _currentName);

                        //Do what need being done now that we are logged in!
                    }
                    else
                    {
                        MessageBox.Show("Couldn't log into Facebook!", 
                                        "Login unsuccessful", MessageBoxButtons.OK,
                                        MessageBoxIcon.Error);
                    }
                }
            }
        } 

As you see, we use the FacebookClient object's TryParseOAuthCallbackUrl method to parse the callback URL to see if the login was successful, and also retrieve the current valid access token for further use.

As a bonus, we use another FacebookClient object (this time created with the access token in the constructor) to retrieve the name and email of the user that is logged in. Note that if we had not specified the "email" extended permission, we would have gotten most of the user information, but NOT the email address. The fields available to you can be seen in this list.

Please note: The above link neglects to mention the thing about "email" permission. It claims that you can get the email address just by specifying the access token. That is NOT true!

Getting the Friend List

To access the user's friend list is easy as pie. The following code does the trick:

C#
Dictionary<string, string> userFriends = new Dictionary<string, string>();

var client = new FacebookClient(_accessToken);

dynamic myInfo = client.Get(@"\me\friends");

foreach (dynamic friend in myInfo.data)
{
    userFriends.Add(friend.id, friend.name);
}

I am doing that in a BackgroundWorker thread so that it doesn't lock up the UI while it's working.

Once I have the friend list, I simply compare it to the result from the previous run, which I have stored in an XML file, and after that, I update the XML file to reflect the current list.

PLEASE NOTE! VERY IMPORTANT! In some cases, you will notice that the friend list retrieved by the API is not complete! For instance, I have 152 friends on Facebook, but the above API only returns 149. I had to Google to find the explanation for that; It turns out that a Facebook user can deny ALL requests from ALL applications. It is called "turning off the platform", but is rarely done, because it also entails that you cannot use Facebook login at third party pages - which most users want because it's easy and convenient.

The problem is that those friends do not show up in the friend list. It is no bug, and there is absolutely nothing you can do about it. That means that in reality, this application can only track people who do NOT deny application requests.

Logging Out When the Deed Is Done

After we have read the friend list, we can either remain logged in or we can log out of Facebook. If we choose to remain logged in, we will completely bypass the authentication process the next time and go directly to the hot stuff (as long as the access token does not expire).

If we choose to log out, we can log in with another account if we so please - and track the friends of that account.

To log out, we need to find the logout url in the same manner as we found the login url:

C#
private string GenerateLogoutUrl()
{
    dynamic parameters = new ExpandoObject();

    parameters.next = HttpUtility.UrlEncode(_loginUrl, Encoding.UTF8);
    parameters.access_token = _accessToken;

    var fb = new FacebookClient(_accessToken);

    Uri logoutUri = fb.GetLogoutUrl(parameters);
    return logoutUri.AbsoluteUri;
}

Again, we use the FacebookClient object to generate the url. According to the documentation I found, specifying a url in the "next" parameter should cause a redirect to that url when the logout was done. In the above case, it should redirect to the login form when the logout was done.

But as I explain in my tip, Facebook SDK for .NET - How to log your application out, that doesn't work at all. My WebBrowser only redirects to the Facebook timeline of the user that is logged in, and that user is NOT logged out at all.

In the above tip, I explain more about how to work around that problem. In short, I test to see if there is a hidden logout form in the current web page (which there is in the timeline), and if there is, I invoke a JavaScript to do the logout. Once that is done, I manually redirect to the login page again:

C#
        private void LoginWebBrowserNavigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            if (_loggingOut)
            {
                if (loginWebBrowser.Document != null)
                {
                    HtmlElement logoutForm = 
                        loginWebBrowser.Document.GetElementById("logout_form");
                    if (logoutForm != null)
                    {
                        loginWebBrowser.Document.InvokeScript("execScript",
                                      new Object[] { "document.getElementById
                                      ('logout_form').submit();", "JavaScript" });
                    }
                }
         
                if (e.Url.AbsoluteUri.StartsWith(@"https://www.facebook.com/index.php")
                 || e.Url.AbsoluteUri.StartsWith(@"http://www.facebook.com/index.php"))
                {
                    loginWebBrowser.Navigate(_loginUrl);
                }
            }
        } 

That's all there is to it! Easy peasy if you know how to. I had to Google a lot and read a lot of articles to be able to piece it all together, so I hope that this can be of a small help to you.

Using the FriendTracker Application

OK, now the application is done and ready for use. So how do you use it?

Step 1 - .NET Framework

Make sure that the machine that should run the program has got .NET Framework 4.5 installed. If not, you can get it from:

Step 2 - Deployment

Copy the contents of the "bin\Release" folder to a folder on the machine where you want to use it. It should be five files in total:

  • Facebook.dll
  • Facebook.xml
  • FriendTracker.exe
  • FriendTracker.exe.config
  • FriendTracker.pdb

Step 3 - Update the Settings in the Config File

  • ApplicationID: This is the App Id you got when you registered the application on the Facebook developer site (see above).
  • ApplicationSecret: This is the App Secret you got when you registered the application on the Facebook developer site (see above)
  • SendEmail: A boolean value. If set to "True", the application will send an email to a given email address whenever an update of the friend list has occurred (new friends added or old friends removed). It requires that the other email settings are set up correctly. If set to "False", no email is ever sent.
  • SMTPServer: The SMTP server with which you want to send the email. Can be empty if SendEmail="False".
  • SMTPPort: The port your SMTP server sends emails on. An integer value. Leave at 80 if you're not sure.
  • SMTPUser: If your SMTP Server requires authentication, you can enter the user name here.
    Please note: If authentication is used, BOTH user name and password MUST be filled in, otherwise it won't work. Can be empty if SendEmail="False".
  • SMTPPassword: If your SMTP Server requires authentication, you can enter the user password here.
    Please note: If authentication is used, BOTH user name and password MUST be filled in, otherwise it won't work. Can be empty if SendEmail="False".
  • SMTPUseSecurity: If your SMTP Server requires the use of SSL, you can set this property to "True". Otherwise, just leave it at "False".
  • FromEmailAddress: The email address that appears to be the sender of the email. Can either be a specific address or the string "[CURRENT_EMAIL]" (without quotes). If it is "[CURRENT_EMAIL]", the email address retrieved from the currently logged in user will be used. The FROM email address can NOT be empty.
  • TomEmailAddress: The email address to whom the email will be sent. Can either be a specific address or the string "[CURRENT_EMAIL]" (without quotes). If it is "[CURRENT_EMAIL]", the email address retrieved from the currently logged in user will be used. The TO email address can NOT be empty.
  • LogOutAfterUpdate: If this is set to "True", the application will log out the current user from Facebook once the update of the friend list has taken place. This is mostly for automation purposes.
  • CloseAfterUpdate: If this is set to "True", the application will close down once the update of the friend list has taken place. This is mostly for automation purposes.

Step 4 - Use the Application

The simplest way to use the application is to simply run it manually by double-clicking the FriendTracker.exe file. That will open the application and present you with the Facebook login. Once you have logged in, you should see the list of your friends in the listview (it takes a very short time to retrieve them, but should not take more than a few seconds).

New friends are placed in the top group, old friends in the group after that and removed friends in the last group.

If new friends have been added or old friends removed, and all the email settings are correctly specified, you should receive and email to the selected address with the changes.

You could, if you so desire, automate the run of the application, either by adding it to the Windows startup sequence so that it is run when Windows starts, or by using the scheduler to run it at scheduled times.

No matter how you do, you need to remember that you might need to log in. Always the first time you run the application. If you don't log out, you should be logged in on every subsequent run unless the access token needs to be renewed.

How to Deal With Friends That Are Not in the List Due to Their Security Settings

As I wrote above, the friend list you get from Facebook might not be complete if some of you friends have turned off their platform. If you can live with that, it's ok. If not, then you can add them manually to your list once you are logged in. Just click the "File" menu and choose "Add friend manually" or simply press the "Insert" button on your keyboard.

A manually added friend will be shown with a person icon. Friends retrieved from Facebook are shown with a Facebook icon.

You can just as easily remove manually added friends, by selecting one or more, and select "Remove friend manually" from the "File" menu or simply pressing the "Delete" button on the keyboard. You needn't worry, you will be asked to confirm the delete before it actually happens.

Please note: If you delete a person that is NOT manually added, the person will be deleted, but restored from Facebook the next time the program is run.

Deleting friends - manually or automatically added - in the FriendTracker program will NOT delete them from Facebook.

Possible Improvements

  • Possibility to change the settings from within the program!
  • Other Facebook features, for instance, it could be interesting to have the program post a message to your timeline when it has updated the friend list, saying "Peter Peterson has recently added 12 new friends" or something like that. It could also be interesting to add a feature so that you can actually remove friends from Facebook by removing them from the FriendTracker list.

I will leave that up to you, the reader, as a homework exercise.

History

  • 3rd July, 2013: Version 1.00 - Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Sweden Sweden
Born in Copenhagen, Denmark
Have been living in Paris, France and L.A., The United States
Now live in Stockholm, Sweden

Started programming when I got my first VIC 20, and a few months later on Commodore 64. Those were the days!

Studied programming at the Copenhagen Engineering Academy

Professional console, winforms and webforms programming in Comal, x86 Assembler, Fortran, Pascal, Delphi, Visual Basic 3 through 6, Classic ASP, C# and VB.NET

I now work as Senior Microsoft Dynamics AX and .Net programmer, and have a number of projects in various states of progress to work on in the spare time...

Comments and Discussions

 
QuestionScope for new Facebook SDK versions Pin
Ruben.Gnlez13-Oct-15 4:16
Ruben.Gnlez13-Oct-15 4:16 
QuestionApp Secret Pin
Member 1035577313-May-14 6:51
Member 1035577313-May-14 6:51 
AnswerRe: App Secret Pin
Johnny J.13-May-14 20:07
professionalJohnny J.13-May-14 20:07 
QuestionAhem! Pin
Bassam Abdul-Baki3-Jul-13 4:36
professionalBassam Abdul-Baki3-Jul-13 4:36 
AnswerRe: Ahem! Pin
Johnny J.3-Jul-13 4:57
professionalJohnny J.3-Jul-13 4:57 
GeneralRe: Ahem! Pin
Bassam Abdul-Baki3-Jul-13 5:05
professionalBassam Abdul-Baki3-Jul-13 5:05 
GeneralRe: Ahem! Pin
Bassam Abdul-Baki3-Jul-13 5:07
professionalBassam Abdul-Baki3-Jul-13 5:07 
GeneralRe: Ahem! Pin
Johnny J.3-Jul-13 5:37
professionalJohnny J.3-Jul-13 5:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.