Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Facebook Application Development with FBML, FBJS, ASP.NET and C#

0.00/5 (No votes)
13 Mar 2008 3  
Build simple and sophisticated Facebook Apps with FBML, ASP.NET

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's the Step-by-step Guide to Creating an Application and Creating a Facebook Application, as well as 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 an SQL Server database.

As you may know, a Facebook application is "hosted" within a Facebook Canvas Page, and the canvas page is within the Facebook frame (kinda like a Russian doll house, eh?). A Facebook application can be FBML or... just take a look at the 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 the Facebook Developers Application.

In this Facebook Application, I am using the Facebook .NET Toolkit found at the 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 we're using the CanvasFBMLBasePage base class

Developing Facebook Application with .NET
Create a Sample User Presentation using ASP.NET and FBML (Building a Facebook Canvas Page Using ASP.NET and FBML)

So, let's say I have data in an SQL Server database:

objects_list_sql1.gif

...and I want to display it in my Facebook Application, for example, using the GridView control like this:

objects_list_grid2.gif

How do we go about developing this? First (or not so first) thing first: create or add a new application in Facebook Developers. I have mine set up as:

facebook_app_setup3.gif

Now open your favorite Visual Studio (I am using Visual Studio 2005) and start/create a new ASP.NET website. 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:

vs_project_setup4.gif

In the first (and only) ASP.NET form (chances are, it's called Default.aspx), open the page and add the 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 Applicatioin: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. We're using FBML and it will be hosted inside the Facebook canvas, so there's no body. Switch to "code view" and let's add some code:

using Facebook;
using Facebook.WebControls;

public partial class _App : CanvasFBMLBasePage 
{
    //keys for FBTestApplication:
    private const string FACEBOOK_API_KEY = 
        "xfxfxdx7xbx7xbxfxaxdx<a href=
        "http://www.siccolo.com" target="_blank">siccolo</a>";
    private const string FACEBOOK_SECRET = 
        "dx8xfx9x8x1x<a href=
        "http://www.siccolo.com" target="_blank">siccolo</a>2x4x1xfx2xdx";
    
    //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;

            DataSet objectList = null;// new DataSet("ObjectList");
            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;
        }
    }
}        

FacebookDB is a middle layer to interface with the SQL Server database. However, let's also explore the options that FBML adds to your Facebook Application, so we can create a Facebook-like application, something like this:

interface_15.gif

...where:

With the FBML "approach," we can put FBML tags right into the ASPX page or have a web application generate them dynamically. To add the "Facebook dashboard," I am using 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 is:

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;
    }

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

Developing Facebook Application with .NET
Adding User-page Interactions with FBML and FBJS, Allowing to Select a Friend

As you may know, you can use FBJS on FBML pages. So, let's modify the 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 the calls to select_object() JavaScript (FBJS) for each row. So, when the user clicks on the "select..." link of the grid row, the page will display the selected row and will allow the user to perform some actions on selected items:

objects_list_grid_select_item6.gif

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, my JavaScript (FBJS) function is:

<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'm using Animation() to show the DIV element; see FBJS/Animation for more information. As you can see, in order to change SPAN innerText, I'm using the setTextValue() method. For a button, I'm using setValue(). To provide the user with the ability to select a Friend, we can add the <fb:friend-selector idname="textSelectedFriend" /> FBML element (more at Fb:friend-selector).

fb_friend_select7.gif

* Notice the idname attribute of the <fb:friend-selector> element. It is the name of the hidden form element that contains the user ID of the selected friend when the form is being submitted, as we will see later on. The same section can be built 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:

fb_editor8.gif

Developing Facebook Application with .NET
Submitting Form Information, Adding Client-side Validation and Using FBJS Dialogs

So, at this point we have a nice-looking form that presents a list of items and allows the user to select a Friend... but it would be nice if the application could pass that information back to us, yeah? 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 on this button, the page supposed to a) check user input, i.e. if a Friend is entered and b) submit the information back. Let's check user input when the form is about to be submitted. On the ASPX page, I added 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(), 
        "sudmitformDataContent", "return check_form(this);");
    ...
    }    

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

client_side_validation_using_dialog9_small.GIF

If input passes the validation check (in this example, we only check if the user selects/enters a Friend), then the page is submitted and we 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 the Page.Request.Form["textSelectedFriend"] form field from the <fb:friend-selector> element. No, we didn't create this element on the page. Instead, the Facebook platform added it "dynamically." You can also use other types of Dialogs, for example, DIALOG_CONTEXTUAL:

CONTEXTUAL_dialog10.gif

To display such s CONTEXTUAL dialog, we 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:

simple_popup_dialog11_small.GIF

Developing Facebook Application with .NET
Using iframe in FBML

If you need to "insert" a page within your application FBML canvas, you can use the <fb:iframe> element (see more at Fb:iframe). For example, I employ the <fb:iframe> element to reference an ASPX page in order to retrieve a user IP address via Request.ServerVariables["REMOTE_ADDR"]. Remember that the FBML application is within the 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:

fb_iframe12_small.GIF

In the page code, to reference the <fb:iframe> element:

...
<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.

Developing Facebook Application with .NET
Using FBJS AJAX with ASP.NET/C#, Displaying Dialog with Dynamic Content and Using FBJS POPUP Dialogs with ASP.NET/C#

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

popup_dialog13.gif

To do this, first of all I needed to add a link to the main GridView (see above: 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 on the "show...history" link in the main Grid, the application shows records from the database. In order to get anything back from the 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, we 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 object_action_history.aspx is the 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 than just a "rendered" GridView. Then, in JavaScript (FBJS) on ajax.ondone, we 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>

Developing Facebook Application with .NET
Using Facebook Notifications

So far, so good. We have a Facebook-like interface; the user selects data; the selected data is being saved in the database. However, I forgot that Facebook really is a social network: it's about social interactions... Let's add "social interaction" in the form of user notifications to our 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, we need to call the SendNotification() method and pass the notification text and ID of a Facebook user. In this code, the ID is of a selected Friend. Because I'm too lazy, the notificationTextToFriend notification text is built into the stored procedure, not into the application code. However, you can "compose" notification in the code, as well. The result is something like this:

notification_sent14_small.GIF

...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 also see this sample application on Facebook: Traveling Babies.

History

  • 6 March, 2008 -- Original version posted
  • 13 March, 2008 -- Article edited and moved to The Code Project main article base

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here