How to post an image to Twitter in C# - c#

I want to post an image to my Twitter account via C#. I can get access token code, everything is fine but I investigated a PHP code
$tmhOAuth = new tmhOAuth(array(
'consumer_key' => OAUTH_CONSUMER_KEY,
'consumer_secret' => OAUTH_CONSUMER_SECRET,
'user_token' => $oauth_token,
'user_secret' => $oauth_token_secret,
));
$image = "{$_FILES['image']['tmp_name']};type={$_FILES['image']['type']};filename={$_FILES['image']['name']}";
$code = $tmhOAuth->request('POST', 'https://upload.twitter.com/1/statuses/update_with_media.json',
array(
'media[]' => "#{$image}",
'status' => " " . $status, //A space is needed because twitter b0rks if first char is an #
'lat' => $lat,
'long' => $long,
),
true, // use auth
true // multipart
In PHP code, the OAuth class has a request method. In C# side, I used Twitterizer library which hasn't any request method in OAuth class. Then I used Webclient instead of request method. But I need to some Credentials to post data. But I don't know what/why I use username and password. Actually, I don't want to use any credentials. What can I use instead of credentials?
Second problem is, I always get an authorized errors (401) here is code
OAuthTokenResponse responseToken = OAuthUtility.GetAccessToken(ConsumerKey, ConsumerSecret, oauth_token, oauth_verifier);
OAuthTokens accessToken = new OAuthTokens();
accessToken.AccessToken = responseToken.Token;
accessToken.AccessTokenSecret = responseToken.TokenSecret;
accessToken.ConsumerKey = ConsumerKey;
accessToken.ConsumerSecret = ConsumerSecret;
TwitterResponse<TwitterUser> twitterResponse = TwitterAccount.VerifyCredentials(accessToken);
System.Net.ServicePointManager.Expect100Continue = false;
if (twitterResponse.Result != RequestResult.Unauthorized)
{
try
{
string URL = "https://upload.twitter.com/1/statuses/update_with_media.json";
WebClient client = new WebClient();
client.Credentials = new System.Net.NetworkCredential(uName, pass);
NameValueCollection postData = new NameValueCollection();
postData.Add("status", status);
postData.Add("media[]", Encoding.ASCII.GetString(bytesOfImage));
byte[] b = client.UploadValues(URL, "POST", postData); // 401 error.
}
catch (Exception e)
{
return e.Message;
}
So where is the problem in my code?

You can do this in LINQ to Twitter, using the TweetWithMedia method, like this:
static void TweetWithMediaDemo(TwitterContext twitterCtx)
{
string status = "Testing TweetWithMedia #Linq2Twitter " + DateTime.Now.ToString(CultureInfo.InvariantCulture);
const bool possiblySensitive = false;
const decimal latitude = StatusExtensions.NoCoordinate; //37.78215m;
const decimal longitude = StatusExtensions.NoCoordinate; // -122.40060m;
const bool displayCoordinates = false;
const string replaceThisWithYourImageLocation = #"..\..\images\200xColor_2.png";
var mediaItems =
new List<Media>
{
new Media
{
Data = Utilities.GetFileBytes(replaceThisWithYourImageLocation),
FileName = "200xColor_2.png",
ContentType = MediaContentType.Png
}
};
Status tweet = twitterCtx.TweetWithMedia(
status, possiblySensitive, latitude, longitude,
null, displayCoordinates, mediaItems, null);
Console.WriteLine("Media item sent - Tweet Text: " + tweet.Text);
}
Joe

Related

C# httpwebrequest is only sending GET requests even when method is set to POST

I'm using Xamarin C# and php to create a simple android app that sends coordinate data to an apache sql database. When I use httpwebrequest to send a POST request to the server php, it sends a GET instead. Even though I set the request type to POST. The strange thing is that other requests that I have used using the exact same code work okay, this one specifically isn't working.
public class gpsGetterScript{
public static double longitude;
public static double latitude;
public static SimpleLocationManager locationManager = new SimpleLocationManager();
public static void startGetLocation()
{
Timer timer = new Timer();
timer.Interval = 6 * 1000;
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
double lon = locationManager.LastLocation.Longitude;
double lat = locationManager.LastLocation.Latitude;
longitude = lon;
latitude = lat;
Console.WriteLine(lon.ToString());
Console.WriteLine(lat.ToString());
Dictionary<string, string> gpsData = new Dictionary<string, string>();
gpsData.Add("longitude", lon.ToString());
gpsData.Add("latitude", lat.ToString());
gpsData.Add("device_owner", "Test");
var url = "theURL";
var httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Method = "POST";
var contentType = "application/json";
//var contentType = "application/x-www-form-urlencoded";
httpRequest.ContentType = contentType;
var data = JsonConvert.SerializeObject(gpsData);
//var data = "longitude=" + lon.ToString() + "&latitude=" + lat.ToString() + "&device_owner=" + "Test";
using (var streamWriter = new StreamWriter(httpRequest.GetRequestStream()))
{
Console.WriteLine(data.ToString());
Console.WriteLine(httpRequest.RequestUri.ToString());
Console.WriteLine(httpRequest.Headers);
Console.WriteLine(httpRequest.Method);
streamWriter.Write(data);
}
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
}
}
timer.Elapsed += Timer_Elapsed;
timer.AutoReset = true;
timer.Start();
locationManager.StartLocationUpdates(LocationAccuracy.Balanced, 5, TimeSpan.FromMinutes(.5), TimeSpan.FromSeconds(20));
SimpleLocationLogger.Enabled = true;
}
}
here is one of the httprequests from a related project that does work (same server being used)
public static string sendLoginRequest(string email, string password)
{
var url = "theURL";
var httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
var data = "email=" + email + "&password=" + password;
using (var streamWriter = new StreamWriter(httpRequest.GetRequestStream()))
{
streamWriter.Write(data);
}
var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}
I know it is the app sending the wrong request, as when I made the php echo the request type it came back as GET. Strangely, when I use reqbin to make the POST request using the same URL, it works fine. It really is just for some reason the request in C# is not sending a POST. The other question about this was resolved by adding a www. to the api url, but that did not work for me.
UPDATE: 4/20/2022- Here is the php code
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
include_once '../../../Database.php';
include_once '../location_obj.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$database = new Database();
$db = $database->getConnection();
$data = json_decode(file_get_contents("php://input"));
$item = new location_obj($db);
$stmt = $item->InputCoordinates();
$item->longitude = $data->longitude;
$item->latitude = $data->latitude;
$item->device_owner = $data->device_owner;
if ($item->InputCoordinates()) {
echo json_encode(array("message" => "Successfully", "data" => $item, "Request Type" => $_SERVER['REQUEST_METHOD']));
}
else {
echo json_encode(array("error" => "failed! Check your data and try again.", "data" => $item, "Request Type" => $_SERVER['REQUEST_METHOD']));
}
}
else {
echo json_encode(array("error" => "Only the POST method is supported!", "Request Type" => $_SERVER['REQUEST_METHOD']));
}
?>`
I get the error {"error":"Only the POST method is supported!","Request Type":"GET"} but when I use reqbin I get "message": "Successfully", "data": { "longitude": "theLongitude", "latitude": "theLatitude", "device_owner": "Test" }, "Request Type": "POST"
I checked the url that is used using Console.WriteLine(url); , it is the right one.
I fixed it, seems I forgot to add a / at the end of the URL. It was https://example.com/api/v2/location/input instead of https://example.com/api/v2/location/input/

How to get Profile Info from the Google API in c#

I am buiding a web application in vs2017 with c#. My requirement is allow user to do login through Google login.
Please note I do not know MVC so I have to write the code in .cs page
I have read this article https://developers.google.com/identity/sign-in/web/sign-in and implemented it accordingly.
I have also created the oAuth client ID and client secret.
I have also installed - Install-Package Google.Apis.Oauth2.v2 -Version 1.38.0.1532
I am totally blank as how to proceed further. I have read so many article but I don't know how to implement it in c# code.
How do I send the access token to an API - there are so many API's - which will get me all these information viz First name, Last name, Date of birth or Age, Phone Number, Email, Address, City or town, Postal code?
I understand that People API will fetch me email and full name.
I would appreciate if someone could please help me going forward as what more nuget package should I install and how do I send token to the API through c# code
Created a button in Test.aspx page
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
// The ID token you need to pass to your backend:
var id_token = googleUser.getAuthResponse().id_token;
console.log("ID Token: " + id_token);
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:53028/1.aspx');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
console.log('Signed in as: ' + xhr.responseText);
};
xhr.send('idtoken=' + id_token);
}
On 1.aspx.cs
string idToken = Request.Form["idtoken"].Trim();
I want First name, Last name, Date of birth or Age, Phone Number, Email, Address, City or town, Postal code.
Update: I have added these lines of code in my .cs file and it return the name.
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "1basa5.apps.googleusercontent.com",
ClientSecret = "AG0LvAwZAD123"
},
new[] { "profile", "https://www.googleapis.com/auth/contacts.readonly" },
"me",
CancellationToken.None).Result;
// Create the service.
var service = new PeopleService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "M_Test",
});
PeopleResource.GetRequest peopleRequest = service.People.Get("people/me");
peopleRequest.RequestMaskIncludeField = "person.names";
Person profile = peopleRequest.Execute();
Now what is the use of id_Token here then? Should I do not pass it xhr.send('idtoken=' + id_token); from the client page?
You can make a call to the people api and request the information just set the authorization header and add the access token.
GET /v1/people/me HTTP/1.1
Host: people.googleapis.com
Content-length: 0
Authorization: Bearer [Access Token]
Your not actually using the .net client library. You might want to try following Web authorization
Note this information is only going to be available if the user filled it in. there are also a few other limitations.
First name, Last name (only name is returned)
Date of birth or Age (only returned if set public)
Phone Number (only returned if set public)
Email (only returned with email scope)
i'am use this documentation
1. In first you need get code. You must generate url for user like this:
var serv = app.Request.Url.GetLeftPart(UriPartial.Authority);
var str = "https://accounts.google.com/o/oauth2/v2/auth" +
"?scope=" + HttpUtility.UrlEncode("https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email") +
"&response_type=" + "code" +
"&access_type=offline" +
"&client_id=" + clien_id +
"&state=" + "test" +
"&redirect_uri=" + HttpUtility.UrlEncode(serv + "/index.html?action=google");
app.Response.Redirect(str);
in action=google you can use this function to exchange code on token.
static bool GetAccessToken(string access_code, string redirect_url, out string token)
{
try
{
var clien_id = ConfigurationManager.AppSettings["google_app_id"];
var clien_secret = ConfigurationManager.AppSettings["google_app_secret"];
var webRequest = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v4/token");
webRequest.Method = "POST";
string parameters = $"code={access_code}&client_id={clien_id}&client_secret={clien_secret}&redirect_uri={redirect_url}&grant_type=authorization_code";
var byteArray = Encoding.UTF8.GetBytes(parameters);
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = byteArray.Length;
var postStream = webRequest.GetRequestStream();
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
var response = webRequest.GetResponse();
postStream = response.GetResponseStream();
var reader = new StreamReader(postStream);
var tmp = reader.ReadToEnd();
var pat = "\"access_token\"";
var ind = tmp.IndexOf(pat);
if (ind != -1)
{
ind += pat.Length;
ind = tmp.IndexOf("\"", ind);
if (ind != -1)
{
var end = tmp.IndexOf("\"", ind + 1);
if (end != -1)
{
token = tmp.Substring(ind + 1, end - ind - 1);
return true;
}
}
}
token = tmp;
}
catch (Exception e)
{
Debug.WriteLine(e);
token = e.Message;
}
return false;
}
Get user profile
var access_code = app.Request.QueryString["code"];
if (access_code == null)
{
return;
}
var serv = app.Request.Url.GetLeftPart(UriPartial.Authority);
var access_token = "";
if (!GetAccessToken(access_code, HttpUtility.UrlEncode(serv + "/index.html?action=google"), out access_token))
{
return;
}
var res = "";
var web = new WebClient();
web.Encoding = System.Text.Encoding.UTF8;
try
{
res = web.DownloadString("https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + access_token);
}
catch (Exception ex)
{
return;
}

Yahoo Weather API using Oauth

I am stuck on implementing the Yahoo Weather private API call. This is my code snippet, whenever I call it using valid clientId & Secret it returns 401 (unauthorized).
var outhWc = new WebClient();
outhWc.Credentials = new NetworkCredential(clientId, clientSecret);
outhWc.Headers.Add(HttpRequestHeader.Accept, "application/json");
var outhresponse = outhWc.DownloadData("https://query.yahooapis.com/v1/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json");
It always throws an exception. I also try to pass username and password in NetworkCredentials and also try to pass clientId and Secret in Header but I cannot find a successful call.
So I've been stuck with the same issue here. Finally I implemented the following code, based on the oAuth c# simple class found at http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs
public void LoadWeather() {
string URLDes, Params = "";
string Signature, BaseURL, cKey, cSecret = "";
OAuthBase oAuth = new OAuthBase();
BaseURL = "http://weather.yahooapis.com/forecastrss?w=" + textBox1.Text + "&u=f";
cKey = "YOUR API KEY";
cSecret = "YOUR API SECRET";
Signature = oAuth.GenerateSignature(new Uri(BaseURL), cKey, cSecret, "", "", "GET", oAuth.GenerateTimeStamp(), oAuth.GenerateNonce(), out URLDes, out Params);
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri(String.Format("{0}?{1}&oauth_signature={2}", URLDes, Params, Signature)));
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e) {
if (e.Error == null) {
XDocument xdoc = XDocument.Parse(e.Result, LoadOptions.None);
xdoc.Save("c:\\weather.xml");
richTextBox1.Text = xdoc.FirstNode.ToString();
} else {
richTextBox1.Text = e.Error.Message;
}
}
As you can see, I already have the city ID. This sample downloads the xml string returned by the API. Worked for me, hope it helps!

oauth_problem=token_rejected when refreshing Yahoo's OAuth Access Token

I've done Oauth with Hammock, I succeed to get access token, access token secret and session handle but now I must get the refresh access token when the token expired.
I've followed the instruction and I tried to pass the access token with urldecode and without urldecode but I can't get the token, I obtain
oauth_problem=token_rejected
UPDATE:
that's my code:
##the call##
var AccessTokenQuery = OAuthUtil.GetAccessTokenQueryRenewal(accessToken, session_handle, accessTokenSecret);
AccessTokenQuery.RequestAsync(AppSettings.AccessTokenUri, null);
AccessTokenQuery.QueryResponse += new EventHandler<WebQueryResponseEventArgs>(AccessTokenQuery_QueryResponse);
internal static OAuthWebQuery GetAccessTokenQueryRenewal(string oauth_token,string session_handle, string oauth_token_secret)
{
var oauth = new OAuthWorkflow
{
AccessTokenUrl = AppSettings.AccessTokenUri,
ConsumerKey = AppSettings.consumerKey,
ConsumerSecret = AppSettings.consumerKeySecret,
SignatureMethod = OAuthSignatureMethod.HmacSha1,
ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader,
TokenSecret = oauth_token_secret,
Token = oauth_token,
SessionHandle = session_handle,
Version = AppSettings.oAuthVersion
};
var info = oauth.BuildAccessTokenInfo(WebMethod.Post);
var objOAuthWebQuery = new OAuthWebQuery(info, false);
objOAuthWebQuery.HasElevatedPermissions = true;
objOAuthWebQuery.SilverlightUserAgentHeader = "Hammock";
return objOAuthWebQuery;
}
void AccessTokenQuery_QueryResponse(object sender, WebQueryResponseEventArgs e)
{
try
{
StreamReader reader = new StreamReader(e.Response);
string strResponse = reader.ReadToEnd();
var parameters = MainUtil.GetQueryParameters(strResponse);
accessToken = parameters["oauth_token"];
accessTokenSecret = parameters["oauth_token_secret"];
session_handle = parameters["oauth_session_handle"];
MainUtil.SetKeyValue<string>("AccessToken", accessToken);
MainUtil.SetKeyValue<string>("AccessTokenSecret", accessTokenSecret);
MainUtil.SetKeyValue<string>("SessionHandle", session_handle);
userLoggedIn();
}
catch (Exception ex)
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.Message);
});
}
}
Quick possibility you could try: you said you 'tried to pass the access token with urldecode'. Have you tried using urlencode? Urldecode is used for decoding urls returned from a web call, encoding is what is done before passing to a web call.
Also, note that the encoding scheme for Oauth is slightly different than the one used in .NET 's default encoding. You can easily write your own encoding routine though, check out the oauth spec for details.
Ex:
private string UrlEncode(string value)
{
string unreserved = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
StringBuilder result = new StringBuilder();
foreach (char symbol in value)
{
if (unreserved.IndexOf(symbol) != -1)
result.Append(symbol);
else
result.Append('%' + String.Format("{0:X2}", (int)symbol));
}
return result.ToString();
}

HTTP POST is giving unauthorized 401 Exception

When calling the same method on google chrome postman after logging in, i'm getting the json object as shown below.
but when i try to get the same json result in codebehind (C#). I'm getting Unauthorized 401 exception.
I'm using my code like this.
using (var clientSideTab = new WebClient())
{
var valSideTab = new System.Collections.Specialized.NameValueCollection { { "username", UserID }, { "Password", strPassword } };
string UpldDataSideTab = "https://resapistage.namechanged.com/v3/secure/Login.aspx?userId=" + UserID + "&passwd=" + strPassword + " ";
SystemComponentWrapper SPPostWrapper = new SystemComponentWrapper();
SystemComponentData request = new SystemComponentData();
SystemComponentaddressId addressId = new SystemComponentaddressId();
addressId.type = "AddressId";
addressId.id = 19863;
addressId.serial = "";
request.addressId = addressId;
request.compId = null;
request.getCompParams = true;
request.filterForAddress = false;
SPPostWrapper.request = request;
var postJson = JsonConvert.SerializeObject(SPPostWrapper);
Encoding encoding = new UTF8Encoding();
string postData = postJson.ToString();
byte[] bdata = encoding.GetBytes(postData);
string URI = "https://resapistage.namechanged.com/v3/api/secure/json/AddressInfo.svc/getSystemComponentsV2";
clientSideTab.UploadValues(UpldDataSideTab, "POST", valSideTab);
clientSideTab.Headers.Add("Content-Type","application/json; charset=utf-8");
clientSideTab.Headers.Add("Accept","application/json");
clientSideTab.UploadString(URI,"POST", postData);
//clientSideTab.UploadData(URI, "POST", bdata);
String jsonresponse = "failed";
Label1.Text = jsonresponse;
}
I'm getting this error everytime. please help me.
use like this.
string cookie = strCookie[0]; // fetch your cookie after logging in
clientSideTab.Headers.Add("Content-Type","application/json; charset=utf-8");
clientSideTab.Headers.Add("Accept","application/json");
clientSideTab.m_container.SetCookies(URI, cookie);
//clientSideTab.Headers.Add(HttpRequestHeader.Cookie, cookie);
String resultJSON = clientSideTab.UploadString(URI,"POST", jsonData);
this worked for me. hope this will help you.

Categories

Resources