Making a Facebook Wall Post using the new Graph API and C#
One of the features coming up with Rate-It is the ability to post your ratings/reviews to your Facebook wall. For this, we decided to go with the new Facebook Graph API.
There are quite a few tricks and obstacles in the way of you doing this, particularly because the documentation omits a few details and the documentation is very PHP- or Javascript-centric. With this in mind, we’ve posted below some very detailed instructions on how to get the system going using Microsoft C#.
Debug your Facebook Application from localhost
One of the first problems you’ll have is trying to debug your application, and for this the easiest way is via localhost. We have seen a few posts suggesting that this is not possible, but it is – and it is easy. Simply setup a new application at www.facebook.com/developers and then enter your localhost information where a URL is required. We’ve copied a screenshot of ours below:
Getting a user to Authorize your Application
Refer: http://developers.facebook.com/docs/authentication/
Facebook has a two-step approach for a user to authorize your application. The first is to connect their Facebook account. The second is to switch the Facebook account code with an OAuth account code.
The key to all this, and the most problems you’ll have is simply structuring your URLs. There are three, and here they are:
/// The callback page where the user is returned to after authorizing with FB
/// </summary>
/// <returns></returns>
private string FacebookAfterAuthorize()
{
return SiteRoot + "services/facebook/canvas/afterauthorise.aspx";
}
/// <summary>
/// Once FB returns a user code to us, we need to use the OAuth key in queries
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public string FacebookOAuthAccessTokenFromFacebookCode(string codeReturnedFromInitialFacebookRequest)
{
var url = "https://graph.facebook.com/oauth/access_token"
.AppendQueryString("client_id", Configuration.Current.FacebookAPIKey)
.AppendQueryString("client_secret", Configuration.Current.FacebookAPISecret)
.AppendQueryString("code", codeReturnedFromInitialFacebookRequest)
.AppendQueryString("redirect_uri", this.FacebookAfterAuthorize())
;
return url;
}
/// <summary>
/// The link the user clicks when they want to initialize their connection to FB
/// </summary>
/// <returns></returns>
public string FacebookAuthorize()
{
var url = "https://graph.facebook.com/oauth/authorize"
.AppendQueryString("client_id", Configuration.Current.FacebookAPIKey)
.AppendQueryString("scope", "publish_stream,offline_access")
.AppendQueryString("redirect_uri", this.FacebookAfterAuthorize())
;
return url;
}
Step 1 – Connect the Facebook Account
Simply create a hyperlink and present it to the user. The hyperlink contains various GET parameters which tell Facebook who you are and what you want to do with the user’s account. Here is our one:
var url = new LinkManager().FacebookAuthorize();
BtnFacebookAuthorize.NavigateUrl = url;
Pretty simple. This redirects the user to a Facebook page where they are presented with something like this:
Assuming the user selects ‘Allow’, they are redirected to the redirect_url parameter you specified in the hyperlink. In our case, this was /services/facebook/canvas/afterauthorize.aspx. Let’s look at that now.
Step 2 – Switching the Facebook Code for the OAuth Code
The Graph API uses the OAuth system to authenticate users and at this point, we only have some kind of Facebook code. We get the OAuth code by POSTing the Facebook code back up to Facebook. I’ll let the code do the talking:
public void ProcessAfterAuthorization(HttpRequest request)
{
// Facebook passes an empty code if the user declined
string code = request.Params("code");
if (string.IsNullOrEmpty(code)) throw new FacebookAuthorizationException("You have chosen not to proceed with Facebook integration.");
// Facebook
var url = new LinkManager().FacebookOAuthAccessTokenFromFacebookCode(code);
var webRequest = WebRequest.Create(url);
var webResponse = webRequest.GetResponse();
StreamReader sr = null;
string returnedKeyValuePairs = "";
try
{
sr = new StreamReader(webResponse.GetResponseStream());
returnedKeyValuePairs= sr.ReadToEnd();
}finally
{
if (sr != null) sr.Close();
}
// Get the OAuth token from the returned querystring
var authToken = returnedKeyValuePairs.GetQueryStringValue("access_token");
}
Save the authToken field against your user record – this is what you’ll pass later when you make a wall post. It will look a little something like this:
108091332590110|a9fa8e86ed521818374c8733-100001367407858|vRR3VgTCPuBwgcsG4Kr2fUiw9A8
Writing to the User’s Wall
Refer: http://developers.facebook.com/docs/reference/api/post
Writing to a user’s wall is a lot more complicated, and the documentation linked above omits a very important point. Here is what we came up with:
public class PostToWall
{
public string Message = "";
public string AccessToken = "";
public string ArticleTitle = "";
public string FacebookProfileID = "";
public string ErrorMessage { get; private set; }
public string PostID { get; private set; }
/// <summary>
/// Perform the post
/// </summary>
public void Post()
{
if (string.IsNullOrEmpty(this.Message)) return;
// Append the user's access token to the URL
var url = "https://graph.facebook.com/me/feed"
.AppendQueryString("access_token", this.AccessToken);
// The POST body is just a collection of key=value pairs, the same way a URL GET string might be formatted
var parameters = ""
.AppendQueryString("name", "name")
.AppendQueryString("link", "http://link.com")
.AppendQueryString("caption", "a test caption")
.AppendQueryString("description", "a test description")
.AppendQueryString("source", "http://blackballsoftware.com/images/whitetheme/headerwhite.png")
.AppendQueryString("actions", "{\"name\": \"View on Rate-It\", \"link\": \"http://www.rate-it.co.nz\"}")
.AppendQueryString("privacy", "{\"value\": \"EVERYONE\"}")
.AppendQueryString("message", this.Message);
// Mark this request as a POST, and write the parameters to the method body (as opposed to the query string for a GET)
var webRequest = WebRequest.Create(url);
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(parameters);
webRequest.ContentLength = bytes.Length;
System.IO.Stream os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
// Send the request to Facebook, and query the result to get the confirmation code
try
{
var webResponse = webRequest.GetResponse();
StreamReader sr = null;
try
{
sr = new StreamReader(webResponse.GetResponseStream());
this.PostID = sr.ReadToEnd();
}
finally
{
if (sr != null) sr.Close();
}
}catch(WebException ex)
{
// To help with debugging, we grab the exception stream to get full error details
StreamReader errorStream = null;
try
{
errorStream = new StreamReader(ex.Response.GetResponseStream());
this.ErrorMessage = errorStream.ReadToEnd();
}finally
{
if (errorStream != null) errorStream.Close();
}
}
}
}
And to use, simply:
var post = new PostToWall();
post.Message = "Test message from Ben";
post.ArticleTitle = "A new rating has been posted";
post.AccessToken = "108091332590110|a9fa8e86ed521818374c8733-100001367407858|vRR3VgTCPuBwgcsG4Kr2fUiw9A8";
post.Post();
Response.Write("The Facebook post successed with ID: " + post.PostID);
Response.Write("<br/>");
Response.Write("The error message was: " + post.ErrorMessage);
Right – hopefully that is useful to somebody, it will be to us when we forget how we did it in a few months.
Apologies for the custom classes etc in the code like AppendQueryString() – I’m sure you can work them out.
Thats awesome Ben! I’ve been struggling with the oAuth stuff with facebook. Are you using this app inside an iframe? My main problem is that you only get to capture the iFrame call (which is the only call that contains the userid) once (when it first loads).
Nope not using in an iFrame. The entire process just uses the main ‘top’ frame of the website – nothing fancy. If an iFrame is not working for you, a popup might?
Thank you so much for that bit of code.I was having a problem with 400 bad request until I stumbled on this….many thanks..
Thanks Ben….
Its a great article.. Even facebook itself does not provide us documentation like this.
Cheers – let’s hope they don’t change the API again any time soon
HI,
Nice Article,
Can you please send me the AppendQueryString method code.
Thanks in advance
No problem (excuse the formatting)…
public static string AppendQueryString(this string url, string key, string value, bool doNotEncrypt)
{
var encode = Dependency.Resolve();
if (url.IndexOf(‘?’) != -1) { url += “&”; } else { url += “?”; }
// Append
if (doNotEncrypt) url += key + “=” + value;
else url += encode.Encode(key) + “=” + encode.Encode(value);
// Return
return url;
}
Hi Ben,
I wish I could have Dependency.Resolve() method, please help me!
Hi, the Dependency.Resolve() methods are just calls using Microsoft Unity to get my class names. If it says IPersonService, then it resolves to just PersonService(). My intention isn’t to give you working code, as it is no good to you without the entire source code and all service methods, rather it is to show the general approach. You can stub out those methods to get it to compile.
Hi Ben,
How can I fix the “Dependency.Resolve()” error in the AppenQueryString method?
You can see how Dependency.Resolve works at http://blog.blackballsoftware.com/2011/04/26/best-practice-architecture-for-professional-microsoft-net-websites/
Or, just delete it and rewrite the line, it’s just a fancy way of concatenating a query string
Ben… sry but I’m just gettin’ started whit this API.
Can you explain me about GetQueryStringValue method and an error on request.Params; VS say Params doesn’t allow parameters.
Thx and sry again. :$
@Da Jona. For the GetQueryStringValue method I just made a string replace (access_token > empty string). For params, theres I syntax error in the code. Its string code = request.Params["code"];. Notice the []. Havent tested it though.
wow it working for me thanks ben .Thnk u so much .I have been struggling with these since last week
this nice post , thnx alot
Thank you so much ben for this post!
Thank you very much. Very good for me. Silly question i guess:
There do i get the api for c# and is there any problems getting started in vs2010?
Hi, VS2010 is fine – it’s what I use actually. C# is built in to it, so you can just get typing. If you’re just learning, I recommend searching ‘getting started with visual studio’ tutorial – it will probably be in C#
Thank you very much
Thanks Ben. Saved my day !
Ben – you saved me HOURS of time. It would have taken me forever to figure this out. Thank you so much for putting this up.
Awesome Ben ! , very clear and good tutorial !
Do you have any post that shows how to retrieve user newsfeed , wall using facebook graph api ? as i am struggling with it Thank you
Hey Sam, nah sorry I don’t have anything about the user newsfeed. Hopefully this tutorial gives you the gist of how it all fits together and you can just plug in some newsfeed code from Stack Overflow or something. Good luck
Hi Ben , may i ask a question please ? i am new to this facebook application.I have managed to post a message to a group wall and able to see my own post in the group. However , my friends is unable to see my post. I used
Facebook.FacebookAPI api = new Facebook.FacebookAPI(AccessToken);
Dictionary data = new Dictionary();
data.Add(“message”, “Test”);
data.Add(“privacy”, “{\”value\”: \”EVERYONE\”}”);
api.Post(“/groupid/feed”, data);
Appreciate any help ! Thanks
Hi Ben. Interesting article. Do you have an example that shows exactly how and when the call to ProcessAfterAuthorization(HttpRequest request) is made? I assume that it is after the user has authorized the app?
Hi, yeah when you set up your app in Facebook, they ask you for the ‘post authorize url’. You can specify anything you like, as long as it falls under your main domain name. So, you might choose http://www.example.com/afterauthorize.aspx. On THAT page, in the Page_Load() method, you make a call to the ProcessAfterAuthorization() function I provided.