Tag Archives: Facebook

The .NET Facebook API and Silverlight

Awesome! There is now a library for .NET developers to interface with the Facebook services, opening up a whole new world of integration between your app and all of your user’s information in Facebook. In this post I have included code samples for a simple Facebook friend viewer. With the viewer, you can pull all tagged photos of yourself, your friends, and all their information. While the app functions, there is so much more that can be done. Comments can be posted to Facebook remotely, pictures uploaded and tagged remotely, videos uploaded, etc. Virtually all of the Facebook functionality is exposed through the API. Checkout the bottom of the post for a link to the project, as well as a working demo. Let’s dive in!

First, downoad the required assemblies. Note that there are assemblies for WinForms, WPF, ASP.NET MVC (not just Silverlight) included!

Then, you will need to setup your account at http://www.facebook.com/developers/. Click on “Setup New Application” and enter a new application name as shown in the screenshot below:

CreateApp

Then fill out the fields shown below on the “Basic Info” tab. Note the developers area. Add any devs who will be working on the app there:

FillOutInfo

From there fill out the connect information. In development this will be the local http://localhost:[port] that that you are developing on. In production it will be yourdomain.com:

connect

Then click on the advanced tab and enable Sandbox mode, as we will be using this account for development purposes:

advancedSandbox

Cool! Now that we have our account setup we need to create a “Silverlight Navigation Application” in Visual Studio. To make everything work, we need to add a javascript file to the same directory as the HTML page that is hosting our Silverlight app. This will allow us to facilitate the cross domain communication between our app and Facebook (note the var silverLightPluginId must match the DOM id of the Silverlight plugin on the page!!!):

fblogin.js

//must match the Silverlight plugin's DOM ID
var silverlightPluginId = 'Silverlight1';

function facebook_init(appid) {
    FB.init(appid, "/xd_receiver.htm");
}

function isUserConnected() {
    FB.ensureInit(function () {
        FB.Connect.get_status().waitUntilReady(function (status) {
            var plugin = document.getElementById(silverlightPluginId);
        });
    });
}

function facebook_login() {
    FB.ensureInit(function () {
        FB.Connect.requireSession(facebook_getSession, true);
    });
}

function facebook_logout() {
    FB.Connect.logout(facebook_onlogout);
}

function facebook_getSession() {

    FB.Facebook.get_sessionState().waitUntilReady(function () {
        var session = FB.Facebook.apiClient.get_session();
        var plugin = document.getElementById(silverlightPluginId);
        plugin.Content.FacebookLoginControl.LoggedIn(session.session_key, session.secret, session.expires, session.uid);
    });
}

function facebook_onlogout() {
    var plugin = document.getElementById(silverlightPluginId);
    plugin.Content.FacebookLoginControl.LoggedOut();
}

function facebook_onpermission(accepted) {
    var plugin = document.getElementById(silverlightPluginId);
    plugin.Content.FacebookLoginControl.PermissionCallback(accepted);
}

function facebook_prompt_permission(permission) {
    FB.ensureInit(function () {
        FB.Connect.showPermissionDialog(permission, facebook_onpermission);
    });
}

Include the script in the page hosting the Silverlight app:

<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" type="text/javascript"></script>
<script type="text/javascript" src="fblogin.js"></script>

Now, add the file xd_receiver.htm to the same directory as the javascript file. This will receive the response from Facebook and route it appropriately:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <body>
    <script src=http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js
                    type="text/javascript">
    </script>
  </body>
</html>

Whew! Now that all that’s done we can tackle the Silverlight part. Add a reference the assembly Facebook.Silverlight.dll to your Silverlight project. Note that if you are using Visual Studio 2010 you might get a build error similar to the following after you add the reference:

—> System.NotSupportedException: An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more information.

This is because the CAS policies have changed in VS2010. No worries though, just locate the assembly in the file system and Unblock it by clicking on the button in the screenshot below:

UnBlock

In your Silverlight application you then just need to initialize the Facebook API object and invoke the Login() method:

        private Api _facebookAPI;
        private readonly BrowserSession _browserSession;
        private const string ApplicationKey = "[Put your application key here, yes I know it's not the best place to initialize it!]";

        public Home()
        {
            InitializeComponent();

            _browserSession = new BrowserSession(ApplicationKey);
            _browserSession.LoginCompleted += browserSession_LoginCompleted;
            _browserSession.GetStatusCompleted += new EventHandler<GetStatusCompletedEventArgs>(_browserSession_GetStatusCompleted);
            _browserSession.Login();
        }

