how to post to facebook page wall from .NET - c#

I've created Facebook page.
I have no application secret and no access token.
I want to post to this page from my .NET desktop application.
How can I do it? Can anyone help please, where can I get access token for this?
Should I create a new Facebook Application? If yes, how can I grant permissions to this application to post on page's wall?
UPD1:
I have no website.
I need to post company's news from .NET desktop application to company's Facebook page.
All I have is Login/Password for Facebook Page Account.
UPD2:
I've created Facebook Application. With AppID/SecretKey. I can get access token. But...
How can I grant permissions to post to page's wall?
(OAuthException) (#200) The user hasn't authorized the application to perform this action

I have created a video tutorial showing how to do this at this location:
http://www.markhagan.me/Samples/Grant-Access-And-Post-As-Facebook-User-ASPNet
You will notice that, in my example, I am asking for both "publish_stream" and "manage_pages". This let's you also post on pages of which that users is an admin. Here is the full code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Facebook;
namespace FBO
{
public partial class facebooksync : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
CheckAuthorization();
}
private void CheckAuthorization()
{
string app_id = "374961455917802";
string app_secret = "9153b340ee604f7917fd57c7ab08b3fa";
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('&'))
{
//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);
client.Post("/me/feed", new { message = "markhagan.me video tutorial" });
}
}
}
}

You need to ask the user for the publish_stream permission. In order to do this you need to add publish_stream to the scope in the oAuth request you send to Facebook. The easiest way to do all of this is to use the facebooksdk for .net which you can grab from codeplex. There are some examples there of how to do this with a desktop app.
Once you ask for that permission and the user grants it you will receive an access token which you can use to post to your page's wall. If you need to store this permission you can store the access token although you might need to ask for offline_access permission in your scope in order to have an access token that doesn't expire.

You can use
https://www.nuget.org/packages/Microsoft.Owin.Security.Facebook/ to obtain users login and permission and
https://www.nuget.org/packages/Facebook.Client/
to post to feeds.
Below example is for ASP.NET MVC 5:
public void ConfigureAuth(IAppBuilder app)
{
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Facebook
var facebookOptions = new FacebookAuthenticationOptions
{
AppId = "{get_it_from_dev_console}",
AppSecret = "{get_it_from_dev_console}",
BackchannelHttpHandler = new FacebookBackChannelHandler(),
UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name,location",
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = context =>
{
context.Identity.AddClaim(new Claim("FacebookAccessToken", context.AccessToken)); // user acces token needed for posting on the wall
return Task.FromResult(true);
}
}
};
facebookOptions.Scope.Add("email");
facebookOptions.Scope.Add("publish_actions"); // permission needed for posting on the wall
facebookOptions.Scope.Add("publish_pages"); // permission needed for posting on the page
app.UseFacebookAuthentication(facebookOptions);
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
}
}
On the callback you get user access token:
public ActionResult callback()
{
// Here we skip all the error handling and null checking
var auth = HttpContext.GetOwinContext().Authentication;
var loginInfo = auth.GetExternalLoginInfo();
var identityInfo = auth.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie);
var email = loginInfo.Email // klaatuveratanecto#gmail.com
var name = loginInfo.ExternalIdentity.Name // Klaatu Verata Necto
var provider = loginInfo.Login.LoginProvider // Facebook | Google
var fb_access_token = loginInfo.identityInfo.FindFirstValue("FacebookAccessToken");
// Save this token to database, for the purpose of this example we will save it to Session.
Session['fb_access_token'] = fb_access_token;
// ...
}
Which then you can use to post to user's feed or page
public class postcontroller : basecontroller
{
public ActionResult wall()
{
var client = new FacebookClient( Session['fb_access_token'] as string);
var args = new Dictionary<string, object>();
args["message"] = "Klaatu Verata N......(caugh, caugh)";
try
{
client.Post("/me/feed", args); // post to users wall (feed)
client.Post("/{page-id}/feed", args); // post to page feed
}
catch (Exception ex)
{
// Log if anything goes wrong
}
}
}

