Facebook* Example App for .NET*

Related Downloads

NOTE: You must have a developer account on Facebook* and get a Facebook* application ID for a Desktop Application before this example application will run properly. Please refer to the video mentioned in the “Incorporating Facebook* Features” section below for more information about how to do this.

This Facebook* Example application is written in .NET* and C# for use on Windows* netbooks. It connects to the Intel AppUp® SDK through the AdpService assembly for .NET*. For details and to download the library, see the separate article.

You can download the source code for this app from the links to the right, so I won’t provide much source in this discussion. You can follow along as you read. This application makes use of the Facebook* Developer Toolkit that Microsoft promotes. This toolkit is a .NET* library and makes building basic Facebook* desktop (and other) apps quite simple.

The application is also documented through inline comments. You can look at those or create MSDN-style reference documents using Sandcastle/DocProject or similar tools.

Functional Description

The Facebook* Example for .NET* asks the user to sign into Facebook* and then retrieves the user’s friend list and current status. The user can post a new status message. If the user has not previously authorized the application to update his or her status the application opens the web browser asking the user to confirm authorization and posts the status.

Technical Description

The Facebook* Example for .NET* uses the Facebook* Developer Toolkit which takes care of authentication when the service is first started. It does not store the login in any persistence, although this would be encouraged for a real-world app. It is built as a standard .NET* WinForms application and makes use of the .NET* WinForms controls provided by the Toolkit to show a list of friends.

The core application handles Intel AppUp® authorization through the AdpService before any forms are loaded. If this fails, it presents a message to the user and exits. All Facebook* interaction is handled in the single form that makes up the interface of the main application.

Automated tests cases are included to test interaction with the Intel AppUp® service and show how to build applications with automated unit or integration testing.

Technical Implementation Summary

To start this application, I created a basic C# Windows* Forms Application. I could next take on Facebook* integration or Intel AppUp® integration. I chose to do Intel AppUp integration first as (a) I had it on-hand and (b) it’s easier to write tests for. I’m going to start by writing my tests.

Automated Integration Testing

Looking at the source code you’ll see two projects. One is the Windows Forms Application, AdpNetExample. The other is a test library, a C# Class Library, AdpNetExampleTests. I’ve created this as a separate assembly so that my main application doesn’t need to reference or distribute the dependent test libraries, and so that I could ship the application without the test code.

You will also notice a folder called ‘lib’. I like to have this in my solution to hold DLL files that are referenced by the assemblies. This allows me to check those DLL’s into source control to ensure that the same version is used by all other developers, by any automated integration testing and by the release package.

For testing I’m using NUnit1. I’ve also added NUnitForms which is a third-party (i.e. not related to NUnit) extension library that provides handy tools for testing forms, including capturing the modal dialogs we’re going to be dealing with. Finally, to provide a mock object to replace the actual ADP service while testing I’m using Rhino Mocks. This helps keep me from writing many stub classes for each test.

Those are all in the lib folder and I’ve added references to the AdpNetExampleTest project. Let’s think about the test cases that we are going to deal with. To make an application work with ADP you need to initialize ADP and then check that the user is authorized to run your application. All this should happen at start up so let’s define what is driving this integration:

As an ADP developer I want to make sure my users are authorized through AppUp Center so that I get paid by everyone that uses my app.

Granted, there are other factors driving our integration (validation for acceptance in the store and all that brings with it) but this should give us a good starting point. Now let’s think about how to test this integration. What possible scenarios can happen with this authorization happens?

Given that the ATDS is running and the app has the correct ID, when the app starts is should display no dialog boxes but rather show the friend list form.

Given that the ATDS is running and the user is not authorized to use the app, when the app starts it should show a message that the app is not authorized and should exit.

Given that the ATDS is not running, when the app starts is should give a message stating that the AppUp store needs to be installed or started and should exit.

That’s a good start. There are many more tests cases that we could add (for ADP failure, incompatible version, expired authorization, etc.) but we’ll start with this.

Let’s take each scenario and create a unit test for it. See the code in AdpNetExampleTests.UnitTests.When_the_application_loads.cs for the tests. I’ll step through the positive test here, the rest are similar.

[Test]
public void Should_initialize_and_authorize_through_adp_service()
{
    var adp = Mocks.DynamicMock<AdpService>();
    Expect
        .Call( adp.Initialize() )
        .Return( ReturnCode.ADP_SUCCESS );

    Expect
        .Call(adp.IsAuthorized(new Guid()))
        .IgnoreArguments()
        .Return(ReturnCode.ADP_AUTHORIZED);

    Mocks.ReplayAll();

    var form = new AdpNetExample.Program(adp);
    Assert.NotNull( form );

    Modal.ExpectModal("Sorry!", ()=>
    {
        var text = new MessageBoxTester("Sorry!").Text;
        Assert.Fail("Should not show dialog: " + text);
    }, false);

    form.InitializeADP();

    Mocks.VerifyAll();
}

The first few lines create a mock object of our ADP service. While AdpService derives from an interface, Rhino Mocks can create mock objects directly from our class. We tell Rhino mocks that we Expect a call to Initialize and that it should return ADP_SUCCESS. We also Expect a call to IsAuthorized and while we don’t care about the parameters (for this test), we should return ADP_AUTHORIZED.