This will generate the browser popup to have the user login to their Facebook account. Once the user is logged in the _browserSession_GetStatusCompleted method gets invoked:

        private void browserSession_LoginCompleted(object sender, EventArgs e)
        {
            _facebookAPI = new Api(_browserSession);

            //set the photo and friends list item sources
            Photos.ItemsSource = myImages;
            FriendsList.ItemsSource = myFriends;

            //get my friends
            _facebookAPI.Friends.GetUserObjectsAsync(
                (friends, state, ex) =>
                {
                    if (ex == null)
                    {
                        Dispatcher.BeginInvoke(
                            () =>
                            {
                                AddFriends(friends);
                            });
                    }
                }, null);

            Facebook.Session.BrowserSession session = sender as Facebook.Session.BrowserSession;

            _facebookAPI.Photos.GetAsync(session.UserId.ToString(), null, null,
                new Photos.GetCallback(
                    (photos, obj, ex) =>
                    {
                        Dispatcher.BeginInvoke(
                            () =>
                            {
                                AddPhotos(photos);
                            });
                    }), null);
        }

In here we’re doing a couple things. First we’re invoking the FB-API and getting the user’s friends and a listing of all photos they have been tagged in. Once we have those we add them to the myImages and myFriends observable collections, which are bound to the UI. The AddFriends() and AddPhotos() implementations are listed below:

        //add friends to the observable collection
        private void AddFriends(IList<Facebook.Schema.user> friends)
        {
            foreach (Facebook.Schema.user friend in friends)
            {
                myFriends.Add(new Friend()
                {
                    Name = friend.first_name,
                    Photo = new BitmapImage(new Uri(friend.pic_small)),
                    UserId = friend.uid.GetValueOrDefault(),
                    Activities = friend.activities,
                    Affiliations = friend.affiliations != null && friend.affiliations.affiliation != null && friend.affiliations.affiliation.Count > 0 ? friend.affiliations.affiliation.Select(a => a.name).Aggregate((i, j) => string.Concat(i, ", ", j)) : string.Empty,
                    Books = friend.books,
                    EducationHistory = friend.education_history != null && friend.education_history.education_info != null ? GetEducation(friend.education_history) : string.Empty,
                    Interests = friend.interests,
                    Movies = friend.movies,
                    Music = friend.music,
                    Quotes = friend.quotes,
                    Sex = friend.sex,
                    TV = friend.tv,
                    WorkHistory = friend.work_history != null && friend.work_history.work_info != null && friend.work_history.work_info.Count > 0 ? friend.work_history.work_info.Select(e => e.company_name).Aggregate((i, j) => string.Concat(i, ", ", j)) : string.Empty
                });
            }
        }

        private void AddPhotos(IList<Facebook.Schema.photo> photos)
        {
            foreach (Facebook.Schema.photo photo in photos)
            {
                myImages.Add(
                        new Photo() { 
                            Small = new BitmapImage(new Uri(photo.src_small)),
                            Normal = new BitmapImage(new Uri(photo.src)),
                            Large = new BitmapImage(new Uri(photo.src_big))
                        }
                    );
            }
        }


        /// <summary>
        /// gets a string representing all education history
        /// </summary>
        /// <param name="educationHistory"></param>
        /// <returns></returns>
        private string GetEducation(Facebook.Schema.userEducation_history educationHistory)
        {
            return educationHistory.education_info.Select(
                    (e) =>
                    {
                        return string.Format(" {0} {1} {2} {3}", 
                            //degree info
                           !string.IsNullOrEmpty(e.degree) ? "Degree: " + e.degree : string.Empty, 

                            //concentration info
                            e.concentrations != null && e.concentrations.concentration != null && e.concentrations.concentration.Count > 0
                            ? 
                                "Concentrations: " + e.concentrations.concentration.Aggregate(
                                (i, j) => {
                                    return string.Concat(i, ", ", j);
                                }) : string.Empty, 
                            
                            //college name
                            !string.IsNullOrEmpty(e.name) ? "College Name: " + e.name : string.Empty, 
                            
                            //college year
                            e.year > 0 ? "Year Graduated: " + e.year : string.Empty);
                    }).Aggregate((i, j) =>
                    {
                        return string.Concat(i, j);
                    });
        }

That’s the core code! Now our UI just needs to bind to the collections and we have all the data we need. Check it out!


Working Demo (If your firewall blocks requests to/from Facebook this will just hang and will not load!!)

Download the project to get the fully working solution (in VS2010 and Silverlight 4)