Azure 1/10 + Facebook Connect 1/2 + Silverlight 2/5 = Fun
Hello all! First off, I want to say this post does not
reflect the way I think authentication should be handled. I don't necessarily
agree with the route Facebook has decided to go with Connect, but that is a
debate I don't really wish to be a part of right now. I would like to
concentrate on the superlatives about Facebook Connect and the possibilities
this opens up to developers. If you wish to discuss the positives and
negatives of the Facebook Connect strategy, please be my guest to comment till
your angelic heart is content.
In this post, I'm going to set up an Azure cloud service project
with a single web role that hosts a Silverlight 2 page, which utilizes Facebook
Connect. I will not go into other portions of the Facebook API during
this post, but I will extend it in a later post. Basically this is 1/10
an excersize in creating a cloud service, 1/2 using Facebook connect, and about
2/5 interactions between JavaScript and Silverlight. Ok, let's get
started.
Things needed:
1)
Azure CTP
2)
Silverlight 2
3)
Facebook account
Let first open Visual Studio 2008 and create an Web Cloud Service and call it AzureFaceBookConnect.

After that is created, let's add our Silverlight Application. We'll call it FaceBookConnect (common theme, huh).

Next let's go set up our developer account with Facebook. For this step you will need a Facebook login. It's not that bad... Plus you might actually like it if you haven't been sucked into the blackhole that is Facebook :). Go to Facebook Developers.

Click on the "Set Up New Application" button. We are going to create an application called {Test Connect} <--- just put whatever you want. Just like code, if you keep your misspellings all the same, then the compiler still loves you :).

So, just agree to everything, and use the old settings editor. You can use the updated settings editor, but the old settings editor has everything we need. Plus, the old settings editor doesn't have as many shinny buttons! In the editor, you should see something like below.

Please make sure to fabricate a good domain name. We will be using it in the near future. Actually, this doesn't need to be a real domain as you can see from mine above. We are going to update our host file, so we can test without having to use a real domain. This can be pretty useful! You can probably find your host file on a windows machine at C:\Windows\System32\drivers\etc. Also, take note of the Callback URL. The callback url will be used by the Facebook client js for authentication, and needs to be of the same base domain.
We will need to create two pages. One to host our client page, and another page to host the callback js for Facebook. You can't tell from above, but I named the callback page FbConnectCallback.aspx.

I love the old faithful, notepad! You can see above, I've added the fake domain, and mapped back to localhost. You will need to specify this domain when you are running your code. Facebook needs to call back to a page which it thinks originates from the base domain. We just want to spoof the domain.
Now onto some code: Default.aspx
<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
TagPrefix="asp" %>
<!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 id="Head1" runat="server">
<title>FaceBookConnect</title>
</head>
<body style="height: 100%; margin: 0;">
<form id="form1" runat="server" style="height: 100%;">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div style="height: 100%;">
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/FaceBookConnect.xap"
MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"
type="text/javascript"></script>
<script type="text/javascript">
FB.init("{You're API Key from setting up you developer account}", "/FbConnectCallback.aspx");
function facebook_onlogin() {
var slcontrol = $get('Xaml1');
slcontrol.Content.slPage.LoggedIn();
}
function login() {
FB.Connect.requireSession(facebook_onlogin);
}
function logout() {
FB.Connect.logout();
}
</script>
</div>
</form>
</body>
</html>
Please pay close attention to the Facebook FeatureLoader script tag, and the fact it is placed in the body. That is manditory for the js to function properly.
Next Up: FbConnectCallback.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FbConnectCallback.aspx.cs" Inherits="AzureFaceBookConnect_WebRole.FbConnectCallback" %>
<!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>FbConnectCallback</title>
</head>
<body>
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
</body>
</html>
Again, pay attention to where the script tag is placed.
Now for the Silverlight: Page.xaml
<UserControl x:Class="FaceBookConnect.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas>
<Button x:Name="btnLogin" Click="Button_Click">
<Button.Content>
<Image Source="Images/connect_light_medium_long.png"/>
</Button.Content>
</Button>
</Canvas>
</UserControl>
This page is just going to host a login / logout button. You may say, that is not very useful. I would agree with you, but I can imagine this could be useful for some other cases that are not quite a simple as this one...
CodeBehind: Page.xaml.cs
#region
using System;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
#endregion
namespace FaceBookConnect
{
[ScriptableType]
public partial class Page : UserControl
{
private bool _loggedin;
public Page()
{
this.InitializeComponent();
this.Loaded += this.Page_Loaded;
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
HtmlPage.RegisterScriptableObject("slPage", this);
}
[ScriptableMember]
public void LoggedIn()
{
this.btnLogin.Content = new Image
{
Source = new BitmapImage(
new Uri("Images/logout_large.png",
UriKind.Relative))
};
this._loggedin = true;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (this._loggedin == false)
{
HtmlPage.Window.Invoke("login");
}
else
{
HtmlPage.Window.Invoke("logout");
this.btnLogin.Content = new Image
{
Source = new BitmapImage(
new Uri("Images/connect_light_medium_long.png",
UriKind.Relative))
};
this._loggedin = false;
}
}
}
}
What are we doing here? Basically, this code invokes login, and logout in js in the page. On login confirmed from facebook, we are alerted via script calling into managed code. I didn't bother styling the button very much... It's pretty lame as far as that goes, but it does achive the end goal -- bring in the designers :)!
Now what should our project look like... I'm going over this pretty quick, because the code will be zipped up down below. I will give you the opportunity to go over it yourself :).

That's pretty much it. Please check out the code below. As always, thank you.. come again!
Twitter: @DavidJustice
Code