Then we instantiate a new object of our Program app, passing in the mock object. We know that we need a mock object for the Program class to use, so we’re going to have to create this constructor. Of course the default constructor (or the main method) can just pass in an instance of AdpService. We’ll take care of that in a minute.

Next we use NUnitForms’ ModalFormTester to catch the message boxes. We need to set this up before we call InitializeADP so that the tester handles any dialog boxes for us if they show up and we don’t have to click the OK button to close them. We want these tests to be fully automated. The final parameter to the ExpectModal call tells the test handler that we are not expecting a dialog, in this case.

With that set up we can call the InitializeADP method. The mock object will return ADP_SUCCESS when the method asks for Initialization and will return ADP_AUTHORIZED when the method check IsAuthorized. If the method doesn’t behave right we’ll catch any message boxes and fail the test. If everything goes as planned we’ll do a final check to make sure that the method did call both ADP methods, because that’s part of our contract (and important to our user story).

Take a look at the source code for the other two tests and think about how to handle the additional test cases we haven’t covered.

A basic app with ADP integration

If you run the test cases right now they won’t even compile. That’s fine, that helps us figure out what code we need to write. Following the source code for Program you’ll see I added a constructor that takes the IAdpService object that we can use for testing. I also created a default constructor that uses AdpService which is what we want to do in production.

public Program() : this(new AdpService()) {}


public Program( IAdpService AdpService ) {
    this.AdpService = AdpService;
}

We also assumed, in testing that there would be an InitializeADP method. I added that to call both Initialize and IsAuthorized on the AdpService object that Program is provided on the constructor. In the source code you’ll see the main method calls this and exits if any errors are found.

Now we have a basic app that connects to the ADP service, verifies that its authorized and launches a form. We also have some test cases we can run to make sure that the app does what it should do even after we make major changes to the code.

Incorporating Facebook* features

All that work and we wanted to build a Facebook* app, right? Let’s add the Facebook.dll and Facebook.Windows.dll from the Facebook* Developer Toolkit to the references on our application and get started. There’s a great video demo online that demonstrates how to build a desktop app using the toolkit. This code is derived directly from that demo, so I won’t go into great detail about what’s going on.

We’re going to add the FacebookService and a FriendList to our Form. We could use dependency injection again to add references to these to our form for testing (well, at least the service) but for brevity I’m going to skip that. (Let’s make that an exercise for he reader.) Instead we’ll manually test later.

Following the tutorial, you’ll need to create a Facebook* Application at http://developers.facebook.com/ to start this. Get your API key and change the one in the Settings. You no longer need to include your Secret (as the video suggests) which is good.

In the source code, in the code-behind for FriendViewer you’ll see that I set up the service with the key and connect on the form’s Load event handler. If the user is not logged in (which they aren’t on load) then this opens an embedded Internet Explorer instance in a form and get’s the user to log into Facebook*. It then continues loading our form. All of this is handled by a single call in the Facebook* Toolkit.

On the designer I added a FriendList and wired up the data from the service on the control’s Load event handler. Finally I added fields to get the current status and update the user’s status.

To get permissions to post on a user’s feed, the user needs to approve our app through Facebook*. Unlike the demo which does this with a button, I captured the error in an exception, and then launch a browser to get that approval.

This is a straightforward example and is quite fast to write with this toolkit.

Testing the app

We didn’t write any automated tests for Facebook* part, so let’s make sure we test it by hand. What value are we providing through our app?

As a Facebook* user I want to see a list of my friends on my netbook so that I can recall my connections without opening a browser.

OK, well that’s a bit contrived, but let’s run with it. How are we going to make sure this works well?

Given that I have a Facebook* account with at least one friend, when I log in I should see my list of friends.

Given that I do not have a Facebook* account, when I start up I should be able to sign up and then see a list with no friends.

Given that I have a Facebook* account with no friends, when I log in I should see a list with no friends.

That’s a good start. I’m sure you can think of more. Those should be easy enough to test manually although you’ll need to set up Facebook* accounts to do that. (This is where dependency injection and mock objects can really help.)

What other value are we including?

As a Facebook* user I want to be able to update my status from my netbook so that I don’t have to open a browser to tell my friends what I’m up to.

Then what scenarios can we think of to test that?

Given that I am a Facebook* user and I have not authorized the app to update my feed, when I send a new status it should ask me for permission to change my account.

Given that I am a Facebook* user and I have authorized the app to update my feed, when I send a new status update it should appear on Facebook*.

Good start. You could add more cases for users who don’t have accounts or for users who don’t authorize the app to the update their status. Go ahead and build the app and test these cases.

1 You can use the built in unit testing framework in Visual Studio if you have Professional or better and if you prefer it. It should be similar.

Tags:
For more complete information about compiler optimizations, see our Optimization Notice.

Comments

southsidesmoka's picture

This AdpService.dll is a gift from the gods! It has literally saved me months upon months of having to rewrite C# apps in C++ to get into the Intel AppUp Store. Kudos to all those involved and a thousand thanks.

-CCK