Facebook Application Development

1. Getting Started with Facebook... Not So Needed Introduction

There are plenty of resources out there that show how to start developing a Facebook application using the ASP.NET/.NET environment. For example, there are Step-by-step Guide to Creating an Application and Creating a Facebook Application and many others. But, how do you take that "Hello, World" Facebook sample to the next level? Hellooooooo,world? "Don't leave me hanging"....

In this article, I will show (or will try to show) how to build a more sophisticated Facebook application that interacts with Facebook users and with a SQL Server database.

As you may know, a Facebook application is "hosted" within a Facebook Canvas Page, and the canvas page is within a Facebook frame (kinda like a Russian doll house, eh?). Facebook application can be FBML or .... just take a look at Anatomy of a Facebook Application.

(When you're ready to develop your own Facebook Application, don't forget to "create" it first and request an Application Key and Application Secret in Facebook at Facebook Developers Application).

In this Facebook Application, I am using the Facebook .NET Toolkit, found at Facebook Developer Toolkit library. To use it, simply reference it in your project; for example:

using Facebook;
using Facebook.WebControls;

public partial class _App : CanvasFBMLBasePage
{
   ...
   ...
}

* notice using the CanvasFBMLBasePage base class

2. Developing Facebook Applications with .NET: Create a Sample User Presentation Using ASP.NET and FBML. Building a Facebook Canvas Page Using ASP.NET and FBML

Say I have data in a SQL Server database:

and I want to display it in my Facebook Application. For example, I want to use a GridView control, like this:

How do you go about developing this?

First (or not so first) things first: Create or add a new application in Facebook Developers. I have mine set up as this:

Now, open your favorite Visual Studio (I am using VS 2005), and start/create a new ASP.NET Web site. I am using C# in this article, but you can adapt the code for VB.NET. Don't forget to add references to the Facebook Developer Toolkit library:

