How to upload image to LinkedIn for Ugc image post in C# - c#

So I am following Linkedin Documentation for implementing Create Image Share on Linkedin.
The documentation lists three steps:
Register your image to be uploaded.
Upload your image to LinkedIn.
Create the image share.
While I am able to do the first step to get the uploadUrl, I am getting 400 response error with blank error message while doing step 2.
The documentation list the second step as:
curl -i --upload-file /Users/peter/Desktop/superneatimage.png --header "Authorization: Bearer redacted" 'https://api.linkedin.com/mediaUpload/C5522AQGTYER3k3ByHQ/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&m=AQJbrN86Zm265gAAAWemyz2pxPSgONtBiZdchrgG872QltnfYjnMdb2j3A&app=1953784&sync=0&v=beta&ut=2H-IhpbfXrRow1'
Here's my step 2 in C# code:
private bool UploadImageBinaryFile(RequestUploadUrlResponse uploadDetails)
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", #access_token#);
client.DefaultRequestHeaders.Add("X-Restli-Protocol-Version", "2.0.0");
MultipartFormDataContent form = new MultipartFormDataContent();
string fileAddress = image_path + "image.png";
byte[] fileBytes = File.ReadAllBytes(fileAddress);
string name = "upload-file";
form.Add(new ByteArrayContent(fileBytes), name);
HttpResponseMessage response = client.PutAsync
(
uploadDetails.value.uploadMechanism.mediaUploadHttpRequest.uploadUrl,
form
).Result;
if (response.IsSuccessStatusCode)//<--getting 400 error Bad Request here
{
string responseBody = response.Content.ReadAsStringAsync().Result;
return true;
}
else
{
ErrorResponseHandler(response.Content.ReadAsStringAsync().Result);
return false;
}
}
}
I have ensured that I was successfully able to the uploadUrl from the first step. And when I used the URL https://api.linkedin.com/v2/assets/#id# to check the status, I was able the see the status as WAITING_UPLOAD.
Where am I going wrong?

I found the solution, basically we have to pass the binary in the content only, whereas I was passing it in the form.
using (HttpClient client = new HttpClient())
{
try
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accesstoken);
var content = new ByteArrayContent(File.ReadAllBytes(fileAddress));
HttpResponseMessage response = client.PutAsync(url, content).Result;
if (response.IsSuccessStatusCode)
{
//response is empty. Have to call the checkAssetStatus to see if the asset is 'AVAILABLE'
string responseBody = response.Content.ReadAsStringAsync().Result;
}
else
{
//handleError();
}
}
catch (HttpRequestException ex)
{
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} ", ex.Message);
}
}

Related

How do I delete a video in my Vimeo account?

How do I delete a video in my Vimeo account using the Vimeo API using C# in .Net Core?
The following works if you have a Vimeo account (at least it works at the Plus level and above) and have created an app, given that app permission to delete, gotten an access token for that app, and have a video number for the video you want to delete.
Within a class put the following code:
HttpClient httpClient = new HttpClient();
public async Task deleteVideo(string videoNumber, string accessToken)
{
try
{
string vimeoApiUrl = "https://api.vimeo.com/videos/" + videoNumber; // Vimeo URL
var body = "{}";
HttpContent content = new StringContent(body);
using (var requestMessage = new HttpRequestMessage(HttpMethod.Delete, vimeoApiUrl))
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
requestMessage.Headers.Add("Accept", "application/vnd.vimeo.*+json;version=3.4");
requestMessage.Headers.Add("ContentType", "application/x-www-form-urlencoded");
requestMessage.Content = content;
var response = await httpClient.SendAsync(requestMessage).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
}
}
catch (Exception err)
{
var errMessage = err.Message;
Console.WriteLine("In deleteVideo() error: " + err.Message);
}
}
To call it from within that class:
await deleteVideo(videoNumber, accessToken).ConfigureAwait(false);

Sending image as base64string to WebAPI; base64 string is too long

