How to convert WebClient to HttpClient C# WinForms - c#

I need to convert the webclient code which is obsolte to httpclient.
using WebClient Client = new();
Client.Headers["User-Agent"] = CompanyName + "/" + ProductName;
byte[] responseBytes = Client.UploadFile("http://blahblah.com/upload.php", fileimage);
string response = Encoding.Default.GetString(responseBytes);
_ = MessageBox.Show(response, Text);
I need the exact same way to do this. I have seen other answers but none meet my needs.

1- read AllByte of file into upfilebytes array
2-create new HttpClient and MultipartFormDataContent
3- add byte array to content
4-upload MultipartFormDataContent content async and store response in response.
var upfilebytes = File.ReadAllBytes("fileimage");
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", CompanyName + "/" + ProductName);
MultipartFormDataContent content = new MultipartFormDataContent();
ByteArrayContent baContent = new ByteArrayContent(upfilebytes);
content.Add(baContent, "File", "filename.png");
var response = await client.PostAsync("http://blahblah.com/upload.php", content);
var responsestr = await response.Content.ReadAsStringAsync();
MessageBox.Show(response, responsestr);

The simplest way you can upload a file is something like here.However,
it's better to use HttpClientFactory to generate httpclient instance.
var client = new HttpClient
{
BaseAddress = new("http://blahblah.com/upload.php")
};
await using var stream = System.IO.File.OpenRead("filePathHere");
using var request = new HttpRequestMessage(HttpMethod.Post, "file");
request.Headers.Add("User-Agent",CompanyName + "/" + ProductName);
using var content = new MultipartFormDataContent
{
{ new StreamContent(stream), "file", "fileNameHere" }
};
request.Content = content;
var response = await client.SendAsync(request);
MessageBox.Show(response, Text);

Related

Uploading image to ServiceNow in C# via REST API

I am trying to upload image to ServiceNow incident using SNow API provided in this link:
https://developer.servicenow.com/dev.do#!/reference/api/orlando/rest/c_AttachmentAPI#r_AttachmentAPI-POSTmultipart
I've written below C# code to post the image:
string url = "https://mycompany.service-now.com/api/now/attachment/upload/"
, userName = "MyUser", passwd = "MyPassword";
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential(userName, passwd),
};
using (var httpClient = new HttpClient(httpClientHandler))
{
// Add an Accept header for JSON format.
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var multipartContent = new MultipartFormDataContent();
multipartContent.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data");
multipartContent.Add(new StringContent("incident"), "table_name");
multipartContent.Add(new StringContent("f264fd3a1bghghgjjhg8f7b4bcbb6"), "table_sys_id"); // id of my incident
multipartContent.Add(new ByteArrayContent(File.ReadAllBytes("D:\\MyImage.jpeg")), "uploadFile", "MyImage.jpeg");
var response = httpClient.PostAsync(new Uri(url), multipartContent).Result;
string result = response.Content.ReadAsStringAsync().Result;
MessageBox.Show(result);
}
However, I keep getting:
Requested URI does not represent any resource
What could be the problem and how to adjust the code accordingly?
After removing the "/" at the end of the url, and also adding double qoutes around the keys in the headers as I read from this post:
https://community.servicenow.com/community?id=community_question&sys_id=328614ffdb00eb808e7c2926ca9619ad&view_source=searchResult
The final working code is:
string url = "https://mycompany.service-now.com/api/now/attachment/upload"
, userName = "MyUser", passwd = "MyPassword";
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential(userName, passwd),
};
using (var httpClient = new HttpClient(httpClientHandler))
{
// Add an Accept header for JSON format.
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var fileStream = new ByteArrayContent(File.ReadAllBytes("D:\\Image.jpeg"));
fileStream.Headers.Remove("Content-Type");
fileStream.Headers.Add("Content-Type", "application/octet-stream");
fileStream.Headers.Add("Content-Transfer-Encoding", "binary");
fileStream.Headers.Add("Content-Disposition", $"form-data;name=\"uploadFile\"; filename=\"{"Image.jpeg"}\"");
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(new StringContent("incident"), "\"table_name\"");
multipartContent.Add(new StringContent("f264fd3a1bghghgjjhg8f7b4bcbb6"), "\"table_sys_id\"");
multipartContent.Add(fileStream, "uploadFile");
var response = httpClient.PostAsync(new Uri(url), multipartContent).Result;
string result = response.Content.ReadAsStringAsync().Result;
MessageBox.Show(result);
}

ReasonPhrase Not Acceptable HTTPClient C#