In the first (and only) ASP.NET form (chances are it's called Default.aspx), open the page and add a GridView control to it.

<%@ Page Language="C#" AutoEventWireup="true"
         CodeFile="app.aspx.cs" Inherits="_App" %>

<!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>
   Facebook Test Application: Traveling Babies
</title></head>

<!-- <body> -->

<form id="formDataContent" runat="server">
    <asp:GridView ID="gridSelectObjects"
                  runat="server"
                  AutoGenerateColumns="true"
                  style="width:80%">

   <AlternatingRowStyle BackColor="#f7f7f7" />
   </asp:GridView>
</form>

<!-- </body> -->
</html>

* Notice that the body element is commented. I'm using FBML, and it will be hosted inside Facebook canvas, so there is no body.

Switch to "code view" and add some code:

using Facebook;
using Facebook.WebControls;

public partial class _App : CanvasFBMLBasePage
{
   //keys for FBTestApplication:
   private const string FACEBOOK_API_KEY =
      "xfxfxdx7xbx7xbxfxaxdxsiccolo";
   private const string FACEBOOK_SECRET  =
      "dx8xfx9x8x1xsiccolo2x4x1xfx2xdx";

   //db interface:
   private FacebookDB m_FacebookDB = null;

   new protected void Page_Load(object sender, EventArgs e)
   {
      base.Api = FACEBOOK_API_KEY;
      base.Secret = FACEBOOK_SECRET;
      base.Page_Load(sender, e);

      string facebookUserID = this.FBService.GetUserInfo().UserId;

      try
      {
         bool result = false;
         string connectInfo = Settings.ConnectInfo();
         m_FacebookDB = new FacebookDB(facebookUserID, connectInfo);

         string applicationUserID       = String.Empty;
         string applicationUserObjectID = String.Empty;
         string objectType              = String.Empty;
         string objectDescription       = String.Empty;
         string errorInfo               = String.Empty;

         result = m_FacebookDB.GetApplicationUserID_withObjectInfo
            (out applicationUserID,
             out applicationUserObjectID,
             out objectType,
             out objectDescription,
             out errorInfo);

         if (!result || applicationUserID == String.Empty)
         {
            this.labelFBDashboard.Text =
               "Failed to retrieve Application User:" + errorInfo;
            return;
         }


         //show object list in a grid
         result = ShowObjectListGrid(applicationUserID,
            out errorInfo);

      }

      catch (Exception)
      {
         throw (new System.Exception "Your mama off the train");
      }

   }


   private bool ShowObjectListGrid(string applicationUserID,
      out string errorInfo)
   {
        errorInfo = String.Empty;

        try
        {
            bool result = false;

            // new DataSet("ObjectList");
            DataSet objectList = null;
            result = m_FacebookDB.GetObjectList(applicationUserID,
                                                out objectList,
                                                out errorInfo);
            // bind the data
            this.gridSelectObjects.DataSource = objectList;

            this.gridSelectObjects.ShowHeader = false;

            //bind
            this.gridSelectObjects.DataBind();

            return result;
        }

        catch(Exception ex_show_grid)
        {
            errorInfo = ex_show_grid.Message;
            return false;
        }
   }
}

Where FacebookDB is a middle layer, to interface with SQL Server database.

But, you also can explore options that FBML adds to your Facebook Application, so you can create a Facebook-alike application, something like this:

where:

  1. is Facebook dashboard menu, created with the fb:dashboard FBML element (more at fb:dashboard at Facebook Developers Wiki)
  2. is a result of using fb:create-button within the fb:dashboard FBML element (more at fb:create-button at Facebook Developers Wiki)
  3. is a result of using the fb:dashboard FBML element
  4. is a GridView element

With the FBML "approach", you can put FBML tags right into an ASPX page, or have the web application generate them dynamically. To add a "Facebook dashboard," I use the following code:

new protected void Page_Load(object sender, EventArgs e)
{
   ...
   ...
   //FMBL part:
      FBMLMaker fbmlMaker =
         new FBMLMaker(this.FBService.GetUserInfo());
      //set dashboard
      this.labelFBDashboard.Text = fbmlMaker.Dashboard();
   ...
   ...
}

Where labelFBDashboard is <asp:Label ID="labelFBDashboard" runat="server" Text="... fb-dashboard ..." ></asp:Label>, and the Dashboard() method:

public string Dashboard()
   {
      //for FBML generations can also be used StringBuilder();

      //http://wiki.developers.facebook.com/index.php/Fb:dashboard
      string fbDashboard = "<fb:dashboard>";

      fbDashboard += "<fb:action href=\"http://www.siccolo.com/\">
         Developer Site
      </fb:action>";

      //show greeting as a link..
      fbDashboard += "<fb:action href=\"#\" >"
         + this.Greeting() + "
     </fb:action>";

      //show application help link:
      fbDashboard += "<fb:help href=\"http://www.siccolo.com/\">
         What do I do with this?!
      </fb:help>";

      fbDashboard += "<fb:create-button
         href=\"http://www.siccolo.com/\">
         Take me away!
      </fb:create-button>";

      fbDashboard += "</fb:dashboard>";
      return fbDashboard;
   }

Or, you simply can add <fbml > tags right into your ASPX page (see below using the <fb:friend-selector/> element).

Facebook Application Development

3. Developing Facebook Application with .NET: Adding User-Page Interactions with FBML and FBJS. Allow to Select a Friend

As you may know, you can use FBJS on FBML pages.

So, you can modify a grid to add a link on each row:

<%@ Page Language="C#" AutoEventWireup="true"
    CodeFile="app.aspx.cs" Inherits="_App" %>

<!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>
   Facebook Test Applicatioin:Traveling Babies
</title></head>

<!-- <body> -->

<form id="formDataContent" runat="server">
   <asp:GridView ID="gridSelectObjects"
                 runat="server"
                 AutoGenerateColumns="false"
                 style="width:80%">

      <Columns>
         <asp:TemplateField ItemStyle-Width='180px'
                            ItemStyle-Wrap=false>
            <ItemTemplate>

               <a href="#" onclick="select_object
                  (<%# Eval("object_id")%>,
                           '<%# Eval("type")%>',
                           '<%# Eval("description")%>');
                              return false;"
                           style="color:Black;
                              background-color:Transparent;
                              border-color:Transparent;
                              border-style:None;">

               <img src="http://www.siccolo.com/fbtestappsiccolo/
                         images/select.gif"
                         border="0"
                         align="center"
                         title="select <%# Eval("description")%>"/>
                                select <%# Eval("description")%></a>
            </ItemTemplate>

         </asp:TemplateField>


      </Columns>

   <AlternatingRowStyle BackColor="#f7f7f7" />
   </asp:GridView>
</form>

<!-- </body> -->
</html>

Notice calls to select_object() javascript (FBJS) for each row. So, when the user clicks the "select..." link on the grid row, the page will display the selected row and will allow the user to perform some action on the selected item:

Selected information is displayed in its own DIV element:

<div id="data_selected_content1" style="display:none">

<span class="detached_label">Baby

   <span id="spanSelectedObject1" style="font-weight: bold;
         font-style: italic; font-variant: normal;"></span>

needs:
<asp:DropDownList ID="listObjectAction1" runat="server"
                  CssClass="listElement" ></asp:DropDownList>

...and then off to

<fb:friend-selector idname="textSelectedFriend" />

<asp:Button ID="buttonSend"
            runat="server"
            Text="Send"
            CssClass="inputsubmit"
            OnClick="buttonSend_Click" />
</span>

</div>

So, here's my JavaScript (FBJS) function:

<script>
   function select_object(object_id , type, description)
   {
      Animation(document.getElementById('data_selected_content1')).
         to('height', 'auto').from('0px').to('width', 'auto').
         from('0px').to('opacity', 1).from(0).blind().show().go();
      document.getElementById("spanSelectedObject1").setTextValue
         ( description) ;
      document.getElementById("buttonSend").setValue
         ( "Send " + description) ;
   }
</script>

Notice that I am using Animation() to show the DIV element—see FBJS/Animation for more information. As you can see, to change SPAN innerText, I'm using the setTextValue() method, and, for a button, I'm using setValue().

To provide the user with the ability to select a Friend, you can add a <fb:friend-selector idname="textSelectedFriend" /> FBML element (more at Fb:friend-selector).

* Notice the idname attribute of the <fb:friend-selector> element: the name of the hidden form element that contains the user ID of the selected friend when form is being submitted, as you will see later on.

The same section can be built by using the <fb:editor> element (see more at Fb:editor):

<div id="data_selected_content2" >

   <fb:editor labelwidth="200">

   <fb:editor-custom label="Baby">
      <span id="spanSelectedObject2"
            style="font-weight: bold;
            font-style: italic;
            font-variant: normal;"></span>
   </fb:editor-custom>

   <fb:editor-custom label="Needs">
      <asp:DropDownList ID="listObjectAction2"
                        runat="server"
                        CssClass="listElement" ></asp:DropDownList>
   </fb:editor-custom>

   <fb:editor-buttonset>
      <fb:editor-button value="Send to Comrade"/>
   </fb:editor-buttonset>

   </fb:editor>

</div>

The result is this:

4. Developing Facebook Application with .NET: Submitting Form Information and Adding Client-Side Validation Using FBJS Dialogs

So, at this point you have a nice looking form that presents a list of items, allows user to select a Friend... But, wouldn't it be nice if the appliction could pass that information back to you?

Do you remember the server-side button buttonSend I had:

<div id="data_selected_content1" style="display:none">

<span class="detached_label">Baby

   <span id="spanSelectedObject1"
         style="font-weight: bold;
         font-style: italic;
         font-variant: normal;"></span>

needs:
<asp:DropDownList ID="listObjectAction1"
                  runat="server"
                  CssClass="listElement" ></asp:DropDownList>
...and then off to
<fb:friend-selector idname="textSelectedFriend" />

<asp:Button ID="buttonSend"
            runat="server"
            Text="Send"
            CssClass="inputsubmit"
            OnClick="buttonSend_Click" />
</span>

</div>

When the user clicks this button, the page is supposed to a) check user input—if a Friend is entered; and b) submit information back.

