我正在尝试使用Facebook API在Facebook用户的个人资料上发布消息。它有时会在身份验证后发送消息,但第二次总是会返回此错误(只是提到我将它用于asp.net webapplication):
An error occurred:The remote server returned an error: (400) Bad Request.
System.Net.WebException: The remote server returned an error: (400) Bad Request. at System.Net.HttpWebRequest.GetResponse() at Facebook.FacebookAPI.MakeRequest(Uri url, HttpVerb httpVerb, Dictionary`2 args) in \wwwroot\App_Code\FacebookAPI.cs:line 185 at Facebook.FacebookAPI.Call(String relativePath, HttpVerb httpVerb, Dictionary`2 args) in \wwwroot\App_Code\FacebookAPI.cs:line 134 at Facebook.FacebookAPI.Post(String relativePath, Dictionary`2 args) in \wwwroot\App_Code\FacebookAPI.cs:line 107 at Views_Publish_to_facebook.btnSend_Click(Object sender, EventArgs e) in \wwwroot\Views\MarketingTool\Publish_to_facebook.aspx.cs:line 90
我该怎么办? 这是登录按钮
<fb:login-button autologoutlink='true' perms='read_stream,publish_stream,offline_access' onlogin='window.location.reload()'>
</fb:login-button>
Facebook C#SDK
这是我的Facebook API代码。
/*
* Copyright 2010 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Web.Script.Serialization;
namespace Facebook
{
enum HttpVerb
{
GET,
POST,
DELETE
}
/// <summary>
/// Wrapper around the Facebook Graph API.
/// </summary>
public class FacebookAPI
{
/// <summary>
/// The access token used to authenticate API calls.
/// </summary>
public string AccessToken { get; set; }
/// <summary>
/// Create a new instance of the API, with public access only.
/// </summary>
public FacebookAPI()
: this(null) { }
/// <summary>
/// Create a new instance of the API, using the given token to
/// authenticate.
/// </summary>
/// <param name="token">The access token used for
/// authentication</param>
public FacebookAPI(string token)
{
AccessToken = token;
}
/// <summary>
/// Makes a Facebook Graph API GET request.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
public JSONObject Get(string relativePath)
{
return Call(relativePath, HttpVerb.GET, null);
}
/// <summary>
/// Makes a Facebook Graph API GET request.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
/// <param name="args">A dictionary of key/value pairs that
/// will get passed as query arguments.</param>
//public JSONObject Get(string relativePath,
// Dictionary<string, string> args)
public JSONObject Get(string relativePath,
Dictionary<string, string> args)
{
return Call(relativePath, HttpVerb.GET, args);
}
/// <summary>
/// Makes a Facebook Graph API DELETE request.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
public JSONObject Delete(string relativePath)
{
return Call(relativePath, HttpVerb.DELETE, null);
}
/// <summary>
/// Makes a Facebook Graph API POST request.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
/// <param name="args">A dictionary of key/value pairs that
/// will get passed as query arguments. These determine
/// what will get set in the graph API.</param>
public JSONObject Post(string relativePath,
Dictionary<string, string> args)
{
return Call(relativePath, HttpVerb.POST, args);
}
/// <summary>
/// Makes a Facebook Graph API Call.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
/// <param name="httpVerb">The HTTP verb to use, e.g.
/// GET, POST, DELETE</param>
/// <param name="args">A dictionary of key/value pairs that
/// will get passed as query arguments.</param>
private JSONObject Call(string relativePath,
HttpVerb httpVerb,
Dictionary<string, string> args)
{
Uri baseURL = new Uri("https://graph.facebook.com");
//relativePath = "/me";
Uri url = new Uri(baseURL, relativePath);
if (args == null)
{
args = new Dictionary<string, string>();
}
if (!string.IsNullOrEmpty(AccessToken))
{
args["access_token"] = AccessToken;
}
JSONObject obj = JSONObject.CreateFromString(MakeRequest(url,
httpVerb,
args));
if (obj.IsDictionary && obj.Dictionary.ContainsKey("error"))
{
throw new FacebookAPIException(obj.Dictionary["error"]
.Dictionary["type"]
.String,
obj.Dictionary["error"]
.Dictionary["message"]
.String + " -> " + url + " " + httpVerb + " " + args);
}
return obj;
}
/// <summary>
/// Make an HTTP request, with the given query args
/// </summary>
/// <param name="url">The URL of the request</param>
/// <param name="verb">The HTTP verb to use</param>
/// <param name="args">Dictionary of key/value pairs that represents
/// the key/value pairs for the request</param>
private string MakeRequest(Uri url, HttpVerb httpVerb,
Dictionary<string, string> args)
{
if (args != null && args.Keys.Count > 0 && httpVerb == HttpVerb.GET)
{
url = new Uri(url.ToString() + EncodeDictionary(args, true));
}
//throw new Exception(url.AbsoluteUri + " ---- " + url.AbsolutePath);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = httpVerb.ToString();
if (httpVerb == HttpVerb.POST)
{
string postData = EncodeDictionary(args, false);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] postDataBytes = encoding.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postDataBytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(postDataBytes, 0, postDataBytes.Length);
requestStream.Close();
}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
try
{
//using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
//throw new Exception(response.ResponseUri + " tra " + response.Server);
{
StreamReader reader
= new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
}
catch (WebException e)
{
throw new FacebookAPIException("Server Error", e.Message + " resp: " + request.GetResponse() + " " + response.ResponseUri + " tra " + response.Server);
}
}
/// <summary>
/// Encode a dictionary of key/value pairs as an HTTP query string.
/// </summary>
/// <param name="dict">The dictionary to encode</param>
/// <param name="questionMark">Whether or not to start it
/// with a question mark (for GET requests)</param>
private string EncodeDictionary(Dictionary<string, string> dict,
bool questionMark)
{
StringBuilder sb = new StringBuilder();
if (questionMark)
{
sb.Append("?");
}
foreach (KeyValuePair<string, string> kvp in dict)
{
sb.Append(HttpUtility.UrlEncode(kvp.Key));
sb.Append("=");
//NOTE: This line causes problems with access_token. The url encoding messes up the access_token, so for now I'm just adding it directly
//if the key == "access_token"
//sb.Append(HttpUtility.UrlEncode(kvp.Value));
if (kvp.Key.ToLower() == "access_token")
{
sb.Append(kvp.Value);
//sb.Append(HttpUtility.UrlEncode(HttpUtility.UrlDecode(kvp.Value)));
}
else
{
sb.Append(HttpUtility.UrlEncode(kvp.Value));
}
sb.Append("&");
}
sb.Remove(sb.Length - 1, 1); // Remove trailing &
return sb.ToString();
}
}
}