I am trying to send a json object with a base4 encoded file to a web api service using the code below
MemoryStream target = new MemoryStream();
q.fileUpload.InputStream.CopyTo(target); //q.fileUpload is an HttpPostedFilebase pdf
var myfile= Convert.ToBase64String(target.ToArray());
var requestbody = new {
filedata = new
{
mimetype = "application/pdf",
basedata = "base64-data=" + myfile
}
};
var jsondata = JsonConvert.SerializeObject(requestbody );
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://web.base.url/");
client.DefaultRequestHeaders.Add("X-API-KEY", "SOMEAPIKEY");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "upload");
request.Content = new StringContent(jsondata, Encoding.UTF8, "application/json");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var responsetask= client.SendAsync(request);
return Json(responsetask);
But i everytime i call this i get a 406 Not Acceptable response. Anyone knows what causes it?

How to send a json file with HttpClient in C#?

I'm trying send a JSON file with postman and it's working. But when I'm trying to send the same contents via HttpClient it's not working.
System.IO.File.WriteAllText(dirName + "\\importproduct.json", jsonitems);
var fileByteArray = File.ReadAllBytes(dirName + "\\importproduct.json");
using (var _client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
content.Add(new StreamContent(new MemoryStream(fileByteArray)), "file");
var url = $"{firmInfo.ServiceUrl}/product/api/products/import";
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearer_token.id_token);
var response = _client.PostAsJsonAsync(url, content).Result;
var result = response.Content.ReadAsStringAsync().Result;
}
}
PostMan:
Instead of using PostAsJsonAsync(); method you should use PostAsync(); So your code should be looking something like that
using (var _client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
content.Add(new StreamContent(new MemoryStream(fileByteArray)), "file");
var url = $"{firmInfo.ServiceUrl}/product/api/products/import";
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearer_token.id_token);
var response = _client.PostAsync(url, content).Result;
var result = response.Content.ReadAsStringAsync().Result;
}
}
PostAsJsonAsync method is a generic method, it expects as the second parameter the object that will be serialized and sent in the POST body.
var obj = JsonConvert.DeserializeObject<SomeModelClass>(jsonString);
var response = await _client.PostAsJsonAsync(url, obj).Result;
This is based on efecetir's post above. It works for me. BTW, I also upvoted his post.
My issue was I needed to set the content type at the content-based level.
var fileByteArray = File.ReadAllBytes(filePath);
HttpContent bytesContent = new ByteArrayContent(fileByteArray);
using (var httpClient = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
var RequestUri = new Uri($"http://whatever.com/");
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearer_token.id_token);
formData.Headers.Add("super-secret-key", "blah");
bytesContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
//httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //("multipart/form-data")); // Not needed
formData.Add(bytesContent, "file", "blah.json");
var response = httpClient.PostAsync(RequestUri, formData).Result;
return await HandleResponse(response);
}
Thanks for your comments.
I fixed it and convert my codes as below. Now it's working and much more clean.
HttpContent bytesContent = new ByteArrayContent(fileByteArray);
using (var client = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
var url = $"{firmInfo.ServiceUrl}/product/api/products/import";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearer_token.id_token);
formData.Add(bytesContent, "file", "importproduct.json");
var response = client.PostAsync(url, formData).Result;
var result = response.Content.ReadAsStringAsync().Result;
}
Here's code I'm using to post form information and a file
using (var httpClient = new HttpClient())
{
var surveyBytes = ConvertToByteArray(surveyResponse);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var byteArrayContent = new ByteArrayContent(surveyBytes);
byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("text/csv");
var url = $"{firmInfo.ServiceUrl}/product/api/products/import";
var response = await httpClient.PostAsync(url , new MultipartFormDataContent
{
{byteArrayContent, "\"file\"", dirName + "\\importproduct.json"}
});
return response;
}
This is for .net 4.5.

How to send a file and form data with HttpClient in C#