Check the user input when the form is about to be submitted. On the APSX page, I added the following JavaScript (FBJS):

<script>
   function displayError(title, message, context)
   {
       new Dialog(Dialog.DIALOG_CONTEXTUAL).
          setContext(context).showMessage(title, message );
   }

   function check_form(form)
   {
      if ( form == null)
         { form = document.getElementById('formDataContent');}

      var params=form.serialize();
      if (params.textSelectedFriend==null ||
         params.textSelectedFriend=='' )
      {
         displayError("Error", "Please select a Comrade!" ,
            document.getElementById('data_selected_content1') );
         return false;
      }
      else 
      {
         return true;
      }
   }
</script>

And, in the code:

new protected void Page_Load(object sender, EventArgs e)
   {
      ...
      ClientScript.RegisterOnSubmitStatement(this.GetType(),
         "submitformDataContent", "return check_form(this);");
      ...
   }

Here, I'm using Dialogs provided by FBJS (see more at Dialogs), and the result is stunning!

If the input passes the validation check (in this example, you only check whether the user selects/enters a Friend), Then, the page is submitted and you have a chance to save selected data into the database. Hooray!

protected void buttonSend_Click(object sender, EventArgs e)
{
   string selectedFriendID = String.Empty;
   try
   {
      selectedFriendID = Page.Request.Form
         ["textSelectedFriend"].ToString();
   }
   catch
   {
      //oh-ho, no friend is selected!!!
      return;
   }

   //save selected action and friend to database:
   bool result = false;
   string errorInfo = String.Empty;
   string connectInfo = Settings.ConnectInfo();
   string facebookUserID = this.FBService.GetUserInfo().UserId;
   m_FacebookDB = new FacebookDB(facebookUserID, connectInfo);

   string applicationUserID = this.textApplicationUserID.Value;
   if ( applicationUserID == String.Empty)
   {
      this.labelFBDashboard.Text = "Application User ID is missing!";
      return;
   }

   string applicationUserObjectID = this.textSelectedObject.Value;
   if (applicationUserObjectID == String.Empty)
   {
      this.labelFBDashboard.Text = "Application Object ID is missing!";
      return;
   }

   string selectedActionID =
      this.listObjectAction1.SelectedValue.ToString();
   string expandedUserObjectActionText = String.Empty;
   string notificationTextToFriend = String.Empty;
   result = m_FacebookDB.DoObjectAction_And_Do
      _SendToFriend(applicationUserID,
                    applicationUserObjectID,
                    selectedActionID,
                    selectedFriendID, 
                    out notificationTextToFriend,
                    out errorInfo);

   if (!result)
   {
      this.labelFBDashboard.Text =
         "Failed to perform selected action!" + errorInfo;
      return;
   }
}

