I have one problem. I have two methods which use HttpWebRequest. One of them post a message to my facebook wall. Another take count number of likes.
Thare is code:
if (Request["code"] == null)
{
Response.Redirect(string.Format(
"https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}&scope={2}",
app_id, Request.Url.AbsoluteUri, scope));
}
else
{
Dictionary<string, string> tokens = new Dictionary<string, string>();
string url =
string.Format(
"https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&scope={2}&code={3}&client_secret={4}",
app_id, Request.Url.AbsoluteUri, scope, Request["code"].ToString(), app_secret);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string vals = reader.ReadToEnd();
foreach (string token in vals.Split('&'))
{
//meh.aspx?token1=steve&token2=jake&...
tokens.Add(token.Substring(0, token.IndexOf("=")),
token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1));
}
}
//get wall data
string access_token = tokens["access_token"];
var client = new FacebookClient(access_token);
//post message to my wall or image
dynamic messagePost = new ExpandoObject();
messagePost.message = "I need to get an id of this post";
try
{
var postId = client.Post("me/feed", messagePost);
id_mypost = postId["id"];
}
catch (FacebookOAuthException ex)
{
//handle oauth exception
}
catch (FacebookApiException ex)
{
//handle facebook exception
}
}
This method post message to my wall. Thare is the second method:
if (Response.BufferOutput == true)
{
if (Request["code"] == null)
{
Response.Redirect(string.Format(
"https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}&scope={2}",
app_id, Request.Url.AbsoluteUri, scope));
}
else
{
Dictionary<string, string> tokens = new Dictionary<string, string>();
string url =
string.Format(
"https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&scope={2}&code={3}&client_secret={4}",
app_id, Request.Url.AbsoluteUri, scope, Request["code"].ToString(), app_secret);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string vals = reader.ReadToEnd();
foreach (string token in vals.Split('&'))
{
//meh.aspx?token1=steve&token2=jake&...
tokens.Add(token.Substring(0, token.IndexOf("=")),
token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1));
}
}
string access_token = tokens["access_token"];
var client = new FacebookClient(access_token);
try
{
string str = client.Get("/me/feed").ToString();
JObject obj = JObject.Parse(str);
JToken jUser = obj["data"];
int numb = jUser.Count();
int id_post = 0;
for (int i = 0; i < numb; i++)
{
if (obj["data"][i]["id"].ToString() == id_mypost)
{
id_post = i;
}
}
string strr = obj["data"][id_post]["likes"].ToString();
string pattern = #"id";
int count_like = 0;
Regex newReg = new Regex(pattern);
MatchCollection matches = newReg.Matches(strr);
foreach (Match mat in matches)
{
count_like++;
}
}
catch (Exception)
{
}
}
So thare is the problem. I use two times HttpWebRequest. So , when I bild my app i got next error: Cannot redirect after HTTP headers have been sent.
Can somebody help me ?
Cannot redirect after HTTP headers have been sent.
This is the error of asynchronous operation. For example if you are using any thread operation and in that thread you try Response.redirect it will give this error.
The response is already sent to client before the statement executes.
Can you please tell me where exactly the error is occurring ?
Related
I'm trying to communicate with some server but the Authorization header gets removed when I use a GET request.
My code (please excuse the mess):
public ApiResponse MakeApiRequest(string path, string body, Dictionary<string, string> header,
Dictionary<string, string> query, string method)
{
var queryBuilder = new StringBuilder("?");
foreach (var queryPair in query)
{
queryBuilder.Append(queryPair.Key + "=" + queryPair.Value + "&");
}
var queryString = queryBuilder.ToString();
queryString = queryString.Substring(0, queryString.Length - 1);
var request = (HttpWebRequest) WebRequest.Create(new Uri(ApiServer + path + queryString));
request.Timeout = 5000;
request.UserAgent = "VSpedSync/DevBuild";
request.Method = method;
foreach (var headerPair in header)
{
if (headerPair.Key.ToLower().Equals("user-agent")) continue;
if (headerPair.Key.ToLower().Equals("authorization"))
{
request.PreAuthenticate = true;
}
request.Headers.Add(headerPair.Key, headerPair.Value);
}
Debug.WriteLine("preauth "+request.PreAuthenticate);
if (!body.Equals(""))
{
var stream = request.GetRequestStream();
var streamWriter = new StreamWriter(stream);
streamWriter.Write(body);
streamWriter.Close();
}
HttpWebResponse response;
try
{
response = (HttpWebResponse) request.GetResponse();
}
catch (WebException ex)
{
response = (ex.Response as HttpWebResponse);
if (response == null)
throw;
}
foreach (string requestHeader in request.Headers)
{
Debug.WriteLine(" --> "+requestHeader+": "+request.Headers.Get(requestHeader));
}
var statusCode = response.StatusCode;
var responseHeaders = new Dictionary<string, string>();
foreach (string headerKey in response.Headers)
{
var headerVal = response.Headers.Get(headerKey);
responseHeaders.Add(headerKey, headerVal);
}
var responseBody = "NONE";
try
{
var streamReader = new StreamReader(response.GetResponseStream());
responseBody = streamReader.ReadToEnd();
}
catch (Exception)
{
responseBody = "ERROR";
// ignored
}
return new ApiResponse(
statusCode,
responseBody,
!responseBody.Equals("ERROR") && !responseBody.Equals("NONE"),
responseHeaders
);
}
This is how I call the method:
var apiResponse = api.MakeApiRequest("auth/check/", "", new Dictionary<string, string>()
{
{"Authorization", "Bearer " + token.token},
{"test", "f"}
}, new Dictionary<string, string>(), "GET");
The headers that are sent when I use the GET method:
--> User-Agent: VSpedSync/DevBuild
--> test: f
--> Host: localhost:55445
The headers that are sent when I use the POST method:
--> User-Agent: VSpedSync/DevBuild
--> Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--> test: f
--> Host: localhost:55445
Am I doing something wrong?
Edit: Seems to be solved. I'm using RestSharp now instead of the normal WebRequest.
You can try to use the HttpClient instead of the WebRequest. I tried the following and the authorization header stayed in the request after sending it.
const string ApiServer = "https://google.com";
static readonly HttpClient _httpClient = new HttpClient();
static async Task Main()
{
InitializeClient();
var headers = new Dictionary<string, string>()
{
{ "Authorization", "Bearer e45jsh56" },
{ "Test", "test_value" }
};
var paramterers = new Dictionary<string, string>()
{
{ "pageNum", "3" },
{ "pageSize", "100" }
};
var response = await MakeApiCallAsync("mypath", "request_body", headers, paramterers, "GET");
Console.WriteLine($"Status Code: {response.StatusCode}.");
}
static void InitializeClient()
{
// Set the base URI
_httpClient.BaseAddress = new Uri(ApiServer);
// Set Timeout to 5 seconds
_httpClient.Timeout = new TimeSpan(hours: 0, minutes: 0, seconds: 5);
// Set the default User Agent
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("VSpedSync/DevBuild");
}
static async Task<ApiResponse> MakeApiCallAsync(string path,
string body, Dictionary<string, string> headers,
Dictionary<string, string> query, string method)
{
// Generate query string
string queryString = '?' +
string.Join(separator: '&', values: query.Select(q => $"{q.Key}={q.Value}"));
// Create the relative URL
string relativeUrl = path + queryString;
// Create the Http Method object
HttpMethod httpMethod = new HttpMethod(method);
// Create the request object
HttpRequestMessage request = new HttpRequestMessage(httpMethod, relativeUrl);
// Set headers to the request
foreach (KeyValuePair<string, string> h in headers)
{
if (!h.Key.Equals("UserAgent", StringComparison.OrdinalIgnoreCase))
{
request.Headers.Add(h.Key, h.Value);
}
}
// Set the content of the request
if (!string.IsNullOrEmpty(body))
{
request.Content = new StringContent(body);
}
// Send the request
HttpResponseMessage response = await _httpClient.SendAsync(request);
// Display request headers
foreach(var h in request.Headers)
{
Console.WriteLine($" --> {h.Key}: {string.Join(';', h.Value)}.");
}
// Process the response body
string responseBody = "NONE";
try
{
// Read the content as a string
responseBody = await response.Content.ReadAsStringAsync();
}
catch
{
responseBody = "ERROR";
}
// Return the api response
return new ApiResponse
{
StatusCode = response.StatusCode,
ResponseBody = responseBody,
ValidResponse = !responseBody.Equals("NONE") && !responseBody.Equals("ERROR"),
ResponseHeaders = response.Headers.ToDictionary(h => h.Key, h => string.Join(';', h.Value)),
};
}
Output
--> Authorization: Bearer e45jsh56.
--> Test: test_value.
--> User-Agent: VSpedSync/DevBuild.
Status Code: BadRequest.
Maybe try to use the WebHeaderCollection.Add(HttpRequestHeader, String) overload method.
public static ApiResponse MakeApiRequest(string path, string body, Dictionary<string, string> headers,
Dictionary<string, string> query, string method)
{
// Generate the query string
string queryString = '?' +
string.Join(separator: '&', values: query.Select(q => $"{q.Key}={q.Value}"));
// Create request obejct
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(ApiServer + path + queryString));
request.Timeout = 5000;
request.UserAgent = "VSpedSync/DevBuild";
request.Method = method;
// Set headers to the request
foreach (KeyValuePair<string, string> h in headers)
{
if (h.Key.Equals("Authorization", StringComparison.OrdinalIgnoreCase))
{
request.Headers.Add(HttpRequestHeader.Authorization, h.Value);
}
else if (!h.Key.Equals("UserAgent", StringComparison.OrdinalIgnoreCase))
{
request.Headers.Add(h.Key, h.Value);
}
}
foreach (string requestHeader in request.Headers)
{
Debug.WriteLine(" --> " + requestHeader + ": " + request.Headers.Get(requestHeader));
}
// ...
// .... Continue ....
// ...
return null;
}
private void CheckAuthorization()
{
string app_id = "*****";
string app_secret = "******";
string scope = "manage_pages,publish_pages";
if (Request["code"] == null)
{
Response.Redirect(string.Format(
"https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}&scope={2}",
app_id, Request.Url.AbsoluteUri, scope));
}
else
{
Dictionary<string, string> tokens = new Dictionary<string, string>();
string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&scope={2}&code={3}&client_secret={4}",
app_id, Request.Url.AbsoluteUri, scope, Request["code"].ToString(), app_secret);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string vals = reader.ReadToEnd();
foreach (string token in vals.Split('&'))
{
//meh.aspx?token1=steve&token2=jake&...
tokens.Add(token.Substring(0, token.IndexOf("=")),
token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1));
}
}
string access_token = tokens["access_token"];
//tokens["access_token"];
var client = new FacebookClient(access_token);
Dictionary<string, string> data = new Dictionary<string, string>();
client.Post("/1038145769594318/feed", new
{
message = " test page post",
picture = "http://service.extrabucks.in/EmailTemplateCss/7/images/bottom-background2.png",
name = "Nikunj Patel",
link = "www.extrabucks.in",
description = "Test Description",
type = "links"
});
}
}
Hey i am using this code for post on Facebook using c# but the problem is that it's not post as a page it's post as a user. I want to post as a Page in my Fan page. please give me a solution using the above code. and one more thing i want life-time Working access_token what should i do ?
thanks in advance
public static string GetPageAccessToken(string userAccessToken)
{
FacebookClient fbClient = new FacebookClient();
fbClient.AppId = "*****";
fbClient.AppSecret = "**************";
fbClient.AccessToken = userAccessToken;
Dictionary<string, object> fbParams = new Dictionary<string, object>();
JsonObject publishedResponse = fbClient.Get("/me/accounts", fbParams) as JsonObject;
JArray data = JArray.Parse(publishedResponse["data"].ToString());
foreach (var account in data)
{
if (account["name"].ToString().ToLower().Equals("opening shortly"))
{
return account["access_token"].ToString();
}
}
return String.Empty;
}
this code is working for me for refreshing page access tokens every time
just add
client.Post("/1038145769594318/feed", new
{
message = " test page post",
picture = "",
name = "Nikunj Patel",
link = "www.extrabucks.in",
description = "Test Description",
type = "photo",
access_token = GetPageAccessToken(access_token)
});
After quite searching i was able to post on Facebook Page as myself. but my target was to post on the Page i manage as the page. I did some more research and i was able to get the access token of the page i manage. when i tried to POST on it, sdk gave me the error that
The user hasn't authorized the application to perform this action
here is my code for your reference :
string app_id = "xxxxx";
string app_secret = "yyyyyyy";
string scope = "publish_actions,manage_pages";
if (Request["code"] == null)
{
string url = string.Format(
"https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}&scope={2}",
app_id, Request.Url.AbsoluteUri, scope);
Response.Redirect(url, false);
}
else
{
Dictionary<string, string> tokens = new Dictionary<string, string>();
string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&scope={2}&code={3}&client_secret={4}",
app_id, Request.Url.AbsoluteUri, scope, Request["code"].ToString(), app_secret);
HttpWebRequest request = System.Net.WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string vals = reader.ReadToEnd();
foreach (string token in vals.Split('&'))
{
tokens.Add(token.Substring(0, token.IndexOf("=")),
token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1));
}
}
string access_token = tokens["access_token"];
var client = new FacebookClient(access_token);
dynamic parameters = new ExpandoObject();
parameters.message = "Check out this funny article";
parameters.link = "http://www.natiska.com/article.html";
parameters.picture = "http://www.natiska.com/dav.png";
parameters.name = "Article Title";
parameters.caption = "Caption for the link";
//zzzzzzz is my fan page
string pageAccessToken = "";
JsonObject jsonResponse = client.Get("me/accounts") as JsonObject;
foreach (var account in (JsonArray)jsonResponse["data"])
{
string accountName = (string)(((JsonObject)account)["name"]);
if (accountName == MY_PAGE_NAME)
{
pageAccessToken = (string)(((JsonObject)account)["access_token"]);
break;
}
}
client = new FacebookClient(pageAccessToken);
client.Post("/zzzzzzz/feed", parameters);
You need the publish_pages permission to post as pages.
https://developers.facebook.com/docs/graph-api/reference/v2.3/page/feed#publish
Your Facebook App Dosn't have manage_page & publish_page permission, instead of this you can create test application and from that u can create test users for your testing .
From there u can manage all the pages posts and data.
I have the following code:
public void CheckAuthorization()
{
string app_id = "";//Your id here
string app_secret = "";//your secret key
string scope = "publish_stream, manage_pages";
if (Request["code"] == null)
{
Response.Redirect(string.Format("https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}&scope={2}",
app_id, Request.Url.AbsoluteUri, scope));
}
else
{
Dictionary<string, string> tokens = new Dictionary<string, string>();
string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&scope={2}&code={3}&client_secret={4}",
app_id, Request.Url.AbsoluteUri, scope, Request["code"].ToString(), app_secret);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string vals = reader.ReadToEnd();
foreach (string token in vals.Split('&'))
{
tokens.Add(token.Substring(0, token.IndexOf("=")), token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=")-1));
}
}
string access_token=tokens["access_token"];
var client = new FacebookClient(access_token);
client.Post("me/feed", new { message="Hi"});
}
}
Using this code , I can post to my profile using the line
client.Post("me/feed", new { message="Hi"});
How can I go about posting on other profiles?
Try this:
client.Post("/PROFILE_ID/feed", new { message="Hi"});
More info: https://developers.facebook.com/docs/reference/api/#publishing
I am encountering a problem getting the access_token in client application using oauth.
The returned response has empty body though in API I can see the response is not empty.
tokenresponse = {
"access_token":"[ACCESSTOKENVALUE]",
"token_type":"bearer",
"expires_in":"1200",
"refresh_token":"[REFRESHTOKENVALUE]",
"scope":"[SCOPEVALUE]"
}
The method from API that returns the token http://api.sample.com/OAuth/Token:
public ActionResult Token()
{
OutgoingWebResponse response =
this.AuthorizationServer.HandleTokenRequest(this.Request);
string tokenresponse = string.Format("Token({0})", response!=null?response.Body:""));
return response.AsActionResult();
}
The client method that requests the token is:
public string GetAuthorizationToken(string code)
{
string Url = ServerPath + "OAuth/Token";
string redirect_uri_encode = UrlEncode(ClientPath);
string param = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",code, ClientId, ClientSecret, redirect_uri_encode);
HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
string result = null;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = 10000;
request.Headers.Remove(HttpRequestHeader.Cookie);
var bs = Encoding.UTF8.GetBytes(param);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse response = request.GetResponse())
{
var sr = new StreamReader(response.GetResponseStream());
result = sr.ReadToEnd();
sr.Close();
}
if (!string.IsNullOrEmpty(result))
{
TokenData tokendata = JsonConvert.DeserializeObject<TokenData>(result);
return UpdateAuthorizotionFromToken(tokendata);
}
return null;
}
The result variable is empty.
Please let me know if you have any idea what could cause this. Initially I assumed is because of the cookies so I tried to remove them from request.
Thanks in advance.
Dear just create webclient using following code and you will get json info in tokeninfo.I used it and simply its working perfect.
WebClient client = new WebClient();
string postData = "client_id=" + ""
+ "&client_secret=" + ""
+ "&grant_type=password&username=" + "" //your username
+ "&password=" + "";//your password :)
string soundCloudTokenRes = "https://api.soundcloud.com/oauth2/token";
string tokenInfo = client.UploadString(soundCloudTokenRes, postData);
You can then use substring that contains only token from tokeninfo.
To upload tracks on sound cloud.
private void TestSoundCloudupload()
{
System.Net.ServicePointManager.Expect100Continue = false;
var request = WebRequest.Create("https://api.soundcloud.com/tracks") as HttpWebRequest;
//some default headers
request.Accept = "*/*";
request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");
request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
request.Headers.Add("Accept-Language", "en-US,en;q=0.8,ru;q=0.6");
//file array
var files = new UploadFile[] { new UploadFile(Server.MapPath("Downloads//0.mp3"), "track[asset_data]", "application/octet-stream") };
//other form data
var form = new NameValueCollection();
form.Add("track[title]", "Some title");
form.Add("track[sharing]", "public");
form.Add("oauth_token", "");
form.Add("format", "json");
form.Add("Filename", "0.mp3");
form.Add("Upload", "Submit Query");
try
{
using (var response = HttpUploadHelper.Upload(request, files, form))
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
Response.Write(reader.ReadToEnd());
}
}
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}