You need to grant the permission "publish_stream".

Possibly the easiest way to do this is via Facebook PowerShell Module, http://facebookpsmodule.codeplex.com. This allows the same sort of operations as FacebookSDK, but via an IT-Admin scripting interface rather than a developer-oriented interface.
AFAIK there is still a limitation of Facebook Graph API that you will not be able to post references to other pages (e.g. #Microsoft) using the Facebook Graph API. This will apply to FacebookSDK, FacebookPSModule, and anything else built over Facebook Graph API.

You will get information on how to create a facebook app or link your website to facebook on https://developers.facebook.com/?ref=pf.
You will be able to download facebook sdk at http://facebooksdk.codeplex.com/. There are some good example given in the document section of the site.

public void PostImageOnPage()
{
string filename=string.Empty;
if(ModelState.IsValid)
{
//-------- save image in image/
if (System.Web.HttpContext.Current.Request.Files.Count > 0)
{
var file = System.Web.HttpContext.Current.Request.Files[0];
// fetching image
filename = Path.GetFileName(file.FileName);
filename = DateTime.Now.ToString("yyyyMMdd") + "_" + filename;
file.SaveAs(Server.MapPath("~/images/Advertisement/") + filename);
}
}
string Picture_Path = Server.MapPath("~/Images/" + "image3.jpg");
string message = "my message";
try
{
string PageAccessToken = "EAACEdEose0cBAAoWM3X";
// ————————create the FacebookClient object
FacebookClient facebookClient = new FacebookClient(PageAccessToken);
// ————————set the parameters
dynamic parameters = new ExpandoObject();
parameters.message = message;
parameters.Subject = "";
parameters.source = new FacebookMediaObject
{
ContentType = "image/jpeg",
FileName = Path.GetFileName(Picture_Path)
}.SetValue(System.IO.File.ReadAllBytes(Picture_Path));
// facebookClient.Post("/" + PageID + "/photos", parameters);// working for notification on user page
facebookClient.Post("me/photos", parameters);// woring using bingoapp access token not page in(image album) Post the image/picture to User wall
}
catch (Exception ex)
{
}
}

Related

C# TweetSharp not sending Tweets

I am using TweetSharp to send tweets to users (currently testing it) however it keeps coming back with Bad Authentication Data
{"errors":[{"code":215,"message":"Bad Authentication data."}]}
I have checked my app settings and it has full read and write access. I have also tried to regenerate my consumer keys but still not luck.
here is my code
public ActionResult AccessToken()
{
string oauth_consumer_key = "<consumer key>";
string oauth_consumer_secret = "<consumer secret>";
var service = new TwitterService(oauth_consumer_key, oauth_consumer_secret);
// Now we need the Token and TokenSecret
OAuthRequestToken requestToken = service.GetRequestToken("http://localhost:37808/");
string authURL = service.GetAuthorizationUri(requestToken).ToString();
Process.Start(authURL);
SendTweetOptions options = new SendTweetOptions();
options.Status = "Hello there Twitter";
service.SendTweet(options);
var re = service.Response.Response;
return View();
}
Am I doing anything wrong?
Finally solved the issue and it works well. Based upon comments from Yort.
public ActionResult AccessToken()
{
// Step 1 - Retrieve an OAuth Request Token
TwitterService service = new TwitterService(ConfigurationManager.AppSettings["TwitterConsumerKey"], ConfigurationManager.AppSettings["TwitterConsumerSecret"]);
// This is the registered callback URL
OAuthRequestToken requestToken = service.GetRequestToken("http://localhost:37808/Twitter/OToken");
// Step 2 - Redirect to the OAuth Authorization URL
Uri uri = service.GetAuthorizationUri(requestToken);
return new RedirectResult(uri.ToString(), false /*permanent*/);
//return View();
}
public ActionResult OToken()
{
return View();
}
public ActionResult UserInfo(string oauth_token, string oauth_verifier)
{
var requestToken = new OAuthRequestToken { Token = oauth_token };
// Step 3 - Exchange the Request Token for an Access Token
TwitterService service = new TwitterService(ConfigurationManager.AppSettings["TwitterConsumerKey"],
ConfigurationManager.AppSettings["TwitterConsumerSecret"]);
OAuthAccessToken accessToken = service.GetAccessToken(requestToken, oauth_verifier);
// Step 4 - User authenticates using the Access Token
service.AuthenticateWith(accessToken.Token, accessToken.TokenSecret);
TwitterUser user = service.VerifyCredentials(new VerifyCredentialsOptions());
ViewBag.Message = string.Format("{0}", user.ScreenName);
// Step 5 - Send Tweet to User TimeLine
SendTweetOptions options = new SendTweetOptions();
string URL = "file:\\C:\\Users\\<User>\\Desktop\\test.jpg";
string path = new Uri(URL).LocalPath;
// Sending with Media
using (var stream = new FileStream(path, FileMode.Open))
{
service.SendTweetWithMedia(new SendTweetWithMediaOptions
{
Status = "<status>",
Images = new Dictionary<string, Stream> { { path, stream } }
});
}
var responseText = service.Response.StatusCode;
if (responseText.ToString() == "OK")
{
ViewBag.Message = "Tweet Successful";
}
else
{
ViewBag.Message = "Tweet Unsuccessful";
}
return View();
}
}
I don't believe you can send Tweets as just a consumer, the Tweets have to be "owned" by a user account. You need to register a Twitter account, then do the full oauth authentication process to get an access token (in addition to the consumer token), then reauthorise the TweetSharp service using both tokens.
Your code above nearly gets there (I think). After the Process.start call there needs to be logic to use the verifier returned in the browser (a number displayed after the user logs in) to complete the auth process and act as that user. At the moment, your code gets half way through that process but does not complete it, so when you try to tweet your TweetSharp service is only authed as the app and not the user.
The originalTweetSharp readme.md does include the missing bits of code. Step 3 needs the actual verifier returned in the browser after login:
// Step 3 - Exchange the Request Token for an Access Token
string verifier = "123456"; // <-- This is input into your application by your user
OAuthAccessToken access = service.GetAccessToken(requestToken, verifier);
// Step 4 - User authenticates using the Access Token
service.AuthenticateWith(access.Token, access.TokenSecret);
//Now your tweet call should work here.
It also looks like you're doing this in a web app on the server? In which case you're using entirely the wrong oauth flow (I believe). This one is designed for desktop apps, hence the call that starts a new browser process for the user to login with. I'm not entirely sure how the web flow works as I've never used it, but I believe you need to redirect the user to the authorisation url you receive, and the callback registered with Twitter should point back to your site. I think there is some kind of state parameter that can be passed back through the oauth flow so you can implement your own logic to pickup where you left off based on a session id or similar.
I worked on this subject before. You have to developer account before the send tweet because you need tokens and keys. It's my windows service project.
I wrote my tokens and key codes in App.config
<appSettings>
<add key="twitterAccessToken" value="*****"/>
<add key="twitterAccessTokenSecret" value="*****"/>
<add key="twitterConsumerKey" value="*****"/>
<add key="twitterConsumerSecret" value="*****"/>
public static void SendTweet()
{
try
{
GetPixelImageFile();
string key = ConfigurationSettings.AppSettings.Get("twitterConsumerKey");
string secret = ConfigurationSettings.AppSettings.Get("twitterConsumerSecret");
string token = ConfigurationSettings.AppSettings.Get("twitterAccessToken");
string tokenSecret = ConfigurationSettings.AppSettings.Get("twitterAccessTokenSecret");
string message = "Color, Colorful, Pixel, Art, PixelColouring, Follow";
var service = new TweetSharp.TwitterService(key, secret);
service.AuthenticateWith(token, tokenSecret);
using (var stream = new FileStream(#"C:\Images\Pixel.png", FileMode.Open))
{
var result = service.SendTweetWithMedia(new SendTweetWithMediaOptions
{
Status = message,
Images = new Dictionary<string, Stream> { { "john", stream } }
});
SendMail("SendTweet", (result == null ? "" : result.Text));
}
}
catch (Exception ex)
{
SendMail("SendTweet", ex.Message);
}
}

Share Post as Facebook App on Facebook page

I have been using facebook api to share post on facebook page as facebook app. I have created facebook app.
The post also gets shared but the problem is, it is not being posted as a facebook app. Instead it asks user for login and then it shares post as a user. Any help regarding how could I share a post as a Facebook App would be appreciated as I have been trying this for a long time.
Thanx in advance friends.
The code that I have been using is as follows.
using Facebook;
protected void CheckAuthorization()
{
string authorizationCode = Request.QueryString["code"];
string access_token = Facebook_GetAccessToken(authorizationCode);
FacebookShare(access_token);
}
private string Facebook_GetAccessToken(string pAuthorizationCode)
{
string urlGetAccessToken = "https://graph.facebook.com/oauth/access_token";
urlGetAccessToken += "?client_id=my app id";
urlGetAccessToken += "&client_secret=app secret";
urlGetAccessToken += "&redirect_uri=" + Facebook_GetRedirectUri();
urlGetAccessToken += "&code=" + pAuthorizationCode;
string responseData = RequestResponse(urlGetAccessToken);
if (responseData == "")
{
return "";
}
NameValueCollection qs = HttpUtility.ParseQueryString(responseData);
string access_token = qs["access_token"] == null ? "" : qs["access_token"];
return access_token;
}
protected void FacebookShare(string token)
{
if (token != null)
{
Int64 transactionid = Convert.ToInt64(Cache["transactionid"]);
string app_id = "my app id";
string app_secret = "app secret";
string scope = "offline_access,read_stream,publish_actions,publish_stream,manage_pages,status_update";
dynamic parameters = new ExpandoObject();
parameters.link = "my website link";
parameters.name = "my project name";
parameters.picture= "my website logo";
var client = new FacebookClient(token);
client.Post("/1374775846180409/feed", parameters); // this is my facebook page id where I want to share post.
Response.Cookies["transaction"].Expires = DateTime.Now;
}
else
{
}
}
Regarding above code, I am getting Facebook Authorization code successfully.
You can only ask your user who has logged into your app to post on facebook, apps as such are not allowed to post.
You will need a page access token to post as the page, which have permissions to modify the data belonging to a Facebook Page. To obtain a page access token you need to start by obtaining a user access token, for which your user has to be logged into your app and asking for the manage_pages permission scope. Next, you can GET /me/accounts, which will return a page access token for each page that you manage.
This can not be accomplished using offline access or without logging in.

Twitter API Safe Authentication

I'm using the C# Twitterizer in a WPF application to authenticate users to Twitter so I can publish tweets to their stream. (But that's irrelevant because the question is about the API itself).
I do not wish to create a new login interface, I want to use Twitter's Login page embedded in a WebBrowser control. Does Twitter support the same authentication style as Facebook where the user logs in to the regular FB login page and the access token is sent back in the callback URL? Or sending the username and password is the only way to get an access token (in Twitter)?!
Here's an Oauth 1.0a class that works with Twitter, and allows what you want.
There's also a simple example that shows how to use the class.
The code looks like this:
OAuth.Manager oauth;
AuthSettings settings;
public void Foo()
{
oauth = new OAuth.Manager();
oauth["consumer_key"] = TWITTER_CONSUMER_KEY;
oauth["consumer_secret"] = TWITTER_CONSUMER_SECRET;
settings = AuthSettings.ReadFromStorage();
if (VerifyAuthentication())
{
Tweet("Hello, World");
}
}
private void Tweet(string message)
{
var url = "http://api.twitter.com/1/statuses/update.xml?status=" + message;
var authzHeader = oauth.GenerateAuthzHeader(url, "POST");
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
{
...
}
}
}
private bool VerifyAuthentication()
{
if (!settings.Completed)
{
var dlg = new TwitterAppApprovalForm(); // your form with an embedded webbrowser
dlg.ShowDialog();
if (dlg.DialogResult == DialogResult.OK)
{
settings.access_token = dlg.AccessToken;
settings.token_secret = dlg.TokenSecret;
settings.Save();
}
if (!settings.Completed)
{
MessageBox.Show("You must approve this app for use with Twitter\n" +
"before updating your status with it.\n\n",
"No Authorizaiton for TweetIt",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return false;
}
}
// apply stored information into the oauth manager
oauth["token"] = settings.access_token;
oauth["token_secret"] = settings.token_secret;
return true;
}
The TwitterAppApprovalForm is boilerplate, and is included in the example. When you have no cached access_token and token-secret, then that form pops open, hosting an embedded webbrowser that displays the Twitter authorization form. If you have the cached data, then you don't need to display that form.
Yes, Twitter seupports the same authentication style than Facebook called OAuth.
Facebook uses OAuth 2 and Twitter uses OAuth 1.0a
Take a look to Spring.NET Social Twitter : http://springframework.net/social-twitter/
It provides samples for what you are trying to do.

Getting information with Token. OAuth

I am creating an app to get information from Fitbit.com using OAuth.
protected void btnConnect_Click(object sender, EventArgs e)
{
// Create OAuthService object, containing oauth consumer configuration
OAuthService service = OAuthService.Create(
new EndPoint(RequestTokenUrl, "POST"), // requestTokenEndPoint
new Uri(AuthorizationUrl), // authorizationUri
new EndPoint(AccessTokenUrl, "POST"), // accessTokenEndPoint
true, // useAuthorizationHeader
"http://app.fitbit.com", // realm
"HMAC-SHA1", // signatureMethod
"1.0", // oauthVersion
new OAuthConsumer(ConsumerKey, ConsumerSecret) // consumer
);
try
{
var personRepository = new PersonRepository();
var person = personRepository.GetPersonById(int.Parse(personSelect.SelectedItem.Value));
OAuthRequest request = OAuthRequest.Create(
new EndPoint(ProfileUrl, "GET"),
service,
this.Context.Request.Url,
//this.Context.Session.SessionID);
person.FitbitAuthAccessToken,
);
request.VerificationHandler = AspNetOAuthRequest.HandleVerification;
OAuthResponse response = request.GetResource();
// Check if OAuthResponse object has protected resource
if (!response.HasProtectedResource)
{
var token = new OAuthToken(TokenType.Request, person.FitbitAuthAccessToken,
person.FitbitAuthSecret, ConsumerKey);
// If not we are not authorized yet, build authorization URL and redirect to it
string authorizationUrl = service.BuildAuthorizationUrl(response.Token).AbsoluteUri;
Response.Redirect(authorizationUrl);
}
person.FitbitAuthAccessToken = response.Token.Token;
person.FitbitAuthSecret = response.Token.Secret;
person.PersonEncodedId = Doc["result"]["user"]["encodedId"].InnerText;
personRepository.Update(person);
// Store the access token in session variable
Session["access_token"] = response.Token;
}
catch (WebException ex)
{
Response.Write(ex.Message);
Response.Close();
}
catch (OAuthRequestException ex)
{
Response.Write(ex.Message);
Response.Close();
}
}
I save Fitbit Access Token and Secret in database.
How can I get information using just Access token and secret, without authorizing every time?
This would assume that the FitBit api was robust enough to not quire authentication every single time. I have seen API's implementing OAuth where you have an authentication process, then from there most of your calls simply require the AccessToken or secret. I would look at the method signatures for the service and see what types of parameters they are requiring.
If you look at the FitBit API about authentication and accessing resources, you will see that you just need to request the data you are interested in and add in the oAuth header with the access token. Here is what it should look like (from the API page):
GET /1/user/-/activities/date/2010-04-02.json HTTP/1.1
Host: api.fitbit.com
Authorization: OAuth realm="api.fitbit.com",
oauth_consumer_key="fitbit-example-client-application",
oauth_token="8d3221fb072f31b5ef1b3bcfc5d8a27a",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1270248088",
oauth_nonce="515379974",
oauth_signature="Gf5NUq1Pvg3DrtxHJyVaMXq4Foo%3D"
oauth_version="1.0"`
The base signature string will look like:
GET&http%3A%2F%2Fapi.fitbit.com%2F1%2Fuser%2F-%2Factivities%2Fdate%2F2010-04-02.json&oauth_consumer_key%3Dfitbit-example-client-application%26oauth_nonce%3D515379974%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1270248088%26oauth_token%3D8d3221fb072f31b5ef1b3bcfc5d8a27a%26oauth_version%3D1.0
I figured I'd offer my VerifyAuthenticationCore that is part of my FitbitClient that inherits from OAuthClient. It took me a while to get this working but I found that I was missing HttpDeliveryMethods.AuthorizationHeaderRequest when I was creating the web request. Adding this allowed the call to stop returning bad request (400) error messages.
The code below is basically using the user id and the access token to get the user profile information. All calls should basically work this way. All you would need to do is change the url and provide the id and token.
protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response)
{
string username;
var accessToken = response.AccessToken;
var userId = response.ExtraData["encoded_user_id"];
var httpWebRequest = WebWorker.PrepareAuthorizedRequest(new MessageReceivingEndpoint(new Uri("http://api.fitbit.com/1/user/" + userId + "/profile.json"), HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest), accessToken);
var dictionary = new Dictionary<string, string>();
dictionary.Add("accesstoken", accessToken);
dictionary.Add("link", "http://www.fitbit.com/user/" + userId);
using (var webResponse = httpWebRequest.GetResponse())
{
using (var stream = webResponse.GetResponseStream())
using (var reader = new StreamReader(stream))
{
var profile = JObject.Parse(reader.ReadToEnd())["user"];
dictionary.AddItemIfNotEmpty("name", profile["displayName"]);
dictionary.AddItemIfNotEmpty("pictureUrl", profile["avatar"]);
username = dictionary["name"];
}
}
return new AuthenticationResult(true, ProviderName, userId, username, dictionary);
}

Post twitter update with Twitterizer

I have this piece of code:
var settings = WebConfigurationManager.AppSettings;
var consumerKey = settings["Twitter.ConsumerKey"];
var consumerSecret = settings["Twitter.ConsumerSecret"];
var authToken = settings["Twitter.OAuthToken"];
var authVerifier = settings["Twitter.OAuthVerifier"];
//var accessToken = GetAccessToken(
// consumerKey, consumerSecret, authToken, string.Empty);
var tokens = new OAuthTokens()
{
AccessToken = authToken,
AccessTokenSecret = authVerifier,
ConsumerKey = consumerKey,
ConsumerSecret = consumerSecret
};
TwitterStatus.Update(tokens, txtComment.Text);
All I need it to to is update my twitter status. Unfortunately it is not working. It only worked once when I initially logged in to twitter to grant the application access. I then stored the authToken and authVerifier so I can reuse them for future updates.
Any idea what is wrong?
UPDATE: I just changed the code to :
TwitterResponse<TwitterStatus> tweetResponse = TwitterStatus.Update(tokens, txtComment.Text);
if (tweetResponse.Result == RequestResult.Success)
lblMessage.Text = "Twitter status successfully posted.";
else
lblMessage.Text = string.Format("Twitter status update failed with Error: '{0}'",
tweetResponse.ErrorMessage);
and I get an error message: "Invalid / expired token".
You are storing the wrong values. The authToken and verifier values need to be quickly exchanged for an access token using OAuthUtility.GetAccessToken(...). The access token that is returned from that method is what should be stored and supplied to Twitterizer.
-Ricky
The Twitterizer Author
I wanted to be able to make a simple status update from C#/.NET, but didn't want to embed a big library.
So I wrote a small OAuth.Manager class that does this stuff.
It's described here:
OAuth with Verification in .NET
Sample code to update status:
var oauth = new OAuth.Manager();
oauth["consumer_key"] = CONSUMER_KEY;
oauth["consumer_secret"] = CONSUMER_SECRET;
oauth["token"] = your_stored_access_token;
oauth["token_secret"] = your_stored_access_secret;
var url = "http://api.twitter.com/1/statuses/update.xml?status=Hello+World";
var authzHeader = oauth.GenerateAuthzHeader(url, "POST");
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.Headers.Add("Authorization", authzHeader);
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
MessageBox.Show("There's been a problem trying to tweet:" +
Environment.NewLine +
response.StatusDescription +
Environment.NewLine +
Environment.NewLine +
"You will have to tweet manually." +
Environment.NewLine);
}
For the first time through, you need to get an access token and secret. This is done in a multi-step process, starting with this code:
var oauth = new OAuth.Manager();
oauth["consumer_key"] = MY_APP_SPECIFIC_KEY;
oauth["consumer_secret"] = MY_APP_SPECIFIC_SECRET;
oauth.AcquireRequestToken("https://api.twitter.com/oauth/request_token", "POST");
Step 2 is to tell the user** to visit https://api.twitter.com/oauth/authorize?oauth_token=XXXX where xxxx is replaced with the actual token received, accessible in this case by oauth["token"]. Step 3 is to tell the user to grab (ctrl-c) the PIN from the webpage and paste it into your app, where you use the pin to get another type of token.
A better way is to automate that web UI sequence by using a Windows Form with an embedded WebBrowser control. When you set the Url property of that control to the appropriate value, it will show that webpage for you, inside the main form of your own app. You can also automate the part where you retrieve the PIN. This reduces context switches for your user and makes things simpler to understand.
Anyway, with the pin you do, step 4:
oauth.AcquireAccessToken("https://api.twitter.com/oauth/access_token",
"POST",
pin);
...which sends out another HTTP REST request, and when it returns you will have an accesss token and secret, available in oauth["token"] and oauth["token_secret"].
This authorization stuff with the web UI needs to happen only once; after you get the access token and secret once, you can store them and re-use them. They never expire, says Twitter.
You can then proceed to sending the status update...
var url = "http://api.twitter.com/1/statuses/update.xml?status=Hello+World";
var authzHeader = oauth.GenerateAuthzHeader(url, "POST");
...
...as above.
I know I am late to the game, but I created an end-to-end video tutorial showing exactly how to do this: I create an application on dev.twitter.com, install twitterizer using nuget, write the code to handle the oauth and finally write the code to use the access tokens received from twitter to make a tweet.
Video: http://www.youtube.com/watch?v=TGEA1sgMMqU
Tutorial: http://www.markhagan.me/Samples/Grant-Access-And-Tweet-As-Twitter-User-ASPNet
Code (in case you don't wan to leave this page):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Twitterizer;
namespace PostFansTwitter
{
public partial class twconnect : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var oauth_consumer_key = "YOUR_CONSUMER_KEY_HERE";
var oauth_consumer_secret = "YOUR_CONSUMER_SECRET_KEY_HERE";
if (Request["oauth_token"] == null)
{
OAuthTokenResponse reqToken = OAuthUtility.GetRequestToken(
oauth_consumer_key,
oauth_consumer_secret,
Request.Url.AbsoluteUri);
Response.Redirect(string.Format("http://twitter.com/oauth/authorize?oauth_token={0}",
reqToken.Token));
}
else
{
string requestToken = Request["oauth_token"].ToString();
string pin = Request["oauth_verifier"].ToString();
var tokens = OAuthUtility.GetAccessToken(
oauth_consumer_key,
oauth_consumer_secret,
requestToken,
pin);
OAuthTokens accesstoken = new OAuthTokens()
{
AccessToken = tokens.Token,
AccessTokenSecret = tokens.TokenSecret,
ConsumerKey = oauth_consumer_key,
ConsumerSecret = oauth_consumer_secret
};
TwitterResponse<TwitterStatus> response = TwitterStatus.Update(
accesstoken,
"Testing!! It works (hopefully).");
if (response.Result == RequestResult.Success)
{
Response.Write("we did it!");
}
else
{
Response.Write("it's all bad.");
}
}
}
}
}

Categories