Facebook Connect Action Filter for ASP.NET MVC

§ November 19, 2009 05:50 by beefarino |

I've got a few ASP.NET MVC projects burning that will be leveraging Facebook Connect for user identity and profile data.  I was impressed with how quickly I could get things running using the Facebook Developer Toolkit.  Well-documented, good examples, and the API makes sense. 

One of Connect's basic features is to provide user identity to other web applications via the "Connect Button".    Adding this feature to your ASP.NET site is already well documented by Clarity Consulting and others; here I will show you how I'm seamlessly folding this feature into the ASP.NET MVC request-handling pipeline using a custom Facebook Connect ActionFilterAttribute. 

The code for the Action Filter is pretty thin:

using System;
using System.Web;
using System.Web.Mvc;
using Facebook.Rest;
using Facebook.Session;
namespace MyWebSite.Filters
{
    public class FacebookConnectAttribute : ActionFilterAttribute
    {
        // obviously, you need to fill these in with your own application's values
        const string myFacebookApiKey = "...";
        const string myFacebookSecret = "...";
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var connectSession = new ConnectSession( myFacebookApiKey, myFacebookSecret );
            if( connectSession.IsConnected())
            {
                filterContext.Controller.ViewData["FBConnected"] = true;
                var api = new Api(connectSession);
                filterContext.Controller.ViewData["FBUser"] = api.Users.GetInfo();
            }
            else
            {
                filterContext.Controller.ViewData["FBConnected"] = false;
            }
        }
    }
}

In my case, I'm making use of Facebook Connect before the controller's result is executed; e.g., before any view is resolved and rendered.  I could just as easily executed this filter before the action is executed by overriding the OnActionExecuting method.  Lines 11 and 12 contain my site's Facebook API key and secret (no prizes for guessing why I left those out of this example), which are used in line 15 to create the toolkit ConnectSession instance.  The filter can use this instance to check if the user has connected with my site and, if they have chosen to connect, fetch some of their profile data (line 20).

To place this filter into the request processing pipeline, just decorate the controller class definition with the filter attribute:

namespace MyWebSite.Controllers
{
    [HandleError]
    [MyWebSite.Filters.FacebookConnect]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        // ... 

With the attribute in place, my Facebook Connect filter will be used during every request that invokes this controller, and the dynamic view data will contain the user's connected status and identity information:

<!-- 
    ... 
-->
<div id="logindisplay">
    <%
        if ((bool) ViewData["FBConnected"] == false) 
        {
    %>
    <fb:login-button v="2" size="xlarge" onlogin="window.location.reload();">Connect</fb:login-button>
    <%
        }
        else
        {
            var user = (user) ViewData["FBUser"];
            Response.Write("Welcome, " + user.first_name + "!");
        }
    %>
</div> 
<!-- 
    ... 
-->

The net result of this minimal effort: the entire site now has access to the user's Facebook identity and profile information once they choose to connect.

I'm still playing with the toolkit, and will hopefully have more to post soon!



Hacking for Fun and ... more Fun

§ November 12, 2009 16:57 by beefarino |

We had big fun tonight at the first Charlotte ALT.NET user group hack night.  Special thanks to Mike Linnen and Xpient for hosting the event.

The theme of the evening was taken from the recent Raleigh and Carolina Code Camps: Rock Paper Scissors.  Teams coded modules to play rounds of RPS, uploaded their assembles to a server, and duked it out over three rounds of riveting RPS action.

I was a bit apprehensive about the event, mostly afraid of looking like an idiot in front of some really smart people.  But once the hacking started we all fell into a groove and it turned out to be a lot of fun.  I chose to try and predict my opponent's actions using a bit of fuzzy logic and some statistics.  It worked fairly well through the first two rounds of the tournament, but I was given a resounding spanking in the final round by @micahlmartin and @DeveloperInfra.  In the end, a three-way tie for first place was resolved with a fourth round, where  @micahlmartin edged us out with a perfect score!

I may blog about my approach to the puzzle some other time, but I wanted to jot down some things I noticed this evening.

When I'm under a time contraint, I can get a lot of work done quickly.  I don't know why this surprises me, but after tonight I'm considering adding stricter timeboxes to my daily GTD routine.

Hacking is fun.  Lately coding has started to feel monotonous.  A lot of the projects I've got going on are hitting non-techcnial walls, and moving forward is proving to be difficult.  It was a blast to hammer out some code without those pesky business boundaries to bring it all down.  I think scheduling some regular geek time to work on things like Project Euler or some code katas would be a good idea - no expectations past my own enjoyment.

Overall a very positive experience, thanks everyone!



it's been noticed...

§ October 1, 2009 01:22 by beefarino |

Just ignore this post, I just need to release some steam...

We just had an emergency team meeting.  The topic: it's been noticed by the executives that we're not always around when they are.  Someone needed something and one of us wasn't there to oblige.  That must have really chapped their hide.  

Well, I've noticed some things too.  Here's what I've noticed:

  • I'm VPN'ed into work at midnight fixing the build someone else broke;
  • I'm constantly tweaking our unit tests to keep them working as the rest of the team gets to plod on to greenfield pastures;
  • I'm responding to support emails at 2am;
  • I'm answering the support phone at 4am;
  • I still make the 9:30am scrum;
  • I bust my hump as a principal developer on a project, only to hear the executives single-out my superiors to praise for my work;
  • After four rounds of layoffs, I've taken on so many roles here I've lost track;
  • I haven't dropped the ball on any of my responsibilities (or if I have, no one has let me know about it);
  • I've been willing to drop my life for days at a stretch to make emergency trips to fix client issues;
  • I'm frequently the last one out the door at the end of the day;
  • I see my kids for maybe 90 minutes a day;

... and more thing I noticed: the people I work for only notice me when I'm not around.

 



when a property should be a method

§ September 29, 2009 13:46 by beefarino |

I posted a quip on twitter this evening:

note to devs: a boolean property that expects to be set to only a false or true value (and throws otherwise) should be a method instead.

Several people prodded me for more an explanation, so here it is.

Say you have a default feature, and you want to offer consumers of an object the ability to disable the feature.  One common practice is to use a boolean property, consumed like so:

// ...
thingWithFeature.DisableFeature = true;
// ... 

It's simple and makes sense.  However, I'm finding a lot of hardware SDKs are throwing exceptions when you try to set such a property to false, in this example indicating that you do not want to disable the feature (forgive the double negative).  In other words, the property is settable to one specific value.  E.g., the SDK implementation looks something like this:

// ...
public bool DisableFeature
{
    set
    {
            if( ! value )
            {
                throw new ArgumentException();
            }
            
            // ... disable the feature when the value is false
    }
}
// ...

As a consumer of this object, there is only one path I can take with the DisableFeature property that will result in a valid operation.  The property syntax goads the consumer into failure by offering up an illusion of functionality that does not exist.  As a developer, I have every reason to assume that a boolean property can be set to true OR false.  If one of those is not appropriate, then the property isn't a property, it's a method:

// ...
public bool DisableFeature()
{
    // ... disable the feature
}
// ...

As a method, the one valid path is captured unequivocally, and it's not possible for consumers to assume they can do more than they are allowed by the SDK.