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;
}
Related
I am inserting calendar events into our domain users O365 calendars with Microsoft Graph API. I need to determine if the event exists, but my research has only shown how to use the GraphClient.Me.Events scenario to search. I don't believe this would work as we have global access to all calendars (Calendars.ReadWrite) within our domain.
Is there any way to search for the event in the applicable domain users calendar before sync?
var scopes = new string[] { "https://graph.microsoft.com/.default" };
var confidentialClient = ConfidentialClientApplicationBuilder.Create(clientId).WithTenantId(tenantId).WithClientSecret(clientSecret).Build();
var authResult = await confidentialClient.AcquireTokenForClient(scopes).ExecuteAsync();
using (HttpClient c = new HttpClient())
{
string url = "https://graph.microsoft.com/v1.0/users/" + userEmail + " /calendar/events";
ToOutlookCalendar createOutlookEvent = CreateEvent();
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(createOutlookEvent), Encoding.UTF8, "application/json");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
request.Content = httpContent;
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
var response = await c.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
}
The calendar event is currently very simple for testing
public static ToOutlookCalendar CreateEvent()
{
ToOutlookCalendar outlookEvent = new ToOutlookCalendar
{
Subject = "Code test migration appt",
Body = new Body
{
ContentType = "HTML",
Content = "Testing API with application client authorization"
},
Start = new End
{
DateTime = "2020-06-22T12:30:00",TimeZone = System.TimeZone.CurrentTimeZone.StandardName
},
End = new End
{
DateTime = "2020-06-22T14:00:00",TimeZone = System.TimeZone.CurrentTimeZone.StandardName
},
Location = new LocationName
{
DisplayName = "Sample Location"
}
};
return outlookEvent;
}
Assuming you're targeting the default calendar for the user, yes.
the /me path segment is an alias to the upn or userId, so something like:
"https://graph.microsoft.com/v1.0/users/" + userEmail + "/calendar/events?$filter=subject eq '" + knownTitle + "'"
Should work just fine if you're using an app only token with sufficent permissions
I need to remove a saved wifi profilefrom code, so that the SoftAP is enabled again. According to the ms docs, there is no way to remove a profile, only disconnect. Is this not possible?
Ms docs for wifi
https://learn.microsoft.com/en-us/uwp/api/windows.devices.wifi.wifiadapter
Device Portal API
https://learn.microsoft.com/de-ch/windows/mixed-reality/device-portal-api-reference#wifi-management
Here is my working code for disconnecting from a wifi using device portal API
// API creds
string username = "Administrator";
string password = "p#ssw0rd
// API request URIs
string apiUri = "http://192.168.1.15:8080/api/wifi/network";
// WiFi details
string wifiInterface = string.Empty;
string wifiProfile = string.Empty;
// WiFi access
WiFiAccessStatus wifiAccess = await WiFiAdapter.RequestAccessAsync();
if (wifiAccess == WiFiAccessStatus.Allowed)
{
// Get WiFi adapter
IReadOnlyList<WiFiAdapter> wifiAdapterResult = await WiFiAdapter.FindAllAdaptersAsync();
WiFiAdapter wifiAdapter = wifiAdapterResult[0];
// Get conn profile / details
ConnectionProfile profile = await wifiAdapter.NetworkAdapter.GetConnectedProfileAsync();
wifiInterface = profile.NetworkAdapter.NetworkAdapterId.ToString();
wifiProfile = profile.ProfileName;
}
// API creds
PasswordCredential credentials = new PasswordCredential("login", username, password);
// HttpClient filter
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.CookieUsageBehavior = HttpCookieUsageBehavior.NoCookies;
filter.CacheControl.ReadBehavior = HttpCacheReadBehavior.MostRecent;
filter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.NoCache;
filter.ServerCredential = credentials;
// HttpClient
HttpClient client = new HttpClient(filter);
apiUri = apiUri + "?interface=" + wifiInterface + "&op=disconnect" + "&createprofile=no";
// Request
HttpRequestMessage request = new HttpRequestMessage();
request.Method = new HttpMethod("POST");
request.RequestUri = new Uri(apiUri);
// Send request
try
{
// Response
HttpResponseMessage response = await client.SendRequestAsync(request);
// Again
if (response.Content.ToString().Contains("Authorization Required"))
{
response = await client.SendRequestAsync(request);
}
}
catch
{
// Dispose
client.Dispose();
filter.Dispose();
}
But for deleting a wifi profile, i get 404 not found back from the API. According to the API docs linked above, the request should be ok. Here is my code for deleting a wifi profile
// API creds
string username = "Administrator";
string password = "p#ssw0rd
// API request URIs
string apiUri = "http://192.168.1.15:8080/api/wifi/network";
// WiFi details
string wifiInterface = string.Empty;
string wifiProfile = string.Empty;
// WiFi access
WiFiAccessStatus wifiAccess = await WiFiAdapter.RequestAccessAsync();
if (wifiAccess == WiFiAccessStatus.Allowed)
{
// Get WiFi adapter
IReadOnlyList<WiFiAdapter> wifiAdapterResult = await WiFiAdapter.FindAllAdaptersAsync();
WiFiAdapter wifiAdapter = wifiAdapterResult[0];
// Get conn profile / details
ConnectionProfile profile = await wifiAdapter.NetworkAdapter.GetConnectedProfileAsync();
wifiInterface = profile.NetworkAdapter.NetworkAdapterId.ToString();
wifiProfile = profile.ProfileName;
}
// API creds
PasswordCredential credentials = new PasswordCredential("login", username, password);
// HttpClient filter
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.CookieUsageBehavior = HttpCookieUsageBehavior.NoCookies;
filter.CacheControl.ReadBehavior = HttpCacheReadBehavior.MostRecent;
filter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.NoCache;
filter.ServerCredential = credentials;
// HttpClient
HttpClient client = new HttpClient(filter);
apiUri = apiUri + "?interface=" + wifiInterface + "&profile=" + wifiProfile;
// Request
HttpRequestMessage request = new HttpRequestMessage();
request.Method = new HttpMethod("DELETE")
request.RequestUri = new Uri(apiUri);
// Send request
try
{
// Response
HttpResponseMessage response = await client.SendRequestAsync(request);
// Again
if (response.Content.ToString().Contains("Authorization Required"))
{
response = await client.SendRequestAsync(request);
}
}
catch
{
// Dispose
client.Dispose();
filter.Dispose();
}
Edit//
To close this problem, since build 17763, there is a new method for deleting WiFi profiles directly from code available
bool canDelete = wifiProfile.CanDelete;
if (canDelete)
{
ConnectionProfileDeleteStatus deleteStatus = await wifiProfile.TryDeleteAsync();
}
You may be able to call netsh from your program.
netsh wlan delete <profile name> should get you there.
After trying for hours, finally found a solution! For those who are interested, you have to call the "run command" API, which allows you to run certain windows commands
string deleteCommand = "netsh wlan delete profile name=*";
string cmdApi = string.Format("http://192.168.1.15:8080/api/iot/processmanagement/runcommand?command={0}&runasdefaultaccount={1}", GetBase64String(deleteCommand), GetBase64String("no"));
The really important thing to note here is that you have to encode the command as a base64 string, otherwise it won't work!
private string GetBase64String(string stringToConvert)
{
return Convert.ToBase64String(Encoding.UTF8.GetBytes(stringToConvert));
}
With this code, it is finally possible for me to delete either certain wifi profiles, or in the example case above, every saved profile.
Thanks a lot Andy for finding this. I was doing it with command line before but this does work. I added some supporting code around it to help others where I had some issues such as get, delete or post. If it works then I restart IoT to be back in Onboarding mode. Maybe someone will find this helpful.
Logging into the portal as admin may or may not be required but that is how I do it. The if (interfaceGUID != null) was assigned by a previous Api request and can be removed for testing.
private string password = "yourpassword";
private string localhost = "127.0.0.1";
private async Task DeleteProfile()
{
try
{
using (HttpClient client = new HttpClient())
{
if (interfaceGUID != null)
{
string deleteCommand = "netsh wlan delete profile name=*";
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, string.Format("http://{0}:8080/api/iot/processmanagement/runcommand?command={1}&runasdefaultaccount={2}", localhost, Convert.ToBase64String(Encoding.UTF8.GetBytes(deleteCommand)), Convert.ToBase64String(Encoding.UTF8.GetBytes("no")))))
{
request.Headers.Authorization = CreateBasicCredentials("Administrator");
using (HttpResponseMessage response = await client.SendAsync(request))
{
if (response.IsSuccessStatusCode == true)
{
ShutdownManager.BeginShutdown(Windows.System.ShutdownKind.Restart, TimeSpan.FromSeconds(1));
}
else
{
Debug.WriteLine("Could not delete the profiles. " + response.ReasonPhrase.ToString());
}
}
}
}
client.Dispose();
}
}
catch (Exception ex)
{
Debug.WriteLine("Could not delete the profiles. " + ex.InnerException.ToString());
}
}
private AuthenticationHeaderValue CreateBasicCredentials(string userName)
{
string toEncode = userName + ":" + password;
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
byte[] toBase64 = encoding.GetBytes(toEncode);
string parameter = Convert.ToBase64String(toBase64);
return new AuthenticationHeaderValue("Basic", parameter);
}
Been working on Windows device portal API recently and came across this post. The reason your code got 404 response is because in the API URI, the &profile= expects a Base64 value instead of a text string that you're using. Once you encode the profile name to Base64, it should work.
I believe this isn't explicitly stated in MS's device portal documentation, as I only discovered this by using web browser debugger to inspect Windows Device Portal web page when deleting a WIFI profile.
To close this problem, since build 17763, there is a new method for deleting WiFi profiles directly from code available
bool canDelete = wifiProfile.CanDelete;
if (canDelete)
{
ConnectionProfileDeleteStatus deleteStatus = await wifiProfile.TryDeleteAsync();
}
I'm trying to create a .NET web application integration with RTC, where I would insert new workitems using RTC change management services, as defined in this article (specifically in "Create a Change Request"). I was able to get the URL-to-be-used inside services.xml file (/oslc/contexts/_0_iN4G09EeGGMqpyZT5XdQ/workitems/) and my goal is to insert data using JSON.
My code is basically the following:
CookieContainer cookies = new CookieContainer();
HttpWebRequest documentPost = (HttpWebRequest)WebRequest.Create(rtcServerUrl + "/oslc/contexts/_0_iN4G09EeGGMqpyZT5XdQ/workitems/order");//"Order" is the workitem name
documentPost.Method = "POST";
documentPost.CookieContainer = cookies;
documentPost.Accept = "application/json";
documentPost.ContentType = "application/x-oslc-cm-change-request+json";
documentPost.Timeout = TIMEOUT_SERVICO;
string json = "{ \"dc:title\":\"" + title + "\", \"rtc_cm:filedAgainst\": [ { \"rdf:resource\" : \"" + rtcServerUrl + "/resource/itemOid/com.ibm.team.workitem.Category/" + idCategory + "\"} ] }"; //dc:title and rtc_cm:filedAgainst are the only two mandatory data from the workitem I'm trying to create
using (var writer = new StreamWriter(documentPost.GetRequestStream()))
{
writer.Write(json);
writer.Flush();
writer.Close();
}
Encoding encode = System.Text.Encoding.UTF8;
string retorno = null;
//Login
HttpWebRequest formPost = (HttpWebRequest)WebRequest.Create(rtcServerUrl + "/j_security_check");
formPost.Method = "POST";
formPost.Timeout = TIMEOUT_REQUEST;
formPost.CookieContainer = request.CookieContainer;
formPost.Accept = "text/xml";
formPost.ContentType = "application/x-www-form-urlencoded";
String authString = "j_username=" + userName + "&j_password=" + password; //create authentication string
Byte[] outBuffer = System.Text.Encoding.UTF8.GetBytes(authString); //store in byte buffer
formPost.ContentLength = outBuffer.Length;
System.IO.Stream str = formPost.GetRequestStream();
str.Write(outBuffer, 0, outBuffer.Length); //update form
str.Close();
//FormBasedAuth Step2:submit the login form and get the response from the server
HttpWebResponse formResponse = (HttpWebResponse)formPost.GetResponse();
var rtcAuthHeader = formResponse.Headers["X-com-ibm-team-repository-web- auth-msg"];
//check if authentication has failed
if ((rtcAuthHeader != null) && rtcAuthHeader.Equals("authfailed"))
{
//authentication failed. You can write code to handle the authentication failure.
//if (DEBUG) Console.WriteLine("Authentication Failure");
}
else
{
//login successful
HttpWebResponse responseRetorno = (HttpWebResponse)request.GetResponse();
if (responseRetorno.StatusCode != HttpStatusCode.OK)
retorno = responseRetorno.StatusDescription;
else
{
StreamReader reader = new StreamReader(responseRetorno.GetResponseStream());
retorno = "[Response] " + reader.ReadToEnd();
}
responseRetorno.Close();
formResponse.GetResponseStream().Flush();
formResponse.Close();
}
As I was managed to search for in other forums, this should be enough in order to create the workitem (I have a very similar code working to update workitems using "" URL and PUT method). However, instead of create the workitem in RTC and give me some response with item's identifier, the request's response returns a huge JSON file that ends with "oslc_cm:next":"https:///oslc/contexts/_0_iN4G09EeGGMqpyZT5XdQ/workitems/%7B0%7D?oslc_cm.pageSize=50&_resultToken=_AAY50FEkEee1V4u7RUQSjA&_startIndex=50. It's a JSON representation of the XML I receive when I access /oslc/contexts/_0_iN4G09EeGGMqpyZT5XdQ/workitems/ directly from browser, like I was trying to do a simple query inside the workitem's collection (even though I'm using POST, not GET).
I also tried to use PUT method, but then I receive a 405 status code.
Does anyone have an idea of what am I missing here? My approach is wrong, even though with the same approach I'm able to update existing workitem data in RTC?
Thanks in advance.
I am trying to use the API against our ALM 12.21 server, but always ends up with "401 Unauthorized". It seems that I get the auth cookie back correctly, but when I try to do something after that I am unauthorized.
I use this the get this to get auth cookie (seems to work):
HttpWebRequest myauthrequest = (HttpWebRequest)WebRequest.Create("https://server/qcbin/authentication-point/alm-authenticate");
string AuthenticationXML = #"<alm-authentication>
<user>username</user>
<password>password</password>
</alm-authentication>";
byte[] Requestbytes = Encoding.UTF8.GetBytes(AuthenticationXML);
myauthrequest.Method = "POST";
myauthrequest.ContentType = "application/xml";
myauthrequest.ContentLength = Requestbytes.Length;
myauthrequest.Accept = "application/xml";
Stream RequestStr = myauthrequest.GetRequestStream();
RequestStr.Write(Requestbytes, 0, Requestbytes.Length);
RequestStr.Close();
HttpWebResponse myauthres = (HttpWebResponse)myauthrequest.GetResponse();
var AuthenticationCookie = myauthres.Headers.Get("Set-Cookie");
AuthenticationCookie = AuthenticationCookie.Replace(";Path=/;HTTPOnly", "");
I am not sure if the .Replace is needed. Just read it somewhere. I get 401 both with or without it though, when trying to do subsequent requests.
Trying e.g. this after getting auth cookie:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://server/qcbin/rest/domains/FS/projects/P3602_SLS_Project/defects/1");
req.Method = "GET";
req.ContentType = "application/xml";
req.Accept = "application/octet-stream";
req.Headers.Set(HttpRequestHeader.Cookie, AuthenticationCookie);
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
Stream RStream2 = res.GetResponseStream();
XDocument doc = XDocument.Load(RStream2);
Which fails with 401.
Anyone have complete working code for the ALM 12.21 REST API?
You need two main cookies to get the ALM REST API works perfectly.
LWSSO_COOKIE_KEY
QCSession
almURL = "https://..com/qcbin/"
authEndPoint = almURL + "authentication-point/authenticate"
qcSessionEndPoint = almURL + "rest/site-session"
After you get successful response for authEndPoint you will get the LWSSO_COOKIE_KEY
Use that cookie in your next request to qcSessionEndPoint, it should give you QCSession cookie.
Use both LWSSO_COOKIE_KEY and QCSession cookies in your subsequent requests to get data from ALM.
I see that you are using octet-stream to get the defect response. When I checked the documentation, it can return one of the following types.
"application/xml"
"application/atom+xml"
"application/json"
Just in case, if you need to see some working implementation in python, here it is https://github.com/macroking/ALM-Integration/blob/master/ALM_Integration_Util.py
It may give you some idea.
Thank you #Barney. You sent me in the correct direction :-) For anyone interested, I managed it like this, e.g. for getting defect ID 473:
Logging on to create a CookieContainer and then use that to do the actual ALM data fetch:
private void button1_Click(object sender, EventArgs e)
{
string almURL = #"https://url/qcbin/";
string domain = "domain";
string project = "project";
CookieContainer cookieContainer = LoginAlm2(almURL, "username", "password", domain, project);
HttpWebRequest myWebRequest1 = (HttpWebRequest)WebRequest.Create(almURL + "/rest/domains/" + domain + "/projects/" + project + "/defects/473");
myWebRequest1.CookieContainer = cookieContainer;
myWebRequest1.Accept = "application/json";
WebResponse webResponse1 = myWebRequest1.GetResponse();
StreamReader reader = new StreamReader(webResponse1.GetResponseStream());
string res = reader.ReadToEnd();
}
public CookieContainer LoginAlm2(string server, string user, string password, string domain, string project)
{
//Creating the WebRequest with the URL and encoded authentication
string StrServerLogin = server + "/api/authentication/sign-in";
HttpWebRequest myWebRequest = (HttpWebRequest)WebRequest.Create(StrServerLogin);
myWebRequest.Headers[HttpRequestHeader.Authorization] = "Basic " + Base64Encode(user + ":" + password);
WebResponse webResponse = myWebRequest.GetResponse();
CookieContainer c = new CookieContainer();
Uri uri = new Uri(server);
string StrCookie = webResponse.Headers.ToString();
string StrCookie1 = StrCookie.Substring(StrCookie.IndexOf("LWSSO_COOKIE_KEY=") + 17);
StrCookie1 = StrCookie1.Substring(0, StrCookie1.IndexOf(";"));
c.Add(new Cookie("LWSSO_COOKIE_KEY", StrCookie1) { Domain = uri.Host });
//Then the QCSession cookie
string StrCookie2 = StrCookie.Substring(StrCookie.IndexOf("QCSession=") + 10);
StrCookie2 = StrCookie2.Substring(0, StrCookie2.IndexOf(";"));
c.Add(new Cookie("QCSession", StrCookie2) { Domain = uri.Host });
//Then the ALM_USER cookie
string StrCookie3 = StrCookie.Substring(StrCookie.IndexOf("ALM_USER=") + 9);
StrCookie3 = StrCookie3.Substring(0, StrCookie3.IndexOf(";"));
c.Add(new Cookie("ALM_USER", StrCookie3) { Domain = uri.Host });
//And finally the XSRF-TOKEN cookie
string StrCookie4 = StrCookie.Substring(StrCookie.IndexOf("XSRF-TOKEN=") + 12);
StrCookie4 = StrCookie4.Substring(0, StrCookie4.IndexOf(";"));
c.Add(new Cookie("XSRF-TOKEN", StrCookie4) { Domain = uri.Host });
return c;
}
Works like a charm :-)
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