Classic ASP and Facebook Graph API





5.00/5 (12 votes)
Building on a previous article, we now delve into the Facebook Graph API and provide a few useful functions.
Introduction
In a previous article I provided a set of utility functions for connecting your website to Facebook using the Facebook for Websites API. This article builds and improves upon the original app and adds some examples of how we can leverage Facebook's Graph API to provide deeper interaction with Facebook.
Background
This article will build on the same code from the previous article that has been refactored into a class object.
What is the Graph API?
The Graph API is Facebook's way of enabling automation of most UI functions based on a REST-ful interface.
The Graph API makes a request to Facebook at a URL that looks like this: http://graph.facebook.com/ID. The ID is the ID of the Facebook object you are working on. Every object in Facebook has an ID as required by REST. You can find the full set of documentation here: http://developers.facebook.com/docs/reference/api/.
Using the code
Before you use the code, you must create a Facebook Application and have an application ID and secret code. See the first article for details.
In this article, I'll provide the base patterns for working with Facebook data. The code will implement a consistent way of returning data from Facebook so when you access user.hometown (for example), it will always return a value or blank. It will not produce an error if the data is not returned by Facebook. Each function in the new design includes test pages that help verify the function works.
Refactoring the original code
Let's review how the current code differs from the previous article. The main change is that all but a few functions are encapsulated in a class library named fb_utility. The code block below shows the class structure for fb_utility.
''************************************************************
'' A summary of the fb_utility class as found in fb_app.asp
''************************************************************
class fb_utility
dim dictKey
dim dictItem
'' Initialize the fb_utility class
sub Class_Initialize()
'' Initialize KSort values
dictKey = 1
dictItem = 2
end sub
'' get the contents of a web page, include
'' validation that the user is logged in
public function get_page_contents(strURL)
end function
'' Some Facebook API functions require a post
'' this function handles the post request
public function post_page(strURL, strData)
end function
'' Generate a GUID
public Function NewID()
End Function
'' KSort is not required for the new oAuth
'' however you might find it useful
public function ksort(byref objDict )
SortDictionary objDict, dictKey
end function
'' Sort dictionary is called by the ksort function
Function SortDictionary(byref objDict, intSort)
End Function
'' gets the access token from the return
'' authentication request made to Facebook
public function parse_access_token( str )
end function
'' Parses the expires value from the return data
'' provided after an oAuth request to Facebook
'' I have yet to figure out how to make use of this
public function parse_expires( str )
end function
end class
This utility class is re-used by just about every other class and function in the Graph API and initial authorization functions.
The basic request pattern
For the most part, every Graph API request does some basic things: make a call to
fb_utility.get_page_contents
which returns a JSON string which
is then converted to a JSON object for reference. The problem with data returned from Facebook is that if a value is blank or null, the property is not returned.
For example: user.hometown might not be populated by the user you are requesting, as a result the JSON string returned by Facebook will not contain a hometown value.
When the JSON string is converted to an object it will not have a hometown property. As a result, attempting to access user.hometown will trigger a VBScript error.
I call it the "sparse data problem".
To solve the sparse data problem, I include a code block in each class that maps from JSON to a VBScript class to provide a reliable interface for each data object.
Below you will find a pattern for a Facebook Data Type Object implemented in a VBScript class. A call to
Load
and passing the Facebook Object ID will get
the JSON string and a call to load_from_json_object
will perform the mapping.
'' Copy and paste the template below for each new Facebook DTO class
'' A Facebook DTO
class fb_DTO
'' **
'' ** Declare Variables
'' **
'' Default Variables for properties
dim fbu '' Facebook utility object
dim m_token ''
dim m_json_str ''
dim m_graph_url ''
'' Default Internal Variables
'' Object Type Specific Variables
'' **
'' ** property exposure
'' **
'' Default Properties
public property get graph_url()
graph_url = m_graph_url
end property
public property get json_string()
json_string = m_json_str
end property
public property get token()
token = m_token
end property
public property let token(value)
m_token = value
end property
'' Object Type property exposure
'' initialization
sub Class_Initialize
set fbu = new fb_utility
end sub
'' termination
sub Class_Terminate
set fbu = nothing
end sub
'' **
'' Implementation
'' **
'' Load object by id
public sub Load(ID)
dim obj
m_graph_url = "https://graph.facebook.com/" & id & _
"?access_token=" & m_token
m_json_str = fbu.get_page_contents( m_graph_url )
set obj = JSON.parse( m_json_str )
load_from_json_object obj
end sub
public sub load_from_json_object( fb_obj )
on error resume next
'' map your properties here
on error goto 0
err.clear
end sub
end class
A real world example - Facebook User Object
The next code block builds on the pattern examples and implements a Facebook user object.
''**************************************************************************
'' Copyright 2012 Larry Boeldt
'' Class: facebook_user V1.0 2012-01-26
'' Author: Larry Boeldt - lboeldt@scs-inc.net; larry@boeldt.net
''
'' Description:
'' Facebook user object
''
''**************************************************************************
class facebook_user
dim m_id '' The user's Facebook ID
dim m_name '' The user's full name
dim m_first_name '' The user's first name
dim m_middle_name '' The user's middle name
dim m_last_name '' The user's last name
dim m_gender '' The user's gender: female or male
dim m_locale '' The user's locale
dim m_languages '' The user's languages
dim m_link '' The URL of the profile for the user on Facebook
dim m_username '' The user's Facebook username
dim m_third_party_id '' An anonymous, but unique identifier for the user;
'' only returned if specifically requested via the fields URL parameter
dim m_timezone '' The user's timezone offset from UTC
dim m_updated_time '' The last time the user's profile was updated;
'' changes to the languages, link, timezone, verified,
'' interested_in, favorite_athletes, favorite_teams,
'' and video_upload_limits are not not reflected in this value
dim m_verified '' The user's account verification status, either true or false (see below)
dim m_bio '' The user's biography
dim m_birthday '' The user's birthday
dim m_education '' A list of the user's education history
dim m_email '' The proxied or contact email address granted by the user
dim m_hometown '' The user's hometown
dim m_interested_in '' The genders the user is interested in
dim m_location '' The user's current city
dim m_political '' The user's political view
dim m_favorite_athletes '' The user's favorite athletes; this field
'' is deprecated and will be removed in the near future
dim m_favorite_teams '' The user's favorite teams; this field
'' is deprecated and will be removed in the near future
dim m_quotes '' The user's favorite quotes
dim m_relationship_status '' The user's relationship status: Single,
'' In a relationship, Engaged, Married, It's complicated,
'' In an open relationship, Widowed, Separated, Divorced,
'' In a civil union, In a domestic partnership
dim m_religion '' The user's religion
dim m_significant_other '' The user's significant other
dim m_video_upload_limits '' The size of the video file and the length
'' of the video that a user can upload; only returned
'' if specifically requested via the fields URL parameter
dim m_website '' The URL of the user's personal website
dim m_token ''
dim m_json_str ''
dim m_graph_url ''
dim fbu '' Facebook utility object
sub Class_Initialize()
m_id = ""
m_name = ""
m_first_name = ""
m_middle_name = ""
m_last_name = ""
m_gender = ""
m_locale = ""
m_languages = ""
m_link = ""
m_username = ""
m_third_party_id = ""
m_timezone = ""
m_updated_time = ""
m_verified = ""
m_bio = ""
m_birthday = ""
m_education = ""
m_email = ""
m_hometown = ""
m_interested_in = ""
m_location = ""
m_political = ""
m_quotes = ""
m_relationship_status = ""
m_religion = ""
m_significant_other = ""
m_video_upload_limits = ""
m_website = ""
set fbu = new fb_utility
end sub
public property get graph_url()
graph_url = m_graph_url
end property
public property get json_string()
json_string = m_json_str
end property
public property get token()
token = m_token
end property
public property let token(value)
m_token = value
end property
public property get id()
id = m_id
end property
public property let id(value)
m_id = value
end property
public property get name()
name = m_name
end property
public property let name(value)
m_name = value
end property
public property get first_name()
first_name = m_first_name
end property
public property let first_name(value)
m_first_name = value
end property
public property get middle_name()
middle_name = m_middle_name
end property
public property let middle_name(value)
m_middle_name = value
end property
public property get last_name()
last_name = m_last_name
end property
public property let last_name(value)
m_last_name = value
end property
public property get gender()
gender = m_gender
end property
public property let gender(value)
m_gender = value
end property
public property get locale()
locale = m_locale
end property
public property let locale(value)
m_locale = value
end property
public property get languages()
languages = m_languages
end property
public property let languages(value)
m_languages = value
end property
public property get link()
link = m_link
end property
public property let link(value)
m_link = value
end property
public property get username()
username = m_username
end property
public property let username(value)
m_username = value
end property
public property get third_party_id()
third_party_id = m_third_party_id
end property
public property let third_party_id(value)
m_third_party_id = value
end property
public property get timezone()
timezone = m_timezone
end property
public property let timezone(value)
m_timezone = value
end property
public property get updated_time()
updated_time = m_updated_time
end property
public property let updated_time(value)
m_updated_time = value
end property
public property get verified()
verified = m_verified
end property
public property let verified(value)
m_verified = value
end property
public property get bio()
bio = m_bio
end property
public property let bio(value)
m_bio = value
end property
public property get birthday()
birthday = m_birthday
end property
public property let birthday(value)
m_birthday = value
end property
public property get education()
education = m_education
end property
public property let education(value)
m_education = value
end property
public property get email()
email = m_email
end property
public property let email(value)
m_email = value
end property
public property get hometown()
hometown = m_hometown
end property
public property let hometown(value)
m_hometown = value
end property
public property get interested_in()
interested_in = m_interested_in
end property
public property let interested_in(value)
m_interested_in = value
end property
public property get location()
location = m_location
end property
public property let location(value)
m_location = value
end property
public property get political()
political = m_political
end property
public property let political(value)
m_political = value
end property
public property get quotes()
quotes = m_quotes
end property
public property let quotes(value)
m_quotes = value
end property
public property get relationship_status()
relationship_status = m_relationship_status
end property
public property let relationship_status(value)
m_relationship_status = value
end property
public property get religion()
religion = m_religion
end property
public property let religion(value)
m_religion = value
end property
public property get significant_other()
significant_other = m_significant_other
end property
public property let significant_other(value)
m_significant_other = value
end property
public property get video_upload_limits()
video_upload_limits = m_video_upload_limits
end property
public property let video_upload_limits(value)
m_video_upload_limits = value
end property
public property get website()
website = m_website
end property
public property let website(value)
m_website = value
end property
public sub LoadMe()
dim strFields
dim obj
m_graph_url = "https://graph.facebook.com/me?access_token=" & _
m_token
m_json_str = fbu.get_page_contents( m_graph_url )
set obj = JSON.parse( m_json_str )
load_from_json_user obj
end sub
public sub Load(ID)
dim strFields
dim obj
m_graph_url = "https://graph.facebook.com/" & _
ID & "?access_token=" & _
m_token
m_json_str = fbu.get_page_contents( m_graph_url )
set obj = JSON.parse( m_json_str )
load_from_json_user obj
end sub
''**************************************************************************
'' Copyright 2012 Larry Boeldt
'' Function: load_from_json_user V1.0 2012-01-26
'' Author: Larry Boeldt - lboeldt@scs-inc.net; larry@boeldt.net
'' Parameter(s):
'' fb_obj - The facebook object as returned from JSON.parse
''
'' Description:
'' This function attempts to safely assign all user parameters from a
'' fasebook object so that you can consistently address the properties in
'' your code without concern about errors resulting from properties that
'' are missing in the return json object
''**************************************************************************
public sub load_from_json_user(fb_obj)
on error resume next
m_id = fb_obj.id
m_name = fb_obj.name
m_first_name = fb_obj.first_name
m_middle_name = fb_obj.middle_name
m_last_name = fb_obj.last_name
m_gender = fb_obj.gender
m_locale = fb_obj.locale
m_languages = fb_obj.languages
m_link = fb_obj.link
m_username = fb_obj.username
m_third_party_id = fb_obj.third_party_id
m_timezone = fb_obj.timezone
m_updated_time = fb_obj.updated_time
m_verified = fb_obj.verified
m_bio = fb_obj.bio
m_birthday = fb_obj.birthday
m_education = fb_obj.education
m_email = fb_obj.email
m_hometown = fb_obj.hometown.name
m_interested_in = fb_obj.interested_in
m_location = fb_obj.location.name
m_political = fb_obj.political
m_quotes = fb_obj.quotes
m_relationship_status = fb_obj.relationship_status
m_religion = fb_obj.religion
m_significant_other = fb_obj.significant_other
m_video_upload_limits = fb_obj.video_upload_limits
m_website = fb_obj.website
on error goto 0
err.clear
end sub
end class
Pulling them all together with the fb_graph_api object
To keep code that uses this library uncluttered, the fb_graph_api
class implements a function that returns a ready made object.
What's in the current library?
I provided everything I'm working on as of this writing, however only some functions are ready for your consumption. The other examples are in alpha mode; use at your own risk. Here are the working objects and associated graph_api "shortcuts":
Facebook Object Name | Class Name | Graph API Function | Test Page |
User | fb_user |
get_user |
user_test.asp |
Friends (a list of user objects) | fb_friends |
get_friends |
friends_test.asp |
Friend | fb_user |
get_friend |
friend_test.asp |
Album (Photo Album) | fb_album |
get_album |
album_test.asp |
Photo | fb_photo |
get_photo |
album_test.asp |
Comment | fb_comment |
none, called by other objects. | none |
Like | fb_like |
none, called by other objects. Note: this is a like object not a like method. I don't have that working yet. | none |
Graph API Methods
Presently only the post_to_wall
method is implemented.
The test page for wall post is post_wall_test.asp. Presently you can only post to the currently logged-in user's wall.
The post to wall takes the following parameters:
Parameter Name | Description |
Message | The message that you want to display on the wall |
Picture | The URL of a picture to display with the wall post |
Link | The URL that is the target of the link |
Name | The name to display on the link |
Caption | The link caption |
Description | A longer text describing the link |
Points of interest
The DTO classes can be stored in the session because they make use of only VBScript variants and there are no objects (like
scripting.dictionary
) that raise threading model issues.
Conclusion
While the example here does not support the full Graph API, I think you'll be able to wade through any other API data by referencing the examples here. If you implement another module, post it here and I'll be sure to included it in a new release. I'll release a new version every third month of the year for the next year. Your feedback, advice, and votes are always appreciated.
History
- Release version 1.