Pass Files in C# HttpClient Post request - c#

I am writing code in C# to consume POST API that accepts form-body with the following parameters.
Files[Array] (User can send multiple files in request)
TemplateId[Int]
Also, I need to pass the bearer AuthToken as a header in the HTTP client Post Request.
I need some help writing the HTTP request with the above form data.
using (var client = new HttpClient())
{
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, $" {_apiBaseUri}/{route}");
requestMessage.Headers.Authorization = new AuthenticationHeaderValue($"Bearer {authToken}");
var pdfFiles = Directory.GetFiles($"C:\\files", "*.pdf");
foreach (var filename in pdfFiles)
{
// create array[] of each File and add them to the form data request
}
// Add TemplateId in the form data request
}
postman request
swagger request

you can add files with 'MultipartFormDataContent'.
private static async Task UploadSampleFile()
{
var client = new HttpClient
{
BaseAddress = new("https://localhost:5001")
};
await using var stream = System.IO.File.OpenRead("./Test.txt");
using var request = new HttpRequestMessage(HttpMethod.Post, "file");
using var content = new MultipartFormDataContent
{
{ new StreamContent(stream), "file", "Test.txt" }
};
request.Content = content;
await client.SendAsync(request);
}
for more: https://brokul.dev/sending-files-and-additional-data-using-httpclient-in-net-core

The Below Code change worked for me,
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), _apiBaseUri))
{
request.Headers.TryAddWithoutValidation("Authorization", $"Bearer {authToken}");
var pdfFiles = Directory.GetFiles($"C:\\test", "*.pdf");
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(new StringContent("100"), "templateId");
foreach (var filename in pdfFiles)
{
multipartContent.Add(new ByteArrayContent(File.ReadAllBytes(filename)), "files", Path.GetFileName(filename));
}
request.Content = multipartContent;
var response = await httpClient.SendAsync(request);
}
}

Related

Postman form-data: How to program it inside a HttpRequestMessage?

I am doing a request through postman to a specific url but I set the form-data type in order to get data to the site like this:
Now I want to program this request inside C# but everything I tried so far is returning a 400 Bad Request response. This is what I tried:
public async Task<CheckAccessTokenModel> CheckAccessTokenAsync(string accessToken)
{
string uriString = "someurl";
var uri = new Uri(uriString);
try
{
using(var httpClient = new HttpClient())
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = uri
};
var ClientId = ConfigurationAccessor.Configuration["WebCredentials:ClientId"];
var Secret = ConfigurationAccessor.Configuration["WebCredentials:Secret"];
var authString = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{ClientId}:{Secret}"));
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StringContent("token"), accessToken);
request.Content = content;
var response = await httpClient.SendAsync(request);
var checkTokenResponseData = await response.Content.ReadAsStringAsync();
//return new CheckAccessTokenModel { Active = true, Exp = 1647431224233 };
return JsonConvert.DeserializeObject<CheckAccessTokenModel>(checkTokenResponseData);
}
}
catch
{
return null;
}
}
I am doing it with the MultipartFormDataContent Object as suggested by many others here but it still won't work.
What can be the problem here?
EDIT: Wrong picture replaced
You can simply
request.Content = new StringContent($"token={accessToken}");
With form data I think it's something like this:
var data = new Dictionary<string, string>
{
{"token", acccessToken}
};
using var content = new FormUrlEncodedContent(data);
request.Content = content;

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);
}

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.

Can't get body data on server using C# code

I'm trying to send a json content inside the body. But unfortunately, I don't get the data in the server. Same data is received using postman tool.
Here is the code I'm running
private string callAPI(string function, string content)
{
using (var httpClient = new HttpClient())
{
string url = function;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", txt_sessionKey.Text);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
httpClient.BaseAddress = new Uri(baseUrlV2);
var json = new StringContent(content, Encoding.UTF8, "application/json");
HttpRequestMessage request = new HttpRequestMessage
{
Method = HttpMethod.Put,
RequestUri = new Uri(baseUrlV2+function),
Content = json
};
HttpContent contentRes = httpClient.SendAsync(request).Result.Content;
return contentRes.ReadAsStringAsync().Result;
}
}
What am I missing here?

Posting unicode data using HttpClient

I am trying to post some unicode data using Http request message. Somehow content encoding is causing some issue. I am not setting any encoding explicitly in my code.
For example, I am trying to send 'รัค' & on client side it is being received as 'รัà¸'.
Sample code
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer, })
using(var httpClient = new HttpClient(handler)){
//set all cookies
foreach (var obj in configurationData["request_cookies"])
{
var cookie = ((JProperty)(obj));
cookieContainer.Add(new Uri(configurationData["request_cookie_base_url"].ToString()),
new Cookie(cookie.Name, HttpUtility.UrlEncode(cookie.Value.ToString())));
}
var request = new HttpRequestMessage();
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(configurationData["form_url"].ToString());
//set all request headers
foreach (var obj in configurationData["request_headers"])
{
var cookie = ((JProperty) (obj));
request.Headers.Add(cookie.Name, cookie.Value.ToString());
}
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
//get request content data from configurationData as keyvalue pair
var contentValue = parsedCrmConfigurationData["form_data_template"]
.ToObject<Dictionary<string, string>>();
request.Content = new FormUrlEncodedContent(contentValue);
var response = httpClient.SendAsync(request).Result;
response.EnsureSuccessStatusCode();
}
Do I need to pass encoding specifically? if yes then how?
Please help me understand the issue.
you can use below code to encode your content
private static HttpContent getencodedContent(string jsonString)
{
var cont = new StringContent(jsonString, Encoding.UTF8, "application/json");
return cont;
}

Categories