Uploading a file to a web service using POST in C# - c#

The problem with this code is that the file, once it is uploaded, is not the correct format. I'm trying to upload a .zip file.
public string HttpPost(string uri, string parameter)
{
WebRequest webRequest = WebRequest.Create(uri);
NetworkCredential credentials = new NetworkCredential("username", "password");
webRequest.Credentials = credentials;
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(parameter);
Stream os = null;
try
{ // send the Post
webRequest.ContentLength = bytes.Length; //Count bytes to send
os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length); //Send it
}
catch (WebException ex)
{
MessageBox.Show(ex.Message, "HttpPost: Request error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (os != null)
{
os.Close();
}
}
try
{ // get the response
WebResponse webResponse = webRequest.GetResponse();
if (webResponse == null)
{ return null; }
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
return sr.ReadToEnd().Trim();
}
catch (WebException ex)
{
MessageBox.Show(ex.Message, "HttpPost: Response error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return null;
}

This example how to upload file in MyBucket
private const string KeyId = "Your KeyId";
private const string AccessKey = "Your AccessKey";
private const string S3Url = "https://s3.amazonaws.com/";
private static void UploadFile()
{
var fileData = File.ReadAllBytes(#"C:\123.zip");
string timeStamp = string.Format("{0:r}", DateTime.UtcNow);
string stringToConvert = "PUT\n" + //Http verb
"\n" + //content-md5
"application/octet-stream\n" + //content-type
"\n" + //date
"x-amz-acl:public-read"+"\n" + //date
"x-amz-date:" + timeStamp + "\n" + //optionall
"/MyBucket/123.zip"; //resource
var ae = new UTF8Encoding();
var signature = new HMACSHA1 {Key = ae.GetBytes(AccessKey)};
var bytes = ae.GetBytes(stringToConvert);
var moreBytes = signature.ComputeHash(bytes);
var encodedCanonical = Convert.ToBase64String(moreBytes);
var url = "https://MyBucket.s3.amazonaws.com/123.zip";
var request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "PUT";
request.Headers["x-amz-date"] = timeStamp;
request.Headers["x-amz-acl"] = "public-read";
request.ContentType = "application/octet-stream";
request.ContentLength = fileData.Length;
request.Headers["Authorization"] = "AWS " + KeyId + ":" + encodedCanonical;
var requestStream = request.GetRequestStream();
requestStream.Write(fileData, 0, fileData.Length);
requestStream.Close();
using (var response = request.GetResponse() as HttpWebResponse)
{
var reader = new StreamReader(response.GetResponseStream());
var data = reader.ReadToEnd();
}
}
Take a look on Amazon S3 REST API

Related

set MultipartFormDataContent for multipart/form-data file upload right with HttpClient

The following code works:
string UploadWithHttpRequest(string url, string filePath, string fileName)
{
try
{
byte[] fileByteArray = File.ReadAllBytes(filePath);
string formDataBoundary = $"----------{Guid.NewGuid():N}";
string contentType = "multipart/form-data; boundary=" + formDataBoundary;
byte[] formData = GetMultipartFormDataForUpload(fileByteArray, fileName, contentType, formDataBoundary);
var request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = contentType;
request.UserAgent = Credentials.UserName;
request.CookieContainer = new CookieContainer();
request.ContentLength = formData.Length;
request.Credentials = Credentials;
using (Stream RequestStream = request.GetRequestStream())
{
RequestStream.Write(formData, 0, formData.Length);
RequestStream.Close();
}
var response = request.GetResponse() as HttpWebResponse;
var ResponseReader = new StreamReader(response.GetResponseStream());
string FullResponse = ResponseReader.ReadToEnd();
response.Close();
return FullResponse;
}
catch (Exception ex)
{
throw ex;
}
}
byte[] GetMultipartFormDataForUpload(byte[] byteArray, string fileName, string contentType, string Boundary)
{
Stream FormDataStream = new MemoryStream();
string Header = string.Format("--{0}" + Environment.NewLine + "Content-Disposition: form-data; name=\"{1}\"; filename=\"{2}\""
+ Environment.NewLine + Environment.NewLine, Boundary, "file", fileName);
FormDataStream.Write(Encoding.UTF8.GetBytes(Header), 0, Encoding.UTF8.GetByteCount(Header));
FormDataStream.Write(byteArray, 0, byteArray.Length);
string Footer = Environment.NewLine + "--" + Boundary + "--" + Environment.NewLine;
FormDataStream.Write(Encoding.UTF8.GetBytes(Footer), 0, Encoding.UTF8.GetByteCount(Footer));
FormDataStream.Position = 0L;
var FormData = new byte[(int)(FormDataStream.Length - 1L + 1)];
FormDataStream.Read(FormData, 0, FormData.Length);
FormDataStream.Close();
return FormData;
}
But instead of using HttpRequest I'd like to use HttpClient and instead of doing all the encoding manually (especially in GetMultipartFormDataForUpload) I'd like to use the class MultipartFormDataContent. When I try this, I always get a 500 from the server. This is what I have tried so far:
async Task<string> UploadWithHttpClient(string url, string filePath, string fileName)
{
try
{
byte[] fileByteArray = File.ReadAllBytes(filePath);
var content = new MultipartFormDataContent("------------" + Guid.NewGuid());
var byteArrayContent = new ByteArrayContent(fileByteArray, 0, fileByteArray.Length);
//Option 1
byteArrayContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = fileName
};
//Option 2
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = fileName
};
content.Add(byteArrayContent, "file");
var client = new HttpClient();
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
return result;
}
catch (Exception ex)
{
throw ex;
}
}
What is the right way to replace the httprequest with the httpclient?
Where does the content-disposition header belong (is one of the options I have tried correct)? If yes what else is my problem?
the following code worked for me in the end:
async Task<string> UploadWithHttpClient(string url, string filePath, string fileName)
{
try
{
byte[] fileByteArray = File.ReadAllBytes(filePath);
var content = new MultipartFormDataContent("------------" + Guid.NewGuid());
var byteArrayContent = new ByteArrayContent(fileByteArray);
byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/pdf");
content.Add(byteArrayContent, "\"file\"", $"\"{fileName}\"");
var client = new HttpClient();
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
return result;
}
catch (Exception ex)
{
throw ex;
}
}
```

Basic Authentication with multiple request header in HttpwebRequest in c#. Getting error 401 unauthorized

Getting 401 unauthorized error on calling external API from a console application.
through hhtpwebrequest class. Below is my code... requestBody gives me Json data to post
Please suggest to me how to do authentication.
public string InvokeRestService()
{
var serviceUrl = "http://xrmd0/api/v1.0/student/specialized/feed";
var reqData = _service.Retrieve("entityname",
new Guid("guid"), new ColumnSet("requestdata"));
var requestBody = reqData.Attributes["requestdata"].ToString();
string prefix = #"abc""";
string userName = prefix + "xyz";
string password = "pwdqawe";
try
{
var request = (HttpWebRequest)WebRequest.Create(new Uri(serviceUrl));
request.Method = "POST";
request.ContentType = "application/json";
request.Accept = "application/json";
//request.Headers["authorization"] = "Basic" + Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + password));
request.Headers["Authorization"] = "Basic Auth" + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(userName + ":" + password));
request.Headers["User-Id"] = "userId";
request.Headers["User-Type"] = "usertype";
if (!string.IsNullOrEmpty(requestBody))
{
byte[] data = Encoding.UTF8.GetBytes(requestBody);
var requestStream = request.GetRequestStream();
requestStream.Write(data, 0, data.Length);
requestStream.Close();
}
var response = (HttpWebResponse)request.GetResponse();
var responseStream = response.GetResponseStream();
var responseStreamReader = new StreamReader(responseStream, Encoding.UTF8);
var responseString = responseStreamReader.ReadToEnd();
responseStreamReader.Close();
return responseString;
}
catch (Exception ex)
{
}
}

Invalid Client Authorization header when trying to get token from "Here" REST API

I am trying to get a Bearer token to start using HERE REST API,
using (OAuth 2.0 (JSON Web Tokens))
after a lot of struggles, I am stuck with 401202 error:
{"errorId":"ERROR-e0242f30-05da-4df0-9beb-b697062240ce","httpStatus":401,"errorCode":401202,"message":"Invalid
Client Authorization header, expecting signed request
format.","error":"invalid_request","error_description":"errorCode:
'401202'. Invalid Client Authorization header, expecting signed
request format."}
Here is my code:
private void GetToken()
{
try
{
var here_client_id = "b1Ibl7XXXXXXXoZtNKb";
var here_access_key_id = "8DKjlwXXXXXXXXXerGCXPA";
var here_access_key_secret = "tuU-bGMa1ljancfoXXXXXXXXXXXXXXXK8cMlk4o0EGUpS2fmwkAtlltFPDhYQUgytJLL-X_YNIjmdWcOabQ";
var url = "https://account.api.here.com/oauth2/token";
var Parameters = "grant_type=client_credentials&client_id=" + here_client_id + "&oauth_consumer_key=" + here_access_key_secret;
var hmac = new HMACSHA256();
var key = Convert.ToBase64String(hmac.Key);
Guid id = Guid.NewGuid();
// Create a request for the URL.
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var cred = #"OAuth oauth_consumer_key=" + here_access_key_id;
request.Headers.Add("Authorization", cred);
//request.Headers.Add("oauth_consumer_key", here_access_key_id);
request.Headers.Add("oauth_nonce", id.ToString());
request.Headers.Add("oauth_signature_method", "HMAC-SHA256");
request.Headers.Add("oauth_signature", key);
request.Headers.Add("oauth_timestamp", ConvertToUnixTimestamp(DateTime.Now).ToString());
request.Headers.Add("oauth_version", "1.0");
byte[] byteArray = Encoding.UTF8.GetBytes(Parameters);
request.ContentLength = byteArray.Length;
Stream postStream = request.GetRequestStream();
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Get the response.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Display the status.
Console.WriteLine(response.StatusDescription);
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
MessageBox.Show(responseFromServer);
// Cleanup the streams and the response.
reader.Close();
dataStream.Close();
response.Close();
}
catch (WebException ex)
{
using (var stream = ex.Response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
//MessageBox.Show(reader.ReadToEnd());
textBox1.Text = reader.ReadToEnd();
}
}
}
This is my first cut and is rough but.
var accessKey = "";
var secret = "";
var url = "https://account.api.here.com/oauth2/token";
var nonce = GetNonce();
var timestamp = GetTimeStamp();
var baseString = #"grant_type=client_credentials&oauth_consumer_key=" + accessKey + "&oauth_nonce=" + nonce + "&oauth_signature_method=HMAC-SHA256&oauth_timestamp=" + timestamp + "&oauth_version=1.0";
var workingString = new List<string>();
foreach (var parameter in baseString.Split('&').ToList())
{
workingString.Add(Uri.EscapeDataString(parameter.Split('=')[0] + "=" + parameter.Split('=')[1].Trim()));
}
var urlEncodeParamaterString = String.Join(Uri.EscapeDataString("&"), workingString.ToArray());
var fullBaseString = $"POST&{Uri.EscapeDataString(url)}&{urlEncodeParamaterString}";
var signature = CreateToken(fullBaseString, (Uri.EscapeDataString(secret) + "&"));
var authHeader = "OAuth oauth_consumer_key=\"" + accessKey + "\",oauth_signature_method=\"HMAC-SHA256\",oauth_timestamp=\"" + timestamp + "\",oauth_nonce=\"" + nonce + "\",oauth_version=\"1.0\",oauth_signature=\"" + Uri.EscapeDataString(signature) + "\"";
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);
var response = await httpClient.PostAsync(url, new StringContent($"grant_type={Uri.EscapeDataString("client_credentials")}",
Encoding.UTF8,
"application/x-www-form-urlencoded"));
var responseContent = response.Content.ReadAsStringAsync();
}
The other Methods are
private string GetNonce()
{
var rand = new Random();
var nonce = rand.Next(1000000000);
return nonce.ToString();
}
private string CreateToken(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
private string GetTimeStamp()
{
var ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalSeconds).ToString();
}
At the end I did it without web JSON WEB TOKENS.
According to this API documentation the call was made only with API KEY.
public static string ConvertAddressToCoordinate(string address)
{
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var apikey = "xxxxxxxxxxxxxxxxxxxxx_xxxxxxxxx";
var url = "https://geocoder.ls.hereapi.com/6.2/geocode.json?apiKey=";
var fullurl = url + apikey + "&searchtext=" + address;
// Create a request for the URL.
WebRequest request = WebRequest.Create(fullurl);
request.Method = "GET";
request.ContentType = "application/json";
// Get the response.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Display the status.
Console.WriteLine(response.StatusDescription);
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
return responseFromServer;
}
catch (WebException ex)
{
return "ERROR " + ex.Message;
}
catch (Exception ex)
{
return "ERROR " + ex.Message;
}
}

Posting tasks to Asana using API in C#

I'm trying to figure out how to post a new task to a user in asana, but I keep getting the 400 error code. Can anyone tell me what I am doing wrong.
This is what I have so far:
string apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string ID = "xxxxxxxxxxxxx";
string url = #"https://app.asana.com/api/1.0/tasks";
Data dat = new Data();
dat.workspace = ID;
dat.name = "Buy eggs";
dat.notes = "Testing";
string json = JsonConvert.SerializeObject(dat);
string data ="\"data\": " + json;
byte[] bytes = Encoding.UTF8.GetBytes(data);
var req = (HttpWebRequest)WebRequest.Create(url);
Console.WriteLine(bytes.ToString());
req.Method = WebRequestMethods.Http.Post;
req.ContentLength = bytes.Length;
req.ContentType = "application/json";
var authInfo = apiKey + ":";
var encodedAuthInfo = Convert.ToBase64String(
Encoding.Default.GetBytes(authInfo));
req.Headers.Add("Authorization", "Basic " + encodedAuthInfo);
req.ContentLength = bytes.Length;
Stream reqStream = req.GetRequestStream();
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Close();
try
{
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
string res = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.WriteLine(res);
Console.ReadLine();
}
catch (WebException ex)
{
HttpWebResponse response = ((HttpWebResponse)ex.Response);
string e = url + " caused a " + (int)response.StatusCode + " error.\n" + response.StatusDescription;
Console.WriteLine(e);
Console.ReadLine();
}
I put the serial converter, did i do it wrong?
As the first comment points out, you need to serialize the data properly. The final body posted should look something like:
{ "data": { "name": "My Example Task", ... }}
(Except of course with the ... replaced with more fields.)
I have researched a long and found below code useful and working. I can successfully post Task to Asana through my application. I have used Json serializer for dot net. Thanks to Newtonsoft.Json.
string json = null;
byte[] bytes = null;
string url = "https://app.asana.com/api/1.0/tasks";
HttpWebRequest req = default(HttpWebRequest);
Stream reqStream = default(Stream);
string authInfo = null;
Task TaskData = new Task();
try
{
authInfo = apiKey + Convert.ToString(":");
TaskData.workspace = WorkspaceId;
TaskData.name = TaskName;
TaskData.notes = TaskNotes;
json = JsonConvert.SerializeObject(TaskData);
json = json.Insert((json.Length - 1), ",\"projects\":[" + ProjectId + "]");
json = Convert.ToString("{ \"data\":") + json + "}";
bytes = Encoding.UTF8.GetBytes(json);
req = (HttpWebRequest)WebRequest.Create(url);
req.Method = WebRequestMethods.Http.Post;
req.ContentType = "application/json";
req.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)));
req.ContentLength = bytes.Length;
reqStream = req.GetRequestStream();
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Close();
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
string res = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.WriteLine(res);
Console.ReadLine();
string finalString = res.Remove(0, 8);
finalString = finalString.Remove((finalString.Length - 1));
AsanaObjectId newtask = JsonConvert.DeserializeObject<AsanaObjectId>(finalString);
return newtask;
}
catch (WebException ex)
{
HttpWebResponse response = (HttpWebResponse)ex.Response;
string resp = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
MessageBox.Show(resp);
System.Environment.Exit(0);
}

Posting to Foursquare API fails

I have been working on a Foursquare app for WIndows Mobile 6 (as I still have at least 6months on my contract) I am failing on every attempt to POST data (ie Checkin) so it is not much use. Any suggestions or pointers on why this code always fails at the
oOutStream = request.GetRequestStream();
Line - HELP PLEASE.
public HTTPPost(Uri Url, Dictionary<string, string> Parameters)
{
StringBuilder respBody = new StringBuilder();
request = (HttpWebRequest)HttpWebRequest.Create(Url);
request.UserAgent = "4SqLite 20110803";
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = 12000000;
string content = "?";
foreach (string k in Parameters.Keys)
{
content += k + "=" + Parameters[k] + "&";
}
content = content.TrimEnd(new char[] { '&' });
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(content);
request.ContentLength = byte1.Length;
byte[] buf = new byte[8192];
Stream oOutStream = null;
int tmp = ServicePointManager.DefaultConnectionLimit;
try
{
// send the Post
oOutStream = request.GetRequestStream();
}
catch
{
MessageBox.Show("Oops! We couldn't send data to the Internet. Try again later.", "HttpPost: Request error",
MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
}
finally
{
if (oOutStream != null)
{
oOutStream.Write(byte1, 0, byte1.Length); //Send it
oOutStream.Close();
}
}
try
{
// get the response
response = (HttpWebResponse)request.GetResponse();
Stream respStream = response.GetResponseStream();
int count = 0;
do
{
count = respStream.Read(buf, 0, buf.Length);
if (count != 0)
respBody.Append(Encoding.ASCII.GetString(buf, 0, count));
}
while (count > 0);
respStream.Close();
ResponseBody = respBody.ToString();
EscapedBody = GetEscapedBody();
}
catch
{
MessageBox.Show("Oops! We couldn't get data from the Internet. Try again later.", "HttpPost: Response error",
MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
}
finally
{
StatusCode = GetStatusLine();
Headers = GetHeaders();
response.Close();
}

Categories