I recently followed these tutorials by Ahsan Siddique
Developing RESTful API in ASP.Net With Azure Database.
Part 1
https://www.c-sharpcorner.com/article/creating-sql-database-in-azure-portal/
part 2
https://www.c-sharpcorner.com/article/developing-restful-api-in-asp-net-with-add-method/
Part 3
https://www.c-sharpcorner.com/article/developing-restful-apis-in-asp-net-with-retrieve-update-and-delete-functions/
Consuming RESTful API in Xamarin.Android
part 4
https://www.c-sharpcorner.com/article/consuming-restful-apis-in-xamarin-android/
I managed to get all the codes to work but I got stuck at the part where i'm trying to pass the base64 string to the web api. The tutorial didn't have the portion that I got stuck at. I tested my POST API on Postman and I get this error message, "HTTP Error 414. The request URL is too long."
Below you can see a portion of my codes:
public String BitmapToBase64(Bitmap bitmap)
{
//Java.IO.ByteArrayOutputStream byteArrayOutputStream = new Java.IO.ByteArrayOutputStream();
MemoryStream memStream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, memStream);
byte[] byteArray = memStream.ToArray();
return Base64.EncodeToString(byteArray, Base64Flags.Default);
}
User user = new User ();
user.ID = "1";
user.name = "Kelly";
user.profilepic = BitmapToBase64(NGetBitmap(uri)); //this is the part where base64string is too long
HttpClient client = new HttpClient();
string url = $"http://test.azurewebsites.net/api/User/{user.ID}?name={user.name}&profilepic={user.profilepic}";
var uri1 = new System.Uri(url); //base64
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response;
var json = JsonConvert.SerializeObject(feedback);
var content = new StringContent(json, Encoding.UTF8, "application/json");
response = await client.PostAsync(uri1, content);
if (response.StatusCode == System.Net.HttpStatusCode.Accepted)
{
Toast.MakeText(this, "Your profile is updated.", ToastLength.Long).Show();
}
else
{
Toast.MakeText(this, "Your profile is not updated." + feedback.profilepic, ToastLength.Long).Show();
}
I need help! Thank you in advance!
Update:
This is how my controller class currently look like
public HttpResponseMessage Update_User(int ID, string name, string profilepic)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
UserTable newUser = new UserTable();
var entry = db.Entry<UserTable>(newUser);
entry.Entity.ID = ID;
entry.Entity.name = name;
entry.Entity.profilepic = profilepic;
entry.State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.Accepted, "Your profile is updated.");
}
As mentioned in the comments, don't send the base64 image as part of the url/GET param.
Instead attach it to the body of the POST request.
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("profilepic", user.profilepic)
});
var result = await client.PostAsync(url, content);

Send Json as body and file webrequest

How to send both body and also a file?
From the API Guide: "Upload Requests are submitted with multiple parts: body (request) and file buffer (file)."
I know how to send only a Json as body, but I need now to seng Json as body and also a file.
My code looks something like:
const string WEBSERVICE_URL = "https://myurl.com";
var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
webRequest.Method = "POST";
webRequest.ContentType = "multipart/form-data;boundary=12345678912345678912345678";
webRequest.Headers.Add("Authorization:7786FFFGFDDDP");
And:
string json="{"\some json"\ :\"here\" }"
using (var streamWriter = new StreamWriter(webRequest.GetRequestStream()))
{
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)webRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result.ToString());
}
But how to send both file and body together? I mean I want also to upload some file wih path #c:\\myFile.txt
I need to do this in a Xamarin application. Post an image to a web api with token based authentication. I made some changes in code to be posible use in a web application.
public async void SendFile()
{
using (System.IO.FileStream stream = System.IO.File.Open(#"c:\file.txt", System.IO.FileMode.Open))
{
var content = new System.Net.Http.MultipartFormDataContent();
content.Add(new System.Net.Http.StreamContent(stream),
"\"file\"",
"Path to your file (ex: c:\temp\file.txt");
await PostItemAsyncWithToken("url to post", content, "accessToken");
}
}
public async System.Threading.Tasks.Task<bool> PostItemAsyncWithToken(string url, System.Net.Http.HttpContent content, string accessToken)
{
try
{
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
System.Net.Http.HttpResponseMessage response = await httpClient.PostAsync(url, content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
return true;
}
else
{
return false;
}
}
}
catch (System.Exception ex)
{
throw new System.Exception("Error message", ex);
}
}

Issue in calling web API by using HttpClient Vs. WebClient C#

I am trying to make a web API call by using HttpClient but getting Not authorized error. I am passing key in the header but still, it gives me this error. I can see my key in fiddler trace.
If I use WebClient then I am getting a successful response. request is same in both methods.
Using HttpClient:
#region HttpClient
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("apiKey", "MyKey");
var content = JsonConvert.SerializeObject(request);
var response = await client.PostAsJsonAsync("https://MyUrl", content);
if (response.IsSuccessStatusCode)
{
deliveryManagerQuoteResponse = await response.Content.ReadAsAsync<DeliveryManagerQuoteResponse>();
}
else
{
var reasonPhrase = response.ReasonPhrase;
if (reasonPhrase.ToUpper() == "NOT AUTHORIZED")
{
throw new KeyNotFoundException("Not authorized");
}
}
}
#endregion
Using WebClient:
#region WebClient
// Create string to hold JSON response
string jsonResponse = string.Empty;
using (var client = new WebClient())
{
try
{
client.UseDefaultCredentials = true;
client.Headers.Add("Content-Type:application/json");
client.Headers.Add("Accept:application/json");
client.Headers.Add("apiKey", "MyKey");
var uri = new Uri("https://MyUrl");
var content = JsonConvert.SerializeObject(request);
var response = client.UploadString(uri, "POST", content);
jsonResponse = response;
}
catch (WebException ex)
{
// Http Error
if (ex.Status == WebExceptionStatus.ProtocolError)
{
var webResponse = (HttpWebResponse)ex.Response;
var statusCode = (int)webResponse.StatusCode;
var msg = webResponse.StatusDescription;
throw new HttpException(statusCode, msg);
}
else
{
throw new HttpException(500, ex.Message);
}
}
}
#endregion
First things first, you are using HttpClient wrong.
Secondly, are you using fiddler to see what both requests look like? You should be able to see that the headers will look different. Right now you are using the Authorization Headers which will actually do something different than you want. All you need to do is simply add a regular 'ol header:
client.DefaultRequestHeaders.Add("apiKey", "MyKey");

how to pass the following JSON to a C# patch method w or w/o Javascript serializer

I am working on a program to access the REST API for Visual Studio Team Services (was Visual Studio Online). I am following https://www.visualstudio.com/integrate/api/wit/work-items
I was able to query the work item by passing the correct Id using this code snippet:
var uri = new Uri("https://{instance}.visualstudio.com/DefaultCollection/_apis/wit/workitems/7?api-version=1.0");
GetWorkItem(uri);
public static async void GetWorkItem(Uri uri)
{
try
{
var username = "my username";
var password = " my pass word";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
using (HttpResponseMessage response = client.GetAsync(uri)
.Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
Console.Read();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.Read();
}
}
It correctly returns a JSON as specified here https://www.visualstudio.com/integrate/api/wit/work-items#GetalistofworkitemsByIDs
Now I am trying to update the work item by modifying its title .
https://www.visualstudio.com/integrate/api/wit/work-items#UpdateworkitemsUpdateafield
For this I wrote a method :
public static async void UpdateWorkItemStatus(Uri requestUri, HttpContent iContent)
{
{
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, requestUri)
{
Content = iContent
};
HttpResponseMessage response;
try
{
using (HttpClient client = new HttpClient())
{
var username = "my username";
var password = "my password";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(response);
Console.Read();
}
}
catch (TaskCanceledException e)
{
Console.WriteLine("ERROR: " + e.ToString());
Console.Read();
}
}
}
I am calling this method by passing my json :
var uri = new Uri("https://{instance}.visualstudio.com/DefaultCollection/_apis/wit/workitems/7?api-version=1.0");
string json = new JavaScriptSerializer().Serialize(new
{
op="replace",
path="fields/System.Title",
value=" 123 New Title"
});
HttpContent httpContent = new StringContent(json, Encoding.UTF8, "application/json-patch+json");
UpdateWorkItemStatus(uri, httpContent);
This is in accordance with the information in https://www.visualstudio.com/integrate/api/wit/work-items#Updateworkitems
They don't have any code samples so I used JavascriptSerializer
But this doesn't do anything . The code runs but gives no output and my work item is also not edited. I am not sure if it is incorrect in format due to using JavascriptSerializer but I have used this class before and it has worked well.
Basically I need to pass this JSON :
[
{
"op": "replace",
"path": "fields/System.Title",
"value":"New Title"
}
]
Any help on how to get this running and pass the JSON in a right format would be appreciated even if without using the JS Serializer class.
Eventually the idea is to convert this to an interpreted script that can run on Unix, like curl, Python or Perl. Any pointers or recommendations on that would also be appreciated.
I usually pass the content strings directly and it works:
string json = "[{\"op\":\"replace\",\"path\":\"/fields/System.Title\",\"value\":\"Title\"}]";
The string json you generated by JavaScriptSerializer is missing "[" and "]".
By the way, with the code you provided, if you run GetWorkItem(uri) before UpdateWorkItemStatus(uri, httpContent), UpdateWorkItemStatus() won't run since the app exit after GetWorkItem().

Categories

Resources