I updated the Facebook SDK to 6.0.10 and some code that used to work is not working anymore. I used to post on users' wall use the method below.
The class FacebookClient used to take the AppId
, and AppSecret
and I didn't gave it any access token for my application.
string uId = "SomeUid";
FacebookClient fb = new FacebookClient(AppId,AppSecret );
string userFeedPath = String.Format("/{0}/feed", uId);
dynamic parameters = new ExpandoObject();
parameters.link = "Test@test";
parameters.message = "test";
try
{
dynamic result = fb.Post(userFeedPath, parameters);
}
catch(Exception ex)
{
}
Now even if I try this,
FacebookClient fb = new FacebookClient();
fb.AppId = "1234...";
fb.AppSecret = "76e69e0c334995cecc8c....";
I'm getting this error:
(OAuthException - #200) (#200) This API call requires a valid app_id.
How do I fix this problem?
You will need to get the app access token by making the request.
var fb = new FacebookClient();
dynamic result = fb.Get("oauth/access_token", new {
client_id = "app_id",
client_secret = "app_secret",
grant_type = "client_credentials"
});
fb.AccessToken = result.access_token;
For code -> user access token exchange in server-side flow - instead (ver. 5):
FacebookOAuthClient oAuthClient = new FacebookOAuthClient();
oAuthClient.AppId = "...";
oAuthClient.AppSecret = "...";
oAuthClient.RedirectUri = new Uri("https://.../....aspx");
dynamic tokenResult = oAuthClient.ExchangeCodeForAccessToken(code);
return tokenResult.access_token;
Now use (ver. 6):
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("client_id", "...");
parameters.Add("redirect_uri", "https://.../....aspx");
parameters.Add("client_secret", "...");
parameters.Add("code", code);
result = fb.Get("/oauth/access_token", parameters);
string accessToken = result["access_token"];
(see: http://developers.facebook.com/docs/authentication/server-side/)
I have just started using this Facebook library yesterday and thought the lack of the ability to give me the access token without passing from JavaScript was a major shortcoming. Here is a helper that can get the access token. I hope this helps anyone who has had the same frustrations as myself. I think this should all work fine. I had something similar working on a website before I discovered the Facebook NuGet which has worked fine for approximately a year now.
If there's a better way please let me know.
public class FacebookHelper
{
private string _appId;
private string _appSecret;
private string _accessToken;
public string AccessToken
{
get
{
if (_accessToken == null)
GetAccessToken();
return _accessToken;
}
set { _accessToken = value; }
}
public FacebookHelper(string appId, string appSecret)
{
this._appId = appId;
this._appSecret = appSecret;
}
public string GetAccessToken()
{
var facebookCookie = HttpContext.Current.Request.Cookies["fbsr_" + _appId];
if (facebookCookie != null && facebookCookie.Value != null)
{
string jsoncode = System.Text.ASCIIEncoding.ASCII.GetString(FromBase64ForUrlString(facebookCookie.Value.Split(new char[] { '.' })[1]));
var tokenParams = HttpUtility.ParseQueryString(GetAccessToken((string)JObject.Parse(jsoncode)["code"]));
_accessToken = tokenParams["access_token"];
return _accessToken;
}
else
return null;
// return DBLoginCall(username, passwordHash, cookieToken, cookieTokenExpires, args.LoginType == LoginType.Logout, null);
}
private string GetAccessToken(string code)
{
//Notice the empty redirect_uri! And the replace on the code we get from the cookie.
string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}", _appId, "", _appSecret, code.Replace("\"", ""));
System.Net.HttpWebRequest request = System.Net.WebRequest.Create(url) as System.Net.HttpWebRequest;
System.Net.HttpWebResponse response = null;
try
{
using (response = request.GetResponse() as System.Net.HttpWebResponse)
{
System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream());
string retVal = reader.ReadToEnd();
return retVal;
}
}
catch
{
return null;
}
}
private byte[] FromBase64ForUrlString(string base64ForUrlInput)
{
int padChars = (base64ForUrlInput.Length % 4) == 0 ? 0 : (4 - (base64ForUrlInput.Length % 4));
StringBuilder result = new StringBuilder(base64ForUrlInput, base64ForUrlInput.Length + padChars);
result.Append(String.Empty.PadRight(padChars, '='));
result.Replace('-', '+');
result.Replace('_', '/');
return Convert.FromBase64String(result.ToString());
}
}
I tried some of the above samples only to find out that dynamic does not compile using xamarin studio. Here is what I did.
public class AccessTokenModel
{
public string Access_Token { get; set;}
}
var fb = new FacebookClient();
var result = fb.Get ("oauth/access_token", new {
client_id = App.FaceBookId,
client_secret = App.FacebookAppSecret,
grant_type = "client_credentials"
});
var accessToken = Newtonsoft.Json.JsonConvert.DeserializeObject<AccessTokenModel> (result.ToString ());
or
FBSession.ActiveSession.AccessTokenData.AccessToken;
There is another method to make calls to the Graph API that doesn't require using a generated app access token. You can just pass your app id and app secret as the access_token parameter when you make a call:
https://graph.facebook.com/endpoint?key=value&access_token=app_id|app_secret
The choice to use a generated access token vs. this method depends on where you hide your app secret.
From: https://developers.facebook.com/docs/facebook-login/access-tokens
var client = new FacebookClient($"{appId}|{appSecret}");
Hare is a real working Method:
protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
{
// Note: Facebook doesn't like us to url-encode the redirect_uri value
var builder = new UriBuilder("https://graph.facebook.com/oauth/access_token");
builder.AppendQueryArgument("client_id", this.appId);
builder.AppendQueryArgument("redirect_uri", NormalizeHexEncoding(returnUrl.GetLeftPart(UriPartial.Path)));
builder.AppendQueryArgument("client_secret", this.appSecret);
builder.AppendQueryArgument("code", authorizationCode);
using (WebClient client = new WebClient())
{
//Get Accsess Token
string data = client.DownloadString(builder.Uri);
if (string.IsNullOrEmpty(data))
{
return null;
}
var parsedQueryString = HttpUtility.ParseQueryString(data);
return parsedQueryString["access_token"];
}
}
private static string NormalizeHexEncoding(string url)
{
var chars = url.ToCharArray();
for (int i = 0; i < chars.Length - 2; i++)
{
if (chars[i] == '%')
{
chars[i + 1] = char.ToUpperInvariant(chars[i + 1]);
chars[i + 2] = char.ToUpperInvariant(chars[i + 2]);
i += 2;
}
}
return new string(chars);
}
来源:https://stackoverflow.com/questions/9906486/how-to-get-an-access-token-using-c-sharp-sdk