網路技術日新月異,Facebook的各項功能也常常在變化,以前的Facebook C# SDK還需要自己 build 出 DLL 來,現在已經不用了,新版的Facebook C# SDK不但網站改了地方,也改成用 Nuget 去取得程式,還加入了支援Windows Phone, Windows Azure, Windows Metro Style Apps,可說是相當多的改變。
(歐對,FB JDK也三不五時在改,請記得定時更新載入語法)
Install Facebook C# SDK via NuGet
要用新版的Facebook C# SDK不難,只要你有裝 NuGet 就很方便了,如果沒用過NuGet沒關係,黑暗執行緒有寫過一篇NuGet介紹,可以參考,其實也就很簡單,在Visual Studio的Extension Manager裡面去找NuGet然後裝就對了,如果你的NuGet版本比較舊無法更新到新版成功的話,請用Administrator權限去開VS,移除掉舊的NuGet再裝新的就好。
NuGet裝好後,在專案上右鍵選擇 Manage NuGet Packages。
如上圖找到 Facebook ,按下 Install 就安裝完了,你會在 bin (或他應該出現的目錄)下面找到多出 Facebook.dll 與 Facebook.xml 這兩個檔案。
First try - Get something
然後就可以使用FB C# SDK去抓資料了,以沒有取得access token的狀態下,我們可以直接拉一些公開資訊來用,例如拉Facebook創辦人Mark Zuckerberg的基本資訊。
var client = new FacebookClient(); dynamic me = client.Get("zuck"); string firstName = me.first_name; string lastName = me.last_name; Label1.Text = firstName + " , " + lastName; |
Authentication using Javascript
接下來就用來取得驗證了,其實可以用FB C# SDK從後端去跟FB用graph認證,但是因為在blog上比較難展示,所以就參考官方文件使用FB JS SDK來取得access token,然後丟給後端程式。你可以參考Facebook C# SDK的getting-started去加入下面的語法以載入FB JDK。
<div id="fb-root"></div> <script> window.fbAsyncInit = function() { FB.init({ appId : 'YOUR_APP_ID', // App ID status : true, // check login status cookie : true, // enable cookies to allow the server to access the session xfbml : true // parse XFBML }); // Additional initialization code here }; // Load the SDK Asynchronously (function(d){ var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0]; if (d.getElementById(id)) {return;} js = d.createElement('script'); js.id = id; js.async = true; js.src = "//connect.facebook.net/en_US/all.js"; ref.parentNode.insertBefore(js, ref); }(document)); </script>
然後getting-started的教學會叫你用 FB.Event.subscribe('auth.authResponseChange') 的方式去取得認證狀態,這不是不能用,但是看起來只有認證狀態改變時才會有東西,所以我改成用 FB.getLoginStatus() 的方式去取,這樣可以確保每次都有東西,所以就是加入下列的javascript在上面 FB.init 的 // Additional initialization code here 這邊。
FB.getLoginStatus(function (response) { if (response.status === 'connected') { // the user is logged in and has authenticated your // app, and response.authResponse supplies // the user's ID, a valid access token, a signed // request, and the time the access token // and signed request each expire var uid = response.authResponse.userID; var accessToken = response.authResponse.accessToken; var form = document.createElement("form"); form.setAttribute("method", 'post'); form.setAttribute("action", '/WebTest/FacebookLogin.ashx'); var field = document.createElement("input"); field.setAttribute("type", "hidden"); field.setAttribute("name", 'accessToken'); field.setAttribute("value", accessToken); form.appendChild(field); document.body.appendChild(form); form.submit(); // TODO: Handle the access token } else if (response.status === 'not_authorized') { alert('not_authorized'); // the user is logged in to Facebook, // but has not authenticated your app } else { alert('not_logged'); // the user isn't logged in to Facebook. } });
基本上,code裡面都有註解了,所以也不用多做解釋,我只是在狀態為connected,也就是有用這個fb app的時候,將取得的access token丟到後端頁面去處理而已,而這個handler FacebookLogin.ashx 做的事情也很簡單,就只是將收到的access token轉成session。
public void ProcessRequest (HttpContext context) { var accessToken = context.Request["accessToken"]; context.Session["AccessToken"] = accessToken; context.Response.Redirect("FBTest.aspx"); }內容大概是長的像上面這樣,寫session後將頁面導到你要的地方,要注意的是在handler裡面用HttpContext.Session,必須要繼承 System.Web.SessionState.IRequiresSessionState ,不然會出錯。
在取得Access Token時,SDK就可以取得比較多的資料了,詳細說明可以看Facebook Graph API這邊的說明,我是很簡單的取得個人資料內的name , uid 還有資料更新時間,語法與結果如下。
基本上大概就是這樣了,與之前寫的FB C# SDK教學差異不大,不過我這邊是用JDK去取得認證資訊而已,下次再來寫server-side的取得認證方式。
Example
這邊是個小範例,因為沒地方放aspx,所以我就用JS SDK假裝一下XD,效果大概就是跟我的測試程式一樣,會對應login/auth狀態做出不同的事,但是我這邊只吐出 Access Token而已。
My test code
下面是我的測試程式,大概的功能就是進入頁面時去判斷這個使用者有沒有登入FB、有沒有認證此APP,沒的話就顯示Facebook CEO的名字,有的話就顯示使用者的名字、uid與更新時間,然後針對使用者移除APP許可的狀況,去catch (OAuthException - #190) Error invalidating access token: User ## has not authorized application ##. 這個錯誤。
然後我有多加一個button方便測試,基本上是多的,可以拿掉無所謂。
FBTest.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="FBTest.aspx.cs" Inherits="FBTest" %> <!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></title> <script src='http://www.google.com/jsapi' type='text/javascript'></script> <script language='javascript' type='text/javascript'> google.load("jquery", "1.7.1");</script> <script type='text/javascript'> $(document).ready(function () { window.fbAsyncInit = function () { FB.init({ appId: 'YOUR_APP_ID', // App ID status: true, // check login status cookie: true, // enable cookies to allow the server to access the session xfbml: true // parse XFBML }); <% if(Session["AccessToken"] == null){ %> try_fb(); <% } %> }; // Load the SDK Asynchronously (function (d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=YOUR_APP_ID"; fjs.parentNode.insertBefore(js, fjs); } (document, 'script', 'facebook-jssdk')); }); function try_fb() { FB.getLoginStatus(function (response) { if (response.status === 'connected') { var uid = response.authResponse.userID; var accessToken = response.authResponse.accessToken; var form = document.createElement("form"); form.setAttribute("method", 'post'); form.setAttribute("action", '/WebTest/FacebookLogin.ashx'); var field = document.createElement("input"); field.setAttribute("type", "hidden"); field.setAttribute("name", 'accessToken'); field.setAttribute("value", accessToken); form.appendChild(field); document.body.appendChild(form); form.submit(); // TODO: Handle the access token } else if (response.status === 'not_authorized') { alert('not_authorized'); // the user is logged in to Facebook, // but has not authenticated your app } else { alert('not_logged'); // the user isn't logged in to Facebook. } }); } </script> </head> <body> <div id="fb-root"></div> <form id="form1" runat="server"> <div> <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" /><br /> <div class="fb-login-button" data-show-faces="true" data-width="400" data-max-rows="1"></div><br /> <asp:Label ID="Label1" runat="server" Text=""></asp:Label><br /> </div> </form> </body> </html>
FBTest.aspx.cs
using System; using Facebook; public partial class FBTest : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { CallFb(); } protected void Button1_Click(object sender, EventArgs e) { CallFb(); } private void CallFb() { if (Session["AccessToken"] != null) { var accessToken = Session["AccessToken"].ToString(); var client = new FacebookClient(accessToken); try { dynamic result = client.Get("me", new { fields = "name,id,updated_time" }); string name = result.name; string id = result.id; string updatedTime = result.updated_time; Label1.Text = name + " , " + id + " , " + updatedTime; } catch (Exception ex) { Session.Remove("AccessToken"); Label1.Text = (ex.Message.IndexOf("OAuthException - #190") > -1) ? "User has not authorized" : "unknow error"; } } else { var client = new FacebookClient(); dynamic me = client.Get("zuck"); string firstName = me.first_name; string lastName = me.last_name; Label1.Text = firstName + " , " + lastName; } } }
FacebookLogin.ashx
<%@ WebHandler Language="C#" Class="FacebookLogin" %> using System.Web.SessionState; using System.Web; public class FacebookLogin : IHttpHandler, IRequiresSessionState { public void ProcessRequest (HttpContext context) { var accessToken = context.Request["accessToken"]; context.Session["AccessToken"] = accessToken; context.Response.Redirect("FBTest.aspx"); } public bool IsReusable { get { return false; } } }
就這樣了,有問題再問我吧。
請問 var client = new FacebookClient(accessToken);
ReplyDelete這行出錯的原因是什麼
執行後會出現
編譯器錯誤訊息: CS0122: 'test0729.FacebookClient' 的保護層級導致無法對其進行存取
你可以考這篇
ReplyDeletehttp://msdn.microsoft.com/zh-tw/library/ha94aebs.aspx
不好意思,為什麼我的Label1 說不存在於目前內容中?
ReplyDelete因為我是個完全的新手,不好意思
Label1是在aspx內的控制項,你可能有改名或漏掉了,在範例裡面是有的。
ReplyDelete你好,第一次登入時擷取的資料是正確的
ReplyDelete關掉網頁重新開啟之後再用其他帳號登入
取得的資料卻是第一次登入的
請問問題出在哪裡呢
有可能cookie還是吃舊的,你可以確認一下cookie內容看看
ReplyDelete你好,再次請教
ReplyDelete請問有實作logout的範例嗎
謝謝
能帮我看看吗??
ReplyDeleteSystem.IO.FileLoadException: 未能加载文件或程序集“Facebook, Version=6.0.10.0, Culture=neutral, PublicKeyToken=58cb4f2111d1e6de”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
你好,我也會有換帳號登入後顯示的資料仍是上一個使用者資料的問題,
ReplyDelete試過清除cookie但仍未解決。
我有架server弄成網頁,換其他電腦登入所顯示的資料還是上一位使用者的,
不知道該怎麼解決...
不好意思我解決了XD
ReplyDelete我在抓acess_token那個if前面先加了remove移掉之前的
謝謝你:)
恭喜你XD
ReplyDelete