* Notice the reference to Page.Request.Form["textSelectedFriend"] form field, from <fb:friend-selector> element. No, you didn't create this element on the page; instead, the Facebook platform added it "dynamically".

You also can use other types of Dialogs; for example, DIALOG_CONTEXTUAL:

To display such a CONTEXTUAL dialog, you can use "inline" JavaScript (FBJS):

<div id="data_selected_content1" style="display:none">

   ...
   <a href="#" onclick="new Dialog(Dialog.DIALOG_CONTEXTUAL).
      setContext(this).showMessage('Selected Object',
        'This is the object you\'ve selected'); return false;">
   <span id="spanSelectedObject1"
         style="font-weight: bold;
         font-style: italic;
         font-variant: normal;"></span></a>

   ...
</div>

Or, to display a POPUP

Facebook Application Development

5. Developing Facebook Applications with .NET: Using iframe in FBML

If you need to "insert" a page within your application, the FBML canvas, you can use the <fb:iframe> element (see more at Fb:iframe).

For example, I use the <fb:iframe> element to reference an APSX page to retrieve the user's IP address, by using Request.ServerVariables["REMOTE_ADDR"] (remember that the FBML application is within a canvas, within Facebook... so you'll get something like 204.15.23.168, which is the IP address of the Facebook server, not of your user). Then, based on the given IP address, I can display various information; for example, the weather forecast:

