Creating a New Facebook Canvas Application
The steps below will help you to create a functional ASP.NET Web site to be used as an FBML canvas application featuring FBML markup, the feed form, and integration with the Facebook API via the Facebook Developer Toolkit (FDT). The project will be built using Visual Studio 2008 and .NET Framework 3.5, although other platforms can also utilize the Facebook Platform.
- Register a Domain Name
- Since Facebook will have to contact your server to get the FBML markup, even during development, you will need to have a fully-qualified domain name (FQDN) for any FBML canvas application development. This part of the setup depends on who you use for domain name registration. See the links at the end of this guide for suggestions.
Create a Facebook Application
In order to develop and integrate with Facebook, you must install the Facebook Developer Application to your Facebook Account. This application is used to manage custom application settings, publish the application and access the Facebook Platform.
- Login to Facebook.com
- Navigate to http://www.facebook.com/apps/application.php?id=2345053339 and install the application.
In the bottom-left corner of the page, click the
Developer application icon. At the top of the Developer page, click "Setup New Application". Enter the application name and agree to the terms of service. The resulting page is the management home for the new application. Take note of the API Key and Secret, which will be used by your site to access the Facebook API.
.jpg)
- Enter any desired application settings, icon images, etc.
- Navigate to the Canvas section of the application settings. Enter a Canvas Page URL, which will be the URL that users will use to visit your application.
- Enter the URL for the root of your site as the Canvas Callback URL. Make sure that it ends in a slash ("/"), otherwise Facebook may not deal with it correctly. This is the URL which Facebook will use to retrieve the FBML for your site. Note that this must be a publicly-visible URL—Facebook cannot contact your server if you try to use localhost.
Make sure the Render method is set to FBML. Save the changes.
.jpg)
- During development you may also wish to enable the Advanced tab's Sandbox Mode, which limits Facebook interaction to only the developer accounts listed in the application.
- Create Template Bundles
- Navigate to the Feed Template Console at http://developers.facebook.com/tools.php?feed
- Select your application in the drop-down and click Next.
- On the Create a One Line Story template page, click Next (this template will not be used).
- On the Create a Short Story template page, add a new template (both title and body) using the placeholder tokens {*actor*} and {*emote*}. For example, our template title was "{*actor*} likes short story templates.", and the body was "{*actor*} is feeling sort of {*emote*}". Make sure to include the following sample data: {"emote":":-)"}
- Click Next. On the Create an Action Link screen, click skip.
- Click Register Template Bundle. When the success message pops up, copy the template bundle ID and save it somewhere for later on. If you close the popup too soon, you can find the template bundle ID at http://developers.facebook.com/tools.php?templates.
- Repeat this one more time to create a second template bundle, except this time using {*actor*}, {*emote*}, and {*emoteaction*} as placeholder tokens in your template body, and the following sample template data: {"emote":":-)","emoteaction":"smile"}
- Download and Open Sample
- Edit Settings in web.config
- In the project, open web.config. Near the top of the file, you should see some settings in the <appSettings> element. Change the values for those settings to the following:
- APIKey: your API key
- Secret: your application secret
- Callback: your callback URL
- Suffix: The suffix of your canvas page URL. For example, for a site located at http://apps.facebook.com/claritysmiley/, the suffix is claritysmiley.
- TemplateID1: the ID of the first template bundle you created
- TemplateID2: the ID of the second template bundle you created
- Build and Deploy Application
- Click the Build menu and select Build Solution.
- Take the entire contents of the project directory and copy them to the hosting server, into the folder set up for this application. This step may differ depending on your hosting setup.
- Run Application
- Navigate to your canvas page URL (http://apps.facebook.com/your-app-suffix/). The first page does not require users to add the application, so you should be able to see the first screen immediately.
- Click the Home tab. This page does require that the app be added to the user's profile, so an "Allow Access?" page will appear.
- On the "Allow Access?" page, click "Allow". You may have to click on the Home tab again to go to the proper page.
- You now have a fully working Facebook FBML canvas application. Enjoy!
Authentication
In this sample, I used the CanvasFBMLMasterPage to take care of authenticating the session with Facebook. This class takes care of the entire authentication process; all you have to do is give the application your API key and secret, as we did in the web.config above, as well as letting it know which pages require the user to have an authenticated session. It may be useful to allow certain pages to be viewed without an authenticated session so that users who have not yet added your application can see it and discover why it might be interesting to them. Also, some parts of the Facebook API are available without an authenticated session.
Since I also needed a master page with logic and markup specific to this application, I created a custom master page that inherits from CanvasFBMLMasterPage. In the markup for the custom master page, it references its code-behind with the CodeBehind attribute:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="FBMLMaster.master.cs"
Inherits="FBMLSample.FBMLMaster" %>
Within the code-behind, the custom master page is set to inherit from CanvasFBMLMasterPage:
public partial class FBMLMaster : Facebook.Web.CanvasFBMLMasterPage
Each page is set to use this custom master page by setting the MasterPageFile attribute in the Page directive as well as creating a MasterType directive. The easiest way to set up the content pages is to create them through the master page: just right-click on the master page in Solution Explorer and select "Add Content Page". The new page will have the correct MasterPageFile attribute set as well as each of the <asp:Content> elements used by the master page, although you will have to set the MasterType directive manually:
<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/FBMLMaster.Master"
CodeBehind="Home.aspx.cs" Inherits="FBMLSample.Home" %>
<%@ MasterType VirtualPath="~/FBMLMaster.Master" %>
Each page that requires the user to have added the application will also need to set the master page's RequireLogin property. This will make sure that the master page authenticates the session with Facebook:
protected void Page_PreInit(object sender, EventArgs e)
{
Master.RequireLogin = true;
...
}
There are times when you might not want to use that Masterpage. For those times, we have added a logincontrol called FBMLCanvasLoginControl. This control needs to be included on each of your FBML canvas pages and it will handle the authentication handshake.
<Facebook:CanvasFBMLLoginControl runat="server" ID="login" RequireLogin="true"/>
If you use the login control, you will need to use it to access the API in your code-behind.
ASP.NET MVC Support
The supported approach for writing FBML canvas applications using ASP.NET MVC involves two facets.
- Add an attribute for controller actions to handle authentication.
- Use an extension method to the controller to get an instance of the API object to make calls to Facebook.
[HandleError]
public class HomeController : Controller
{
private const string APIKEY = "yourkey";
private const string SECRET = "yoursecret";
[FacebookAuthorization(IsFbml = true, ApiKey = APIKEY, Secret = SECRET)]
public ActionResult Index()
{
Api api = this.GetApi(APIKEY, SECRET);
var user = api.Users.GetLoggedInUser();
return Content("Hello, " + user.ToString());
}
public ActionResult About()
{
return View();
}
}
When using this attribute, you do not need to include the apiKey and secret (in either the attribute or GetApi call) if these are specified in your web.config. In the above code, you will see the Authorization attribute added to the Action method and then a call to the extension method GetApi to get the Instance of the Facebook.Rest.Api object that you need to make any of the necessary rest calls.
Making REST Calls to the API
If you're using the CanvasFBMLMasterPage, making calls to the Facebook API over its REST-like interface is a snap. The master page has an API property, and all of the API calls can be made through the child objects of that object. Each of the methods is structured as close to the actual Facebook method as possible, while still being strongly-typed and following typical .NET conventions.
For example, here's the code we used to set the markup for a box on the user's profile through the profile.setFBML method:
this.Master.Api.Profile.SetFBML(this.Master.Api.Session.UserId, null, getUserProfileBox(), null);
Each of the other methods are similar. The return values are also strongly-typed values, based on the schema from Facebook. For example, if you wanted to find out the name of a user with a certain ID, you might use code like this:
user someUser = this.Master.Api.Users.GetInfo(userId);
string name = someUser.name;
Each of the CanvasBasePage/CanvasMasterPage classes works similarly, so that making calls to the Facebook API is as easy as possible.
FBML
As described above, FBML is an extension of HTML to allow developers to more tightly integrate their applications with Facebook. The Facebook-specific FBML tags were used in several different places in this sample. For example, here is the code used to create the tabs on each page:
<fb:tab-item title="Public" href="default.aspx" selected="<%=Convert.ToInt32(selected=="default") %>"/>
<fb:tab-item title="Home" href="home.aspx" selected="<%=Convert.ToInt32(selected=="home") %>" />
<fb:tab-item title="My Smiles" href="mysmiles.aspx"
selected="<%=Convert.ToInt32(selected=="mysmiles") %>"/>
<fb:tab-item title="New Smiley" href="newsmiley.aspx"
selected="<%=Convert.ToInt32(selected=="newsmiley") %>"/>
<fb:tab-item title="Send Smiley" href="sendsmiley.aspx"
selected="<%=Convert.ToInt32(selected=="sendsmiley") %>"/>
</fb:tabs>
Or as another example, here is the multi-friend-input control used to select friends to send a smiley to. Although it requires very little markup, it contains a lot of funtionality, and is automatically styled to match the rest of Facebook:
<fb:multi-friend-input />
.jpg)
FBML Server Controls
In order to simplify the ASP.NET programming experience of building an FBML application. We have supplied a set of Server Controls that support the entire FBML namespace. These controls can be used in a manner similar to typical ASP.NET server controls and will render FBML as specified on the Facebook wiki. This will provide a fully supported server programming model for FBML. These controls are not yet supported in the ASPX design surface, but they will be in the toolbox and will provide full IntelliSense support in the Source view of an ASPX page. The code listing below provides a glimpse at how a few of these controls can be placed on an FBML page. Each of these controls supports rendering XFBML compliant text (for any that are supported in XFBML)
<%@ Register Assembly="Facebook.Web" Namespace="Facebook.Web.FbmlControls" TagPrefix="fb" %>
<fb:Fbml ID="Fbml1" runat="server">
<ContentTemplate>
<fb:IfSectionNotAdded ID="IfSectionNotAdded1" runat="server" Section="Profile">
<ContentTemplate>
Display our box on your profile!<br />
<fb:AddSectionButton ID="AddSectionButton" runat="server" Section="Profile"></fb:AddSectionButton>
</ContentTemplate>
</fb:IfSectionNotAdded>
<fb:Name ID="Name1" runat="server" Uid="loggedinuser"></fb:Name>
<fb:Board ID="Board" runat="server" Xid="aaaa" Title="TTT"></fb:Board>
<fb:Title ID="Title" runat="server" Text="T3"></fb:Title>
<fb:Dialog ID="Dialog" runat="server" Identifier="Dialog">
<ContentTemplate>
<fb:DialogTitle ID="dialogtitle" runat="server" Text="Title of Dialog"></fb:DialogTitle>
<fb:DialogContent ID="content" runat="server">
<ContentTemplate>this is the content of the dialog</ContentTemplate>
</fb:DialogContent>
</ContentTemplate>
</fb:Dialog>
<fb:Wall ID="wall" runat="server">
<ContentTemplate>
<fb:WallPost ID="wallpost" runat="server" Uid="1">
<ContentTemplate>
this is some stuff<br />
<fb:WallPostAction runat="server" ID="WallPostAction" Href="http://localhost" Text="the text for the link"></fb:WallPostAction>
</ContentTemplate>
</fb:WallPost>
</ContentTemplate>
</fb:Wall>
</ContentTemplate>
</fb:Fbml>
Feed Form
The feed form is a method for you to post stories and other information about what users have been doing on your application onto the Feed system. Once a story has been posted to a user's feed, all of their friends can see it, making the feed a great method for the users to tell their friends what they've been up to, as well as for you to tell more users about your application.
To use the feed form, you first have to have a template bundle set up (which was done during the application setup). Then you just need to make a JavaScript call to FB.Connect.showFeedDialog with the correct parameters, including the data to fill the template with. This will pop up a dialog box displaying the story, and asking the user if they would like to publish the story or not:
var image = image_src + '/smile' + id + ".jpg";
var template_data = {'mood': title,
'emote': emote,
'mood_src': image,
'images' : [{'href':base , 'src' : image}]};
var ajax = new Ajax();
ajax.responseType = Ajax.RAW;
ajax.post(callback+'handlers/jsFeed.aspx', {'picked':id});
Facebook.showFeedDialog(template_id, template_data, '', [],
function() {document.setLocation(base + 'mysmilies.aspx');});
.jpg)
More information about how to set up the template data can be found on the Facebook Developers wiki.
If you need to do something after the feed is sent, you can send a callback parameter, which in the above example was the final parameter sent to Facebook.showFeedDialog. Once the feed dialog is closed, the callback function will be called. In this sample, the callback navigates the user back to mysmilies.aspx.
Extended Permissions
In order to perform certain actions on the Facebook Platform (such as sending e-mails and publishing items to a user's stream), your application has to ask the user for special permissions. Facebook calls these "extended permissions".
There are several ways to ask users for these extended permissions. In this sample, we used the <fb:prompt-permission> tag. This tag allows you to turn a piece of text into a link that, when clicked, will pop up a dialog to let the user grant your application a specific permission:
<fb:prompt-permission perms="email">Enable Email</fb:prompt-permission>
You can also use the users.hasAppPermission API call to check if the user has a specific permission:
if (Master.Api.Users.HasAppPermission(Enums.ExtendedPermissions.email))
{
// Send an e-mail
}
.jpg)
In addition, the FBMLBasePage, MasterPage, login control and MVC attribute all support a property that allows you to set the permissions required by your application. If you use this property, the authentication process with Facebook will include a check for the required permissions and will redirect the user to a page requesting those permissions prior to displaying your canvas application.
For example, if you are using the FBMLMasterpage you can add a constructor to your master page where you specify the permissions as follows:
public partial class FBMLMaster : Facebook.Web.CanvasFBMLMasterPage
{
protected string selected = string.Empty;
public FBMLMaster() : base()
{
this.RequiredPermissions = new List<Enums.ExtendedPermissions>() {
Enums.ExtendedPermissions.publish_stream };
}
Alternatively, if you are using the login control, the syntax would be:
<%@ Register TagPrefix="Facebook" Namespace="Facebook.Web" Assembly="Facebook.Web" %>
<Facebook:CanvasFBMLLoginControl runat="server" ID="login" RequireLogin="true"
RequiredPermissions="offline_access,publish_stream"/>
Lastly, if you are using the MVC action attribute, the model is similar to the LoginControl.
[FacebookAuthorization(IsFbml = true, ApiKey = APIKEY, Secret = SECRET, RequiredPermissions="publish_stream,offline_access")]