How can I send a file and form data with the HttpClient?
I have two ways to send a file or form data. But I want to send both like an HTML form. How can I do that? Thanks.
This is my code:
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
var client = new HttpClient();
var requestContent = new MultipartFormDataContent();
filename = openFileDialog1.FileName;
array = File.ReadAllBytes(filename);
var imageContent = new ByteArrayContent(array);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("audio/*");
requestContent.Add(imageContent, "audio", "audio.wav");
var values = new Dictionary<string, string>
{
{ "token", "b53b99534a137a71513548091271c44c" },
};
var content = new FormUrlEncodedContent(values);
requestContent.Add(content);
var response = await client.PostAsync("localhost", requestContent);
var responseString = await response.Content.ReadAsStringAsync();
txtbox.Text = responseString.ToString();
}
Here's code I'm using to post form information and a csv file
using (var httpClient = new HttpClient())
{
var surveyBytes = ConvertToByteArray(surveyResponse);
httpClient.DefaultRequestHeaders.Add("X-API-TOKEN", _apiToken);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var byteArrayContent = new ByteArrayContent(surveyBytes);
byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("text/csv");
var response = await httpClient.PostAsync(_importUrl, new MultipartFormDataContent
{
{new StringContent(surveyId), "\"surveyId\""},
{byteArrayContent, "\"file\"", "\"feedback.csv\""}
});
return response;
}
This is for .net 4.5.
Note the \" in the MultipartFormDataContent. There is a bug in MultipartFormDataContent.
In 4.5.1 MultipartFormDataContent wraps the data with the correct quotes.
Update: This link to the bug no longer works since the have retired Microsoft Connect.
Here's code I'm using a method to send file and data from console to API
static async Task uploaddocAsync()
{
MultipartFormDataContent form = new MultipartFormDataContent();
Dictionary<string, string> parameters = new Dictionary<string, string>();
//parameters.Add("username", user.Username);
//parameters.Add("FullName", FullName);
HttpContent DictionaryItems = new FormUrlEncodedContent(parameters);
form.Add(DictionaryItems, "model");
try
{
var stream = new FileStream(#"D:\10th.jpeg", FileMode.Open);
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(#"http:\\xyz.in");
HttpContent content = new StringContent("");
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "uploadedFile1",
FileName = "uploadedFile1"
};
content = new StreamContent(stream);
form.Add(content, "uploadedFile1");
client.DefaultRequestHeaders.Add("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.dsfdsfdsfdsfsdfkhjhjkhjk.vD056hXETFMXYxOaLZRwV7Ny1vj-tZySAWq6oybBr2w");
var response = client.PostAsync(#"\api\UploadDocuments\", form).Result;
var k = response.Content.ReadAsStringAsync().Result;
}
catch (Exception ex)
{
}
}

Unable to get header "Content-Disposition" with httpclient in C#

SCENARIO:
First of all, please consider I'm using HttpClient class, not WebRequest, I know that there is a lot of related question here but all answers are for WebRequest.
I made a Web Api Application that set in this way the following header in order to download a .txt file:
resp.Content = new StringContent(result, System.Text.Encoding.UTF8, "text/plain");
resp.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = _datacontext.GetAppConfig("814FileNameHeader") + DateTime.Now.ToString("yyyyMMdd") + ".txt"
};
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
After I made an HttpClient from other application to connect to this method.
Everything is working, retrieves 200 and the content of the file. But I can't get the header in order to read the filename.
TRIES MADE:
Working with a REST Client I can read the following header attribute:
Content-Disposition: attachment; filename=814Entes_PG_20160114.txt
and from the code I could debug it and I found that the header is in "invalidHeaders" but I can't reach the value:
QUESTION:
How can I set up this and getting without any doubt from the client?
UPDATE:
These are my tries to get the header:
The original:
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(uri);
string authentication = string.Concat(authenticationArgs[0], ":", authenticationArgs[1]);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Basic " + Base64Encode(authentication));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, "Report/" + type);
req.Content = new StringContent("");
HttpResponseMessage response = await httpClient.SendAsync(req);
Console.WriteLine(response.StatusCode);
if (response.IsSuccessStatusCode)
{
string stream = response.Content.ReadAsStringAsync().Result;
Console.Write("Respuesta servicio: " + stream);
Console.WriteLine(stream);
string cp = response.Headers.GetValues("Content-Disposition").ToString();
}
The second one I tried with some SO investigation:
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(uri);
string authentication = string.Concat(authenticationArgs[0], ":", authenticationArgs[1]);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Basic " + Base64Encode(authentication));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, "Report/" + type);
req.Content = new StringContent("");
HttpResponseMessage response = await httpClient.SendAsync(req);
Console.WriteLine(response.StatusCode);
if (response.IsSuccessStatusCode)
{
string stream = response.Content.ReadAsStringAsync().Result;
Console.Write("Respuesta servicio: " + stream);
Console.WriteLine(stream);
string cp = "";
HttpHeaders headers = response.Headers;
IEnumerable<string> values;
if (headers.TryGetValues("Content-Disposition", out values))
{
cp = values.ToString();
}
}
If you are trying to get the headers of the content, it should be from response.Content.Headers
As per #terbubbs you need response.Content.Headers.
But also code needs to be - for the first code sample:
string cp = response.Result.Content.Headers.GetValues("Content-Disposition").ToList()[0];
And for the second:
cp = values.FirstOrDefault().ToString();
Otherwise the result is System.String[]

Categories