In page the code, to reference the <fb:iframe> element, here's what you do:

...
<div style="text-align:right;
            position: relative;
            bottom:1%;
            width:99%">
   <fb:iframe src="http://www.siccolo.com/fbtestappsiccolo/
      clientdata.aspx" style="width: 99%;
                       height:135px" smartsize="false"
                       frameborder="no">
   </fb:iframe>
</div>
...

This is very similar to using the <iframe> HTML element.

6. Developing Facebook Applications with .NET: Using FBJS AJAX with ASP.NET/C#. Display Dialog with Dynamic Content, by Using FBJS POPUP Dialogs with ASP.NET/C#

One of the features of FBML and FBJS is ability to display standard dialogs (see "Using FBJS Dialogs"). You can use one of the standard dialogs to display dynamic content; for example, a list of records from SQL Server database:

To do this, first of all I needed to add a link to the main GridView (see "Using <asp:GridView> with FBML"):

...
<asp:GridView ID="gridSelectObjects"
              runat="server"
              AutoGenerateColumns="false"
              style="width:80%;
              text-align:center"
              align="center">
   <Columns>
      <asp:TemplateField ItemStyle-Width='180px'
                         ItemStyle-Wrap=false>
         <ItemTemplate>

            <a href="#" onclick="select_object(<%# Eval("object_id")%>,
               '<%# Eval("type")%>',
               '<%# Eval("description")%>');return false;"
                    style="color:Black;
                    background-color:Transparent;
                    border-color:Transparent;
                    border-style:None;">

            <img src="http://www.siccolo.com/fbtestappsiccolo/
                         images/select.gif"
                 border="0"
                 align="center"
                 title="select <%# Eval("description")%>"/>
                 select <%# Eval("description")%></a>
         </ItemTemplate>

      </asp:TemplateField>

         <asp:TemplateField ItemStyle-Width='180px'
                            ItemStyle-Wrap=false>
         <ItemTemplate>

            <a href="#" onclick="show_object_info
               (<%# Eval("object_id")%>);return false;"
                    style="color:Black;
                    background-color:Transparent;
                    border-color:Transparent;
                    border-style:None;">
                    show <%# Eval("description")%>'s history</a>
            </ItemTemplate>

      </asp:TemplateField>

   </Columns>
      <AlternatingRowStyle BackColor="#f7f7f7" />
</asp:GridView>
...

So, when the user clicks the "show...history" link in the main Grid, the application shows records from the database. To get anything back from database, or from the server-side, the application needs to "post-back." Fortunately, FBJS has built-in support for AJAX (see more at Mock AJAX). So, you can post back to the server and patiently wait for a reply:

<script>
   function show_object_info(object_id)
   {
      var ajax = new Ajax();
      ajax.responseType = Ajax.FBML;
      ajax.ondone = function(data) 
      {
         var dlg = new Dialog();
         dlg.showMessage('Object Action History', data );
      }


      ajax.post("http://www.siccolo.com/fbtestappsiccolo/
                 object_action_history.aspx?id=" + object_id);
   }
</script>

Where the object_action_history.aspx ASP.NET page:

<%@ Page Language="C#"
    AutoEventWireup="true"
    CodeFile="object_action_history.aspx.cs"
    Inherits="_ObjectActionHistory" %>

<!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>Object Action History</title>
</head>
   <form id="formDataContent" runat="server" >
   <div style="text-align:center">
   <asp:GridView ID="gridSelectObjects"
                 runat="server"
                 AutoGenerateColumns="false"
                 style="width:95%"> </asp:GridView>
   </div>
   </form>
</html>

Basically, object_action_history.aspx, when it returns from ajax.post() to ajax.ondone(), gives nothing more, just a "rendered" Grid View. Then, in JavaScript (FBJS), on ajax.ondone, you take that data and "shovel" it down Dialog.showMessage():

<script>
   function show_object_info(object_id)
   {
      //var dlg =
      // new Dialog().showMessage('.. Traveling Babies ..',
      // 'Select a baby and send it to your comrade...');

      var ajax = new Ajax();
      ajax.responseType = Ajax.FBML;
      ajax.ondone = function(data) 
      {
         var dlg = new Dialog();
         dlg.showMessage('Object Action History', data ); 
      }


      ajax.post("http://www.siccolo.com/fbtestappsiccolo/
                 object_action_history.aspx?id=" + object_id);
   }
</script>

7. Developing Facebook Applications with .NET: Using Facebook Notifications

So far, so good. You have a Facebook-alike interface, the user can select data, and the selected data is being saved in the database. But, I forgot that Facebook really is a social network. it's about social interactions... You can add a "social interaction" in a form of user notification to your Facebook Application.

Thanks to the Facebook Developer Toolkit library, notifications are very easy to do:

protected void buttonSend_Click(object sender, EventArgs e)
{
   string selectedFriendID = String.Empty;
   try
   {
      selectedFriendID = Page.Request.Form
         ["textSelectedFriend"].ToString();
   }
   catch
   {
      //oh-ho, no friend is selected!!!
      return;
   }

   ...
   result = m_FacebookDB.DoObjectAction_And_Do
            _SendToFriend(applicationUserID,
                          applicationUserObjectID,
                          selectedActionID,
                          selectedFriendID, 
                          out notificationTextToFriend,
                          out errorInfo);
   ...
   string notification_result =
       FBService.SendNotification(notificationTextToFriend,
          selectedFriendID);
   ...
}

To send a notification, you need to call the SendNotification() method and pass the notification text and ID of the Facebook user. In this code, the ID is of the selected Friend. Because I'm too lazy, the notificationTextToFriend notification text is built in the stored procedure, not in the application code. But, you can "compose" your notification in the code as well. The result is something like this:

where, in my stored procedure, I can do something like this:

declare @application_path varchar(255)
set @application_path = 'http://apps.facebook.com/fbtestappsiccolo'

declare @notification varchar(8000)
select @notification =
   ' on [' + convert(varchar(10), action_date, 101) + ' ' +
      convert(varchar(8), action_date, 108) + '] ' +
   ' sent '+
   '<a href="' + @application_path + '">' + o.description +
      '</a>' + ' to you!' +
   ' <fb:name uid="' + @facebook_user_id + '" /> already ' +
      replace( oa.action_performed_text_ex,
               '<object_description>',o.description )

And that's it for Part 1.

Credits

You can see this sample application on Facebook: Traveling Babies.



About the Author

Al Siks

check out the free SQL Server Management Tool for mobile devices at Siccolo

Comments

  • There are no comments yet. Be the first to comment!

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

  • Not long ago, security was viewed as one of the biggest obstacles to widespread adoption of cloud-based deployments for enterprise software solutions. However, the combination of advancing technology and an increasing variety of threats that companies must guard against is rapidly turning the tide. Cloud vendors typically offer a much higher level of data center and virtual system security than most organizations can or will build out on their own. Read this white paper to learn the five ways that cloud …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds