I can't upload image to my azure storage by REST API.
This is my code:
using (var client = new HttpClient())
{
using (var fileStream = await _eventPhoto.OpenStreamForReadAsync())
{
var content = new StreamContent(fileStream);
content.Headers.Add("Content-Type", _eventPhoto.ContentType);
content.Headers.Add("x-ms-blob-type", "BlockBlob");
var uploadResponse = await client.PutAsync(new Uri("https://myservice.blob.core.windows.net/photos/newblob"),content);
int x = 2;
}
}
I get error about missing paramerer. Probably Authorization.
1) How to add missing headers?
2) Someone have working sample?
3) How to add Authorization?
Do you have a reason not to be using the client library that does this for you already? If you have a reason and you really want to use HttpClient, then you need to either a.) implement signing per spec, or b.) use a Shared Access Signature in your URI.
using System;
using System.Globalization;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
namespace AzureSharedKey
{
class Program
{
private const string blobStorageAccount = "your_account";
private const string blobStorageAccessKey = "your_access_key";
private const string blobPath = "blob_path";
private const string blobContainer = "your_container";
static void Main(string[] args)
{
Console.WriteLine("Program Initiated..");
CreateContainer();
Console.ReadLine();
}
private async static void CreateContainer()
{
string requestMethod = "GET";
string msVersion = "2016-05-31";
string date = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
string clientRequestId = Guid.NewGuid().ToString();
string canHeaders = string.Format("x-ms-client-request-id:{0}\nx-ms-date:{1}\nx-ms-version:{2}", clientRequestId, date, msVersion);
string canResource = string.Format("/{0}/{1}/{2}", blobStorageAccount, blobContainer, blobPath);
string SignStr = string.Format("{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canHeaders, canResource);
string auth = CreateAuthString(SignStr);
string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}/{2}", blobStorageAccount, blobContainer, blobPath);
Uri uri = new Uri(urlPath);
Console.WriteLine("urlPath "+ urlPath);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("x-ms-date", date);
client.DefaultRequestHeaders.Add("x-ms-version", "2016-05-31");
client.DefaultRequestHeaders.Add("x-ms-client-request-id", clientRequestId);
client.DefaultRequestHeaders.Add("Authorization", auth);
HttpResponseMessage response = client.GetAsync(uri).Result;
if (response.IsSuccessStatusCode)
{
string actualFilename= Path.GetFileName(blobPath);
string physicaPath = "D:/Others/AZ/";//change path to where you want to write the file
HttpContent content = response.Content;
string pathName = Path.GetFullPath(physicaPath + actualFilename);
FileStream fileStream = null;
try
{
fileStream = new FileStream(pathName, FileMode.Create, FileAccess.Write, FileShare.None);
await content.CopyToAsync(fileStream).ContinueWith(
(copyTask) =>
{
fileStream.Close();
});
Console.WriteLine("FileName: "+actualFilename);
Console.WriteLine("File Saved Successfully..");
}
catch
{
if (fileStream != null) fileStream.Close();
throw;
}
}
else
{
throw new FileNotFoundException();
}
}
private static string CreateAuthString(string SignStr)
{
string signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(blobStorageAccessKey);
using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
{
byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(SignStr);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
string authorizationHeader = string.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
blobStorageAccount,
signature);
return authorizationHeader;
}
}
}
this code worked for me
Have a look at this example.
http://www.codeninjango.com/programming/azure/azure-blob-storage-rest-api/
It gives a step by step guide to using the Azure Blob Storage REST API to upload chunked files with SAS url's.
Related
I have an API using POST Method.From this API I can download the file via Postmen tool.But I would like to know how to download file from C# Code.I have tried below code but POST Method is not allowed to download the file.
Code:-
using (var client = new WebClient())
{
client.Headers.Add("X-Cleartax-Auth-Token", ConfigurationManager.AppSettings["auth-token"]);
client.Headers[HttpRequestHeader.ContentType] = "application/json";
string url = ConfigurationManager.AppSettings["host"] + ConfigurationManager.AppSettings["taxable_entities"] + "/ewaybill/download?print_type=detailed";
TransId Id = new TransId()
{
id = TblHeader.Rows[0]["id"].ToString()
};
List<string> ids = new List<string>();
ids.Add(TblHeader.Rows[0]["id"].ToString());
string DATA = JsonConvert.SerializeObject(ids, Newtonsoft.Json.Formatting.Indented);
string res = client.UploadString(url, "POST",DATA);
client.DownloadFile(url, ConfigurationManager.AppSettings["InvoicePath"].ToString() + CboGatePassNo.EditValue.ToString().Replace("/", "-") + ".pdf");
}
Postmen Tool:-
URL : https://ewbbackend-preprodpub-http.internal.cleartax.co/gst/v0.1/taxable_entities/1c74ddd2-6383-4f4b-a7a5-007ddd08f9ea/ewaybill/download?print_type=detailed
Header :-
Content-Type : application/json
X-Cleartax-Auth-Token :b1f57327-96db-4829-97cf-2f3a59a3a548
Body :-
[
"GLD24449"
]
using (WebClient client = new WebClient())
{
client.Headers.Add("X-Cleartax-Auth-Token", ConfigurationManager.AppSettings["auth-token"]);
client.Headers[HttpRequestHeader.ContentType] = "application/json";
string url = ConfigurationManager.AppSettings["host"] + ConfigurationManager.AppSettings["taxable_entities"] + "/ewaybill/download?print_type=detailed";
client.Encoding = Encoding.UTF8;
//var data = "[\"GLD24449\"]";
var data = UTF8Encoding.UTF8.GetBytes(TblHeader.Rows[0]["id"].ToString());
byte[] r = client.UploadData(url, data);
using (var stream = System.IO.File.Create("FilePath"))
{
stream.Write(r,0,r.length);
}
}
Try this. Remember to change the filepath. Since the data you posted is not valid
json. So, I decide to post data this way.
I think it's straight forward, but instead of using WebClient, you can use HttpClient, it's better.
here is the answer HTTP client for downloading -> Download file with WebClient or HttpClient?
comparison between the HTTP client and web client-> Deciding between HttpClient and WebClient
Example Using WebClient
public static void Main(string[] args)
{
string path = #"download.pdf";
// Delete the file if it exists.
if (File.Exists(path))
{
File.Delete(path);
}
var uri = new Uri("https://ewbbackend-preprodpub-http.internal.cleartax.co/gst/v0.1/taxable_entities/1c74ddd2-6383-4f4b-a7a5-007ddd08f9ea/ewaybill/download?print_type=detailed");
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.Headers.Add("X-Cleartax-Auth-Token", "b1f57327-96db-4829-97cf-2f3a59a3a548");
client.Encoding = Encoding.UTF8;
var data = UTF8Encoding.UTF8.GetBytes("[\"GLD24449\"]");
byte[] r = client.UploadData(uri, data);
using (var stream = System.IO.File.Create(path))
{
stream.Write(r, 0, r.Length);
}
}
Here is the sample code, don't forget to change the path.
public class Program
{
public static async Task Main(string[] args)
{
string path = #"download.pdf";
// Delete the file if it exists.
if (File.Exists(path))
{
File.Delete(path);
}
var uri = new Uri("https://ewbbackend-preprodpub-http.internal.cleartax.co/gst/v0.1/taxable_entities/1c74ddd2-6383-4f4b-a7a5-007ddd08f9ea/ewaybill/download?print_type=detailed");
HttpClient client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, uri)
{
Content = new StringContent("[\"GLD24449\"]", Encoding.UTF8, "application/json")
};
request.Headers.Add("X-Cleartax-Auth-Token", "b1f57327-96db-4829-97cf-2f3a59a3a548");
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
using (FileStream fs = File.Create(path))
{
await response.Content.CopyToAsync(fs);
}
}
else
{
}
}
So, for my homework, I need to make an application that will not use SQL(as I used to), but the rest api. Problem is that I never done this, and I don't know how to configure it.
So far I got this:
string strUrlTest = String.Format("https://test.api.amadeus.com/v1/shopping/flight-offers");
WebRequest requestObjGet = WebRequest.Create(strUrlTest);
requestObjGet.Method = "GET";
requestObjGet.Headers.Add("API KEY",
"API SECRET);
HttpWebResponse responseObjGet = null;
responseObjGet = (HttpWebResponse)requestObjGet.GetResponse();
string strResultTest = null;
using(Stream stream = responseObjGet.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strResultTest = sr.ReadToEnd();
sr.Close();
}
I just wanted to see with debugger if I got my all my data, but my program crashes at
responseObjGet = (HttpWebResponse)requestObjGet.GetResponse();
Could you help me figure it out?
I wrote a code example in C#, replace apikey and apisecret by the ones you get on the portal by creating an application. You can find a guide here.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace testApp
{
public class AmadeusTest
{
static void Main()
{
const string URL = "https://test.api.amadeus.com/v1/shopping/flight-destinations?origin=BOS";
string token = getToken();
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(URL);
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + token);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "");
Task<HttpResponseMessage> response = client.SendAsync(request);
string myJsonResponse = Newtonsoft.Json.JsonConvert.DeserializeObject(response.Result.Content.ReadAsStringAsync().Result).ToString();
JObject jsonObject = JObject.Parse(myJsonResponse);
Console.WriteLine(myJsonResponse);
Console.WriteLine(jsonObject["data"][0]["destination"]);
client.Dispose();
}
private static string getToken()
{
const string apikey = "";
const string apisecret = "";
const string tokenURL = "https://test.api.amadeus.com/v1/security/oauth2/token";
string postData = $"grant_type=client_credentials&client_id={apikey}&client_secret={apisecret}";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(tokenURL);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "");
request.Content = new StringContent(postData,
Encoding.UTF8,
"application/x-www-form-urlencoded");
Task<HttpResponseMessage> response = client.SendAsync(request);
if (response.Result.IsSuccessStatusCode)
{
string myJsonResponse = Newtonsoft.Json.JsonConvert.DeserializeObject(response.Result.Content.ReadAsStringAsync().Result).ToString();
JObject jsonObject = JObject.Parse(myJsonResponse);
client.Dispose();
string token = (string)jsonObject["access_token"];
return token;
}
else
{
Console.WriteLine("{0} ({1})", (int)response.Result.StatusCode, response.Result.ReasonPhrase);
return response.Result.ReasonPhrase;
}
}
}
}
The getToken method is in charge of doing the authorization process (as explained here).
This token is used in the API call (in the Main method). It is added to the Authorization header with the value: Bearer {token}
Firstly, you need to get access token, to retrieve the data. How i accomplish this, you can see in code below.
[HttpGet("[action]")]
public async Task<List<FlightOffersModel>> GetData(string origin, string destination, string departureDate, string returnDate, string adults, string currency)
{
const string client_id = "oqsIlG0xAbnlXXXXXXXXXXg7GdYwemI5";
const string client_secret = "lAcXXXXXXXXX5AD0";
string token = await GetToken(client_id, client_secret);
const string baseUrl = "https://test.api.amadeus.com/v1/";
string urlParams = "shopping/flight-offers?origin=" + origin + "&destination=" + destination + "&departureDate=" + departureDate;
urlParams += returnDate == "" || returnDate == null ? "" : "&returnDate=" + returnDate;
urlParams += "&adults=" + adults + "&nonStop=false¤cy=" + currency + "&max=50";
FlightOffer ff = null;
List<FlightOffersModel> model = new List<FlightOffersModel>();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.amadeus+json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage response = await client.GetAsync(urlParams);
if (response.IsSuccessStatusCode)
{
var x = await response.Content.ReadAsStringAsync();
var xx = JObject.Parse(x);
ff = JsonConvert.DeserializeObject<FlightOffer>(xx.ToString());
foreach (var fo in ff.Data)
{
FlightOffersModel temp = new FlightOffersModel();
foreach (var item in fo.OfferItems)
{
foreach (var service in item.Services)
{
if (item.Services.IndexOf(service) < 1)
{
temp.BrojPresjedanjaPovratak = item.Services.Length > 1 ? GetBrojPresjedanja(item.Services[1]) : 0;
temp.BrojPresjedanjaOdlazak = GetBrojPresjedanja(item.Services[0]);
temp.BrojPutnika = GetBrojPutnika(service.Segments);
temp.UkupnaCijena = item.Price.Total;
temp.Valuta = ff.Meta.Currency;
temp.PolazniAerodrom = GetAerodromName(service.Segments, "departure", ff.Dictionaries.Locations);
temp.OdredisniAerodrom = GetAerodromName(service.Segments, "arrival", ff.Dictionaries.Locations);
temp.DatumPolaska = GetDatumLeta(service.Segments, "departure");
temp.DatumPovratka = GetDatumLeta(service.Segments, "arrival");
model.Add(temp);
}
}
}
}
}
}
return model;
}
This part of code is to get access token
const string client_id = "oqsIlG0xAbnlXXXXXXXXXXg7GdYwemI5";
const string client_secret = "lAcXXXXXXXXX5AD0";
string token = await GetToken(client_id, client_secret);
and this is GetToken function:
private async Task<string> GetToken(string client_id, string client_secret)
{
AccessToken s = null;
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://test.api.amadeus.com/v1/security/oauth2/token"))
{
request.Content = new StringContent("grant_type=client_credentials&client_id=" + client_id + "&client_secret=" + client_secret, Encoding.UTF8, "application/x-www-form-urlencoded");
HttpResponseMessage response = await httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
s = await response.Content.ReadAsAsync<AccessToken>();
}
}
}
return s.Access_token;
}
The rest of the code supplies data according to the parameters that user entered.
Im trying to download object from S3 bucket facing below issue
The Security token included in the request is Invalid .
Please check and correct where is the mistake.
Below is my code
1. Get Temporary credentails:
main()
{
string path = "http://XXX.XXX.XXX./latest/meta-data/iam/security-credentials/EC2_WLMA_Permissions";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(path);
request.Method = "GET";
request.ContentType = "application/json";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
dynamic metaData = JsonConvert.DeserializeObject(result);
_awsAccessKeyId = metaData.AccessKeyId;
_awsSecretAccessKey = metaData.SecretAccessKey;
}
}
Create SessionAWSCredentials instance:
SessionAWSCredentials tempCredentials =
GetTemporaryCredentials(_awsAccessKeyId, _awsSecretAccessKey);
//GetTemporaryCredentials method:
private static SessionAWSCredentials GetTemporaryCredentials(
string accessKeyId, string secretAccessKeyId)
{
AmazonSecurityTokenServiceClient stsClient =
new AmazonSecurityTokenServiceClient(accessKeyId,
secretAccessKeyId);
Console.WriteLine(stsClient.ToString());
GetSessionTokenRequest getSessionTokenRequest =
new GetSessionTokenRequest();
getSessionTokenRequest.DurationSeconds = 7200; // seconds
GetSessionTokenResponse sessionTokenResponse =
stsClient.GetSessionToken(getSessionTokenRequest);
Console.WriteLine(sessionTokenResponse.ToString());
Credentials credentials = sessionTokenResponse.Credentials;
Console.WriteLine(credentials.ToString());
SessionAWSCredentials sessionCredentials =
new SessionAWSCredentials(credentials.AccessKeyId,
credentials.SecretAccessKey,
credentials.SessionToken);
return sessionCredentials;
}
Get files from S3 using AmazonS3Client:
using (IAmazonS3 client = new AmazonS3Client(tempCredentials,RegionEndpoint.USEast1))
{
GetObjectRequest request = new GetObjectRequest();
request.BucketName = "bucketName" + #"/" + "foldername";
request.Key = "Terms.docx";
GetObjectResponse response = client.GetObject(request);
response.WriteResponseStreamToFile("C:\\MyFile.docx");
}
We do something a little simpler for interfacing with S3 (downloads and uploads)
It looks like you went the more complex approach. You should try just using the TransferUtility instead:
TransferUtility fileTransferUtility =
new TransferUtility(
new AmazonS3Client("ACCESS-KEY-ID", "SECRET-ACCESS-KEY", Amazon.RegionEndpoint.CACentral1));
// Note the 'fileName' is the 'key' of the object in S3 (which is usually just the file name)
fileTransferUtility.Download(filePath, "my-bucket-name", fileName);
NOTE: TransferUtility.Download() returns void because it downloads the file to the path specified in the filePath argument. This may be a little different than what you were expecting but you can still open a FileStream to that path afterwards and manipulate the file all you want. For example:
using (FileStream fileDownloaded = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
// Do stuff with our newly downloaded file
}
Bucketname, Accesskey and secretkey, I took from web config. You could type manually.
public void DownloadObject(string imagename)
{
RegionEndpoint bucketRegion = RegionEndpoint.USEast1;
IAmazonS3 client = new AmazonS3Client(bucketRegion);
string accessKey = System.Configuration.ConfigurationManager.AppSettings["AWSAccessKey"];
string secretKey = System.Configuration.ConfigurationManager.AppSettings["AWSSecretKey"];
AmazonS3Client s3Client = new AmazonS3Client(new BasicAWSCredentials(accessKey, secretKey), Amazon.RegionEndpoint.USEast1);
string objectKey = "EMR" + "/" + imagename;
//EMR is folder name of the image inside the bucket
GetObjectRequest request = new GetObjectRequest();
request.BucketName = System.Configuration.ConfigurationManager.AppSettings["bucketname"];
request.Key = objectKey;
GetObjectResponse response = s3Client.GetObject(request);
response.WriteResponseStreamToFile("D:\\Test\\"+ imagename);
}
//> D:\Test\ is local file path.
Following is how I download it. I need to download only .zip files in this case. Restricting to only required file types (.zip in my case), helped me to avoid errors related to (416) Requested Range Not Satisfiable
public static class MyAWS_S3_Helper
{
static string _S3Key = System.Configuration.ConfigurationManager.ConnectionStrings["S3BucketKey"].ConnectionString;
static string _S3SecretKey = System.Configuration.ConfigurationManager.ConnectionStrings["S3BucketSecretKey"].ConnectionString;
public static void S3Download(string bucketName, string _ObjectKey, string downloadPath)
{
IAmazonS3 _client = new AmazonS3Client(_S3Key, _S3SecretKey, Amazon.RegionEndpoint.USEast1);
TransferUtility fileTransferUtility = new TransferUtility(_client);
fileTransferUtility.Download(downloadPath + "\\" + _ObjectKey, bucketName, _ObjectKey);
_client.Dispose();
}
public static async Task AsyncDownload(string bucketName, string downloadPath, string requiredSunFolder)
{
var bucketRegion = RegionEndpoint.USEast1; //Change it
var credentials = new BasicAWSCredentials(_S3Key, _S3SecretKey);
var client = new AmazonS3Client(credentials, bucketRegion);
var request = new ListObjectsV2Request
{
BucketName = bucketName,
MaxKeys = 1000
};
var response = await client.ListObjectsV2Async(request);
var utility = new TransferUtility(client);
foreach (var obj in response.S3Objects)
{
string currentKey = obj.Key;
double sizeCheck = Convert.ToDouble(obj.Size);
int fileNameLength = currentKey.Length;
Console.WriteLine(currentKey + "---" + fileNameLength.ToString());
if (currentKey.Contains(requiredSunFolder))
{
if (currentKey.Contains(".zip")) //This helps to avoid errors related to (416) Requested Range Not Satisfiable
{
try
{
S3Download(bucketName, currentKey, downloadPath);
}
catch (Exception exTest)
{
string messageTest = currentKey + "-" + exTest;
}
}
}
}
}
}
Here is how it is called
static void Main(string[] args)
{
string downloadPath = #"C:\SourceFiles\TestDownload";
Task awsTask = MyAWS_S3_Helper.AsyncDownload("my-files", downloadPath, "mysubfolder");
awsTask.Wait();
}
Here is what I have done to download the files from S3 bucket,
var AwsImportFilePathParcel = "TEST/TEMP"
IAmazonS3 client = new AmazonS3Client(AwsAccessKey,AwsSecretKey);
S3DirectoryInfo info = new S3DirectoryInfo(client, S3BucketName, AwsImportFilePathParcel);
S3FileInfo[] s3Files = info.GetFiles(pattenForParcel);
now in s3Files, you have all the files which are on provided location, using for each you can save all files in to your system
foreach (var fileInfo in s3Files)
{
var localPath = Path.Combine("C:\TEST\", fileInfo.Name);
var file = fileInfo.CopyToLocal(localPath);
}
I have been trying to construct authorisation header for Docebo but I am unable to get it working as the documentation is not descriptive enough and their code sample (only code sample) is very confusing.
This is basically all Docebo documentation:
What I am trying to do is to get a list of all users.
public JsonResult GetCoursesCount()
{
const string apiKey = "[API KEY FROM MY DOCEBO PORTAL]";
const string apiSecret = "[API SECRET FROM MY DOCEBO PORTAL]";
const string doceboUrl = "[URL OF MY DOCEBO PORTAL]";
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var toEncodeWithSha1 = String.Format("{0},{1}", String.Join(",", new[] {"0", "null"}), apiSecret); // should the values be values or parameters??
var code = GetSHA1HashData(toEncodeWithSha1);
var toEncodeWithBase64 = String.Format("{0}:{1}", apiKey, code);
code = Base64Encode(toEncodeWithBase64);
var xAuthorisation = String.Format("Docebo {0}", code);
httpClient.DefaultRequestHeaders.Add("X-Authorization", xAuthorisation);
var stringContent = JsonConvert.SerializeObject("{ \"from\": \"0\", \"count\": \"null\" }");
var userResult = httpClient.PostAsync(String.Format("{0}/api/user/listUsers", doceboUrl),
new StringContent(stringContent)).Result;
var userData = JsonConvert.DeserializeObject<dynamic>(userResult.Content.ReadAsStringAsync().Result);
return new JsonResult { Data = userData, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
private string GetSHA1HashData(string data)
{
//create new instance of md5
var sha1 = SHA1.Create();
//convert the input text to array of bytes
byte[] hashData = sha1.ComputeHash(Encoding.Default.GetBytes(data));
//create new instance of StringBuilder to save hashed data
var returnValue = new StringBuilder();
//loop for each byte and add it to StringBuilder
foreach (byte #byte in hashData)
{
returnValue.Append(#byte.ToString());
}
// return hexadecimal string
return returnValue.ToString();
}
private string Base64Encode(string plainText)
{
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
Anytime I contact their API I get "{
"success": false,
"message": "Authorization header value doesn't match",
"code": 104
}".
It would be great to get a feedback on this or an understandable translation of their API documentation.
After long struggle (8 hours) I resolved the correct code.
public JsonResult GetCoursesCount()
{
const string apiKey = "[API KEY FROM MY DOCEBO PORTAL]";
const string apiSecret = "[API SECRET FROM MY DOCEBO PORTAL]";
const string doceboUrl = "[URL OF MY DOCEBO PORTAL]";
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var listKeyValuePair = new List<KeyValuePair<string,string>>
{
new KeyValuePair<string, string>("from", "0"),
new KeyValuePair<string, string>("count", "10")
};
var toEncodeWithSha1 = String.Format("{0},{1}", String.Join(",", listKeyValuePair.Select(n => n.Value)), apiSecret); // should the values be values or parameters??
var code = Sha1Hash(toEncodeWithSha1);
var toEncodeWithBase64 = String.Format("{0}:{1}", apiKey, code);
code = Base64Encode(toEncodeWithBase64);
var xAuthorisation = String.Format("Docebo {0}", code);
httpClient.DefaultRequestHeaders.Add("X-Authorization", xAuthorisation);
var content = new FormUrlEncodedContent(listKeyValuePair);
var userResult = httpClient.PostAsync(String.Format("{0}/api/user/listUsers", doceboUrl),
content).Result;
var responseByteArray = userResult.Content.ReadAsByteArrayAsync().Result;
var convertedResult = Encoding.UTF8.GetString(responseByteArray, 0, responseByteArray.Length);
var userData = JsonConvert.DeserializeObject<UserListResult>(convertedResult);
return new JsonResult { Data = userData, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
public class UserListResult
{
public List<dynamic> Users { get; set; }
public bool Success { get; set; }
}
private string Sha1Hash(string input)
{
return string.Join(string.Empty, SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(input)).Select(x => x.ToString("x2")));
}
private string Base64Encode(string plainText)
{
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
Including the PHP example for reference:
<?php
/**
* DOCEBO, e-learning SAAS
*
* #link http://www.docebo.com/
* #copyright Copyright © 2004-2013 Docebo
*/
class Api {
static public $url = 'yoursite.docebosaas.com';
static public $key = 'your_key_from_api_app';
static public $secret_key = 'your_secret_from_api_app';
static public $sso = 'your_toekn_from_api_app';
static public function getHash($params) {
$res =array('sha1'=>'', 'x_auth'=>'');
$res['sha1']=sha1(implode(',', $params) . ',' . self::$secret_key);
$res['x_auth']=base64_encode(self::$key . ':' . $res['sha1']);
return $res;
}
static private function getDefaultHeader($x_auth) {
return array(
"Host: " . self::$url,
"Content-Type: multipart/form-data",
'X-Authorization: Docebo '.$x_auth,
);
}
static public function call($action, $data_params) {
$curl = curl_init();
$hash_info = self::getHash($data_params);
$http_header =self::getDefaultHeader($hash_info['x_auth']);
$opt = array(
CURLOPT_URL=>self::$url . '/api/' . $action,
CURLOPT_RETURNTRANSFER=>1,
CURLOPT_HTTPHEADER=>$http_header,
CURLOPT_POST=>1,
CURLOPT_POSTFIELDS=>$data_params,
CURLOPT_CONNECTTIMEOUT=>5, // Timeout to 5 seconds
);
curl_setopt_array($curl, $opt);
// $output contains the output string
$output = curl_exec($curl);
// it closes the session
curl_close($curl);
return $output;}
static public function sso($user) {
$time = time();
$token = md5($user.','.$time.','.self::$sso);
return 'http://' . self::$url .
'/doceboLms/index.php?modname=login&op=confirm&login_user=' . strtolower($user) . '&time=' .
$time . '&token=' . $token;
}
}
// sample call
$res = API::call('user/checkUsername', array(
'userid' => 'username_to_chek'
));
I found following solution in order to invoke Docebo APIs using OAUTH2 authentication; it isn't documented on the Docebo site either. This C# example invokes the "user/count" API; it can be easily adapted to the other APIs. It uses Json.Net to parse the answers.
using Newtonsoft.Json; //see http://www.newtonsoft.com/json
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace DoceboClient
{
class CallDoceboAPI
{
static void Main(string[] args)
{
string url = "https://YOUR_DOCEBO_PORTAL_URL"; //https is mandatory!
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
//Obtain token
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + "/oauth2/token");
string postParametersForToken = "client_id=YOUR_DOCEBO_CLIENT_ID&client_secret=YOUR_DOCEBO_CLIENT_SECRET&grant_type=password&username=YOUR_DOCEBO_USERNAME&password=YOUR_DOCEBO_PASSWORD&scope=api";
request.ContentType = #"application/x-www-form-urlencoded";
Byte[] byteArray = encoding.GetBytes(postParametersForToken);
request.ContentLength = byteArray.Length;
request.Method = "POST";
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
string token = "";
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
string result = reader.ReadToEnd();
DoceboToken dt = JsonConvert.DeserializeObject<DoceboToken>(result);
token = dt.access_token;
}
}
//invoke API, e.g. "/user/count"
string api = "/api/user/count";
string postParametersForAPI = "status=all"; //if more than 1 parameter, concat them as &parmName=parmValue
request = (HttpWebRequest)WebRequest.Create(url + api);
byteArray = encoding.GetBytes(postParametersForAPI + "&access_token=" + token);
request.ContentLength = byteArray.Length;
request.ContentType = #"application/x-www-form-urlencoded";
request.Method = "POST";
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
string result = reader.ReadToEnd();
UserCountResponse ucr = JsonConvert.DeserializeObject<UserCountResponse>(result);
//get the result
int count = ucr.count;
}
}
}
}
class UserCountResponse
{
public bool success;
public int count;
}
class DoceboToken
{
public string access_token;
}
}
I just recieve my unique developer API key from Imgur and I'm aching to start cracking on this baby.
First a simple test to kick things off. How can I upload an image using C#? I found this using Python:
#!/usr/bin/python
import pycurl
c = pycurl.Curl()
values = [
("key", "YOUR_API_KEY"),
("image", (c.FORM_FILE, "file.png"))]
# OR: ("image", "http://example.com/example.jpg"))]
# OR: ("image", "BASE64_ENCODED_STRING"))]
c.setopt(c.URL, "http://imgur.com/api/upload.xml")
c.setopt(c.HTTPPOST, values)
c.perform()
c.close()
looks like the site uses HTTP Post to upload images. Take a look at the HTTPWebRequest class and using it to POST to a URL: Posting data with HTTPRequest.
The Imgur API now provide a complete c# example :
using System;
using System.IO;
using System.Net;
using System.Text;
namespace ImgurExample
{
class Program
{
static void Main(string[] args)
{
PostToImgur(#"C:\Users\ashwin\Desktop\image.jpg", IMGUR_ANONYMOUS_API_KEY);
}
public static void PostToImgur(string imagFilePath, string apiKey)
{
byte[] imageData;
FileStream fileStream = File.OpenRead(imagFilePath);
imageData = new byte[fileStream.Length];
fileStream.Read(imageData, 0, imageData.Length);
fileStream.Close();
string uploadRequestString = "image=" + Uri.EscapeDataString(System.Convert.ToBase64String(imageData)) + "&key=" + apiKey;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://api.imgur.com/2/upload");
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ServicePoint.Expect100Continue = false;
StreamWriter streamWriter = new StreamWriter(webRequest.GetRequestStream());
streamWriter.Write(uploadRequestString);
streamWriter.Close();
WebResponse response = webRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
string responseString = responseReader.ReadToEnd();
}
}
}
Why don't you use the NuGet for this: called Imgur.API and for upload
you would have a method like this:
/*
The refresh token and all the values represented by constans are given when you allow the application in your imgur panel on the response url
*/
public OAuth2Token CreateToken()
{
var token = new OAuth2Token(TOKEN_ACCESS, REFRESH_TOKEN, TOKEN_TYPE, ID_ACCOUNT, IMGUR_USER_ACCOUNT, int.Parse(EXPIRES_IN));
return token;
}
//Use it only if your token is expired
public Task<IOAuth2Token> RefreshToken()
{
var client = new ImgurClient(CLIENT_ID, CLIENT_SECRET);
var endpoint= new OAuth2Endpoint(client);
var token = endpoint.GetTokenByRefreshTokenAsync(REFRESH_TOKEN);
return token;
}
public async Task UploadImage()
{
try
{
var client = new ImgurClient(CLIENT_ID, CLIENT_SECRET, CreateToken());
var endpoint = new ImageEndpoint(client);
IImage image;
//Here you have to link your image location
using (var fs = new FileStream(#"IMAGE_LOCATION", FileMode.Open))
{
image = await endpoint.UploadImageStreamAsync(fs);
}
Debug.Write("Image uploaded. Image Url: " + image.Link);
}
catch (ImgurException imgurEx)
{
Debug.Write("Error uploading the image to Imgur");
Debug.Write(imgurEx.Message);
}
}
Also you can find all the reference here: Imgur.API NuGet