I am having problem posting the photo to the facebook.Anybody know how to it. Please help. Thanks.
FacebookClient fb = new FacebookClient(App.AccessToken);
fb.PostCompleted += (o, e) =>
{
if (e.Error != null)
{
Dispatcher.BeginInvoke(() => MessageBox.Show(e.Error.Message));
return;
}
var result = (IDictionary<string, object>)e.GetResultData();
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Success post message to the wall.");
// reset the selections after the post action has successfully concluded
tbmessage.Text = "";
});
};
var parameters = new Dictionary<string, object>();
parameters["name"] = tbmessage.Text;
dynamic res = fb.PostTaskAsync("me/photos", parameters);
In the parameters list, you have to provide the image source by either of the following:
url : a valid url to the image
source: iamge data
[Code]
[HttpPost]
public ActionResult PostPhotoOnWall(HttpPostedFileBase file)
{
var filename = Path.GetFileName(file.FileName);
StreamResourceInfo sri = null;
Uri jpegUri = new Uri(filename, UriKind.Relative);
sri = Application.GetResourceStream(jpegUri);
byte[] imageData = new byte[sri.Stream.Length];
sri.Stream.Read(imageData, 0, System.Convert.ToInt32(sri.Stream.Length));
var client = new FacebookClient();
// Post to user's wall
var postparameters = new Dictionary<string, object>();
var media = new FacebookMediaObject
{
FileName = filename,
ContentType = "image/jpeg"
};
media.SetValue(imageData);
postparameters["source"] = media;
postparameters["access_token"] = Session["access_token"].ToString();
var result = client.Post("/me/photos", postparameters);
return View("PostPhoto");
}
Related
I was using OpenID and we have to switch to Xamarin.Essentials.WebAuthenticator.
I can get an authorization code from Okta using WebAuthenticator.AuthenticateAsync().
But, everything I try to then translate that code into an access token returns 400 Bad Request.
Okta's API error is "E0000021: HTTP media type not supported exception" and it goes on to say, "Bad request. Accept and/or Content-Type headers likely do not match supported values."
I have tried to follow https://developer.okta.com/blog/2020/07/31/xamarin-essentials-webauthenticator as much as possible, but we are not using the hybrid grant type like he is.
We are using only Authorization Code, which means I have to make a secondary call, and I have spent two days trying to figure out how.
private async Task LoginOktaAsync()
{
try
{
var loginUrl = new Uri(BuildAuthenticationUrl()); // that method is down below
var callbackUrl = new Uri("com.oktapreview.dev-999999:/callback"); // it's not really 999999
var authenticationResult = await Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(loginUrl, callbackUrl);
string authCode;
authenticationResult.Properties.TryGetValue("code",out authCode);
// Everything works fine up to this point. I get the authorization code.
var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/token"
+"?grant_type=authorization_code"
+$"&code={authCode}&client_id={OktaConfiguration.ClientId}&code_verifier={codeVerifier}";
var request = new HttpRequestMessage(HttpMethod.Post, url);
var client = new HttpClient();
var response = await client.SendAsync(request); // this generates the 400 error.
}
catch(Exception e)
{
Debug.WriteLine($"Error: {e.Message}");
}
}
Here are the methods that produce the login url and a couple of other things:
public string BuildAuthenticationUrl()
{
var state = CreateCryptoGuid();
var nonce = CreateCryptoGuid();
CreateCodeChallenge();
var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/authorize?response_type=code"
+ "&response_mode=fragment"
+ "&scope=openid%20profile%20email"
+ "&redirect_uri=com.oktapreview.dev-999999:/callback"
+$"&client_id={OktaConfiguration.ClientId}"
+$"&state={state}"
+$"&code_challenge={codeChallenge}"
+ "&code_challenge_method=S256"
+$"&nonce={nonce}";
return url;
}
private string CreateCryptoGuid()
{
using (var generator = RandomNumberGenerator.Create())
{
var bytes = new byte[16];
generator.GetBytes(bytes);
return new Guid(bytes).ToString("N");
}
}
private string CreateCodeChallenge()
{
codeChallenge = GenerateCodeToVerify();
codeVerifier = codeChallenge;
using (var sha256 = SHA256.Create())
{
var codeChallengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeChallenge));
return Convert.ToBase64String(codeChallengeBytes);
}
}
private string GenerateCodeToVerify()
{
var str = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
Random rnd = new Random();
for (var i = 0; i < 100; i++)
{
str += possible.Substring(rnd.Next(0,possible.Length-1),1);
}
return str;
}
'''
After much online research, I discovered the issue was with how I was doing my post to get the token. This is how I made it work:
public static Dictionary<string, string> JsonDecode(string encodedString)
{
var inputs = new Dictionary<string, string>();
var json = JValue.Parse(encodedString) as JObject;
foreach (KeyValuePair<string, JToken> kv in json)
{
if (kv.Value is JValue v)
{
if (v.Type != JTokenType.String)
inputs[kv.Key] = v.ToString();
else
inputs[kv.Key] = (string)v;
}
}
return inputs;
}
private async Task<string> ExchangeAuthCodeForToken(string authCode)
{
string accessToken = string.Empty;
List<KeyValuePair<string, string>> kvdata = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", authCode),
new KeyValuePair<string, string>("redirect_uri", OktaConfiguration.Callback),
new KeyValuePair<string, string>("client_id", OktaConfiguration.ClientId),
new KeyValuePair<string, string>("code_verifier", codeVerifier)
};
var content = new FormUrlEncodedContent(kvdata);
var request = new HttpRequestMessage(HttpMethod.Post, OktaConfiguration.TokenUrl)
{Content = content, Method = HttpMethod.Post};
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendAsync(request);
string text = await response.Content.ReadAsStringAsync();
Dictionary<string, string> data = JsonDecode(text);
data.TryGetValue("access_token", out accessToken);
return accessToken;
}
I am following below link to integrate tableau report on web application(asp .net mvc),
https://onlinehelp.tableau.com/current/server/en-us/trusted_auth.htm
https://onlinehelp.tableau.com/current/server/en-us/trusted_auth_webrequ.htm
Code :
var uri = "http://<server ip>:8000/trusted";
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("username ", "<user>");
parameters.Add("target_site", "<site>");
var bodyParameters = new ArrayList();
foreach (var parameter in parameters)
{
bodyParameters.Add(string.Format("{0}={1}", HttpUtility.UrlEncode(parameter.Key), HttpUtility.UrlEncode(Convert.ToString(parameter.Value))));
}
string requestBody = String.Join("&", bodyParameters.ToArray());
var request = WebRequest.CreateHttp(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
try
{
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(requestBody);
}
var response = (HttpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
String body = reader.ReadToEnd();
}
}
catch (Exception ex)
{
string str = ex.Message.ToString();
}
My machine is registered as trusted host on tableau server, still i am getting -1 when i request for token.
I need to be able to access the id of a new Post. I will be using this id to populate another field called LocationId like this: "L" + id = LocationId (example L22) where 22 is the id of the new Post. Here is the code for my Post request:
private async void BtnSubmit_Clicked(object sender, EventArgs e)
{
var imageArray = FilesHelper.ReadFully(file.GetStream());
file.Dispose();
var location = new Models.Location()
{
LocationName = EntName.Text,
ImageArray = imageArray,
};
ApiServices apiServices = new ApiServices();
bool response = await apiServices.PostLocation(location);
bool response2 = await apiServices.InputLocationId(id, location);
if (!response || !response2)
{
await DisplayAlert("Alert", "Something wrong", "Cancel");
}
else
{
await DisplayAlert("Hi", "Your record has beed added successfully", "Alright");
}
await Navigation.PushAsync(new SetupPage());
This is on the client side. I have all the APIs created (such as PostLocation and InputLocationId)on Azure SQL Server. This is for a mobile inventory app built using Xamarin.
public async Task<bool> PostLocation(Location location)
{
var json = JsonConvert.SerializeObject(location);
var httpClient = new HttpClient();
var content = new StringContent(json, Encoding.UTF8, "application/json");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Settings.AccessToken);
var wimsApiUrl = "http://xxxxxxx.azurewebsites.net/api/Locations";
//Get the Body of the Post
var body = await httpClient.PostAsync(wimsApiUrl, content);
//Convert it to a string
var jString = await body.Content.ReadAsStringAsync();
//Place it in a JSON Object
JObject joResponse = JObject.Parse(jString);
//Parse the JSON Object into an Int from a String
var id = int.Parse(joResponse["Id"].ToString());
//This is used in my other script to Put the LocationId of Lxx
AddNewLocationPage.NewLocationId = id;
return body.IsSuccessStatusCode;
}
My Post Location API:
// POST: api/Locations
[ResponseType(typeof(Location))]
public IHttpActionResult PostLocation([FromBody] Location location)
{
string userId = User.Identity.GetUserId();
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var stream = new MemoryStream(location.ImageArray);
var guid = Guid.NewGuid().ToString();
var file = String.Format("{0}.jpg", guid);
var folder = "~/Content/Images";
var fullPath = String.Format("{0}/{1}", folder, file);
var response = FilesHelper.UploadPhoto(stream, folder, file);
if (response)
{
location.ImagePath = fullPath;
}
var newLocation = new Location()
{
LocationName = location.LocationName,
User = userId,
ImagePath = location.ImagePath
};
db.Locations.Add(newLocation);
db.SaveChanges();
return Ok(new { newLocation.Id});
}
I will then take the id and put it in this Put Request to create the LocationId:
public async Task<bool> InputLocationId(int id, Location location)
{
var json = JsonConvert.SerializeObject(location);
var httpClient = new HttpClient();
var content = new StringContent(json, Encoding.UTF8, "application/json");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Settings.AccessToken);
var wimsApiUrl = "http://xxxxxxx.azurewebsites.net/api/Locations/InputLocationId/";
var completeUrl = String.Format("{0}{1}", wimsApiUrl, id);
var response = await httpClient.PutAsync(completeUrl, content);
return response.IsSuccessStatusCode;
}
The InputLocationId API will automatically create the LocationId. Here is my API:
// PUT: api/Locations/5
[HttpPut]
[ResponseType(typeof(void))]
[Route("api/Locations/InputLocationId/{id}")]
public IHttpActionResult InputLocationId(int id, [FromBody] Location location)
{
//string userId = User.Identity.GetUserId();
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = db.Locations.FirstOrDefault(locationId => locationId.Id == id);
var resultant = String.Format("L{0}", id);
location.LocationName = location.LocationName;
result.LocationId = resultant;
db.SaveChanges();
return Ok("The record has been updated");
}
I am simply stuck on how to access that id!
// get the response body
var body = await httpClient.PostAsync(wimsApiUrl, content);
// load it into a JSON object using Newtonsoft
JObject data = JObject.Parse(body);
// get the id
var id = int.Parse(data["id"]);
The returns need to be converted into a string from the HttpResponseMessage.
var body = await httpClient.PostAsync(wimsApiUrl, content);
var jString = await body.Content.ReadAsStringAsync();
Then we can place it into a JSON Object:
JObject joResponse = JObject.Parse(jString);
Now this JSON Object can be parsed into an Int. Note it needs to be converted to a string.
var id = int.Parse(joResponse["Id"].ToString());
I'm trying to post a file in a json object to an external rest api over https. I have confirmed the json object is formatted correctly, do I have to do anything special to post to a rest api over https? I'm using the answer found over here as a guide: How to post JSON to the server?
private static void PostDatatoFTP(string FileName,
string fileString, string centerCode, string fileType) {
try {
byte[] plainTextBytes = Encoding.ASCII.GetBytes(fileString);
string base64File = Convert.ToBase64String(plainTextBytes);
FileInfo fileInfo = new FileInfo {
FileData = base64File,
FileName = FileName,
FileType = fileType,
FileVersion = _fileVersion
};
FileInfo[] transmitFileInfo = new FileInfo[1];
transmitFileInfo[0] = fileInfo;
Json jsonObject = new Json {
RequestType = _RequestType,
APIVersion = _apiVersion,
SubmissionId = Guid.NewGuid().ToString(),
UserId = _ftpUsername,
Password = _ftpPassword,
Vendor = _vendor,
CenterCode = centerCode,
FileInfo = transmitFileInfo
};
var json = JsonConvert.SerializeObject(jsonObject);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_uploadPath);
request.Method = "POST";
request.ContentType = "application/json";
using (var streamWriter = new StreamWriter(request.GetRequestStream())) {
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream() ?? throw new InvalidOperationException())) {
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
}
}
catch (WebException e) {
Console.WriteLine(e.Message);
String status = ((HttpWebResponse)e.Response).StatusDescription;
Console.WriteLine(status);
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
I config service for GitHub
services.AddOAuth("GitHub", "Github", o =>
{
o.ClientId = Configuration["Authentication:GitHub:ClientId"];
o.ClientSecret = Configuration["Authentication:GitHub:ClientSecret"];
o.CallbackPath = new PathString("/signin-github");
o.AuthorizationEndpoint = "https://github.com/login/oauth/authorize";
o.TokenEndpoint = "https://github.com/login/oauth/access_token";
o.UserInformationEndpoint = "https://api.github.com/user";
o.ClaimsIssuer = "OAuth2-Github";
o.SaveTokens = true;
// Retrieving user information is unique to each provider.
o.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
o.ClaimActions.MapJsonKey(ClaimTypes.Name, "login");
o.ClaimActions.MapJsonKey("urn:github:name", "name");
o.ClaimActions.MapJsonKey(ClaimTypes.Email, "email", ClaimValueTypes.Email);
o.ClaimActions.MapJsonKey("urn:github:url", "url");
o.Events = new OAuthEvents
{
OnCreatingTicket = async context =>
{
// Get the GitHub user
var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted);
response.EnsureSuccessStatusCode();
var user = JObject.Parse(await response.Content.ReadAsStringAsync());
context.RunClaimActions(user);
}
};
});
When I login on GitHub I redirect to action and in action has line ...
var info = await _signInManager.GetExternalLoginInfoAsync();//return null
That line always return null.
Can you help me?