HTTP POST file from .NET controller to java rest service - c#

Lately i have been trying to post a file from .net controller through .net controller using HttpClient,
to a Java Rest Service and failed many times as i was unable to send the file in the correct format.
below ajax call in the working jQuery way to invoke the service and pass the file with meta data key.
function Upload() {
var data = new FormData();
data.append('file', document.getElementById("file").files[0])
var metaData = [{"symbolicName": "DocumentTitle","dataType": "string","value": "Test CSEPF Document"}]
data.append('metaData', JSON.stringify(metaData));
$.ajax({
url: 'http://xxx:xx/FileNetCoreRestServices/AddDocument',
type: "POST",
dataType: 'json',
data: data,
contentType: false,
processData: false,
success: function (data) {
debugger
}
});
}
Request payload when posted with ajax
------WebKitFormBoundaryaCyKxSim0zzwhHK7
Content-Disposition: form-data; name="file"; filename="4.pdf"
Content-Type: application/pdf
------WebKitFormBoundaryaCyKxSim0zzwhHK7
Content-Disposition: form-data; name="metaData"
[{"symbolicName":"DocumentTitle","dataType":"string","value":"Test CSEPF Document"}]
------WebKitFormBoundaryaCyKxSim0zzwhHK7--
Now i want the same thing to be replicated in the .net controller side,
As per my research i know that i need to use MultipartFormDataContent and HttpClient in order to get this working.
below is the .net code i have written in order to upload the file to the service.
List<string> lstFilesToBeUploaded = null;
try
{
string FileTransferApiUrl = "http://xxx:xx/FileNetCoreRestServices/AddDocument";
lstFilesToBeUploaded = new List<string>();
string OperatorSourceRootFolderPath = Server.MapPath(System.Configuration.ConfigurationSettings.AppSettings["UploadLocation"]);
if (Directory.Exists(OperatorSourceRootFolderPath))
{
lstFilesToBeUploaded = Directory.GetFiles(OperatorSourceRootFolderPath).ToList();
}
foreach (string filePart in lstFilesToBeUploaded) // improvement - this is sequential, can be made threaded
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("metaData", "[{'symbolicName':'DocumentTitle','dataType':'string','value':'Test CSEPF Document'}]");
using (var content = new MultipartFormDataContent())
{
byte[] Bytes = System.IO.File.ReadAllBytes(filePart);
var fileContent = new StreamContent(new MemoryStream(Bytes));
fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = Path.GetFileName(filePart) };
content.Add(fileContent);
var response = client.PostAsync(FileTransferApiUrl, fileContent).Result;
if (response.IsSuccessStatusCode)
{
var responseData = response.Content.ReadAsStringAsync().Result;
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
When i run this code i get the response as
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { Access-Control-Allow-Origin: * $WSEP: Transfer-Encoding: chunked Connection: Close Date: Wed, 27 Jun 2018 11:41:39 GMT Server: WebSphere Server: Application Server: Server/7.0 Content-Language: en-US Content-Type: text/html; charset=ISO-8859-1 }}
I am not entirely sure how the MultipartFormDataContent works, it would be helpful if any one points out where i am going wrong.

After so many failed attempts and research i was able to call the service with the file, and below is the working code which i used in order to achieve this.
#region FILENET Upload
string FileLocation = Server.MapPath(System.Configuration.ConfigurationSettings.AppSettings["FileLocation"]);
var FileNetRestServiceURL = "http://xxx:xx/FileNetCoreRestServices/AddDocument";
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
//Working - Default Values
//var values = new[]
//{new KeyValuePair<string, string>("metaData", "[{'symbolicName':'DocumentTitle','dataType':'string','value':'Test CSEPF Document'}]")};
//Real Values
var values = new[]
{new KeyValuePair<string, string>("metaData", "[{'symbolicName':'"+Path.GetFileNameWithoutExtension(FileLocation).ToString()+"','dataType':'string','value':'"+Path.GetFileNameWithoutExtension(FileLocation).ToString()+"'}]")};
//Convert the file into ByteArrayContent as the service is expecting a file object
content.Add(new ByteArrayContent(System.IO.File.ReadAllBytes(FileLocation)), "file", Path.GetFileName(FileLocation).ToString());
foreach (var keyValuePair in values)
{
content.Add(new StringContent(keyValuePair.Value), keyValuePair.Key);
}
var response = client.PostAsync(FileNetRestServiceURL, content).Result;
if (response.IsSuccessStatusCode)
{
var responseData = response.Content.ReadAsStringAsync().Result;
}
}
}
#endregion

try something like:
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
var values = new[]
{
new KeyValuePair<string, string>("metaData", JsonConvert.SerializeObject("[{'symbolicName':'DocumentTitle','dataType':'string','value':'Test CSEPF Document'}]"))
};
foreach (var keyValuePair in values)
{
content.Add(new StringContent(keyValuePair.Value), keyValuePair.Key);
}
var fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(filePart));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Foo.txt"
};
content.Add(fileContent);
var requestUri = "http://xxxx:xxxx/CSEPFCoreRestServices/addDocument";
var result = client.PostAsync(requestUri, content).Result;
}
}

Related

C# REST Api always return 401 status code when i am calling API by HttpClient

I am working with Nasdaq Fund Network Data Service first time. i am calling their one of the API where passing user id,pwd and access key but always getting 401 status code. i am not able to figure out what is wrong in my http call. please some one have a look at the code and tell me where i made the mistake for which i am getting 401 status code instead of right response.
here is my sample code where i could not share actual credentials and access key.
giving the code
string url = "sample url";
Uri u = new Uri(url);
string username = "test1";
string password = "test2";
string accessKey = "myaccesskey";
var payload = new Dictionary<string, string>
{
{"username", username},
{"password", password},
{ "accessKey", accessKey}
};
string strPayload = JsonConvert.SerializeObject(payload);
//HttpContent c = new StringContent(strPayload, Encoding.UTF8, "application/json");
HttpContent c = new StringContent(strPayload, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = string.Empty;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
using (var client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = u,
Content = c
};
var result = client.SendAsync(request).Result;
if (result.IsSuccessStatusCode)
{
response = result.StatusCode.ToString();
}
}
This Error i am getting
{StatusCode: 401, ReasonPhrase: 'Check Username/Password or Access
Key', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: {
Pragma: no-cache X-Frame-Options: SAMEORIGIN Cache-Control:
no-cache Date: Wed, 10 Aug 2022 11:55:36 GMT Content-Length: 0
Expires: -1 }}
Try the following in order to extract the JWT token you receive as a response.
var url = "https://nfn.nasdaq.com/servicecall/tempsession";
var formDataDictionary = new Dictionary<string, string>
{
{ "username", "test1"},
{ "password", "test2"},
{ "accessKey", "myaccesskey"}
};
var formData = new FormUrlEncodedContent(formDataDictionary);
using (var client = new HttpClient())
{
var response = await client.PostAsync(url, formData);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
var responseBody = JObject.Parse(result);
var accessToken = responseBody["data']"].Value<string>();
}

Uploading files to GLPI server POST_MAX_SIZE

I'm trying to POST a Document (any file type) to a GLPI server through API REST.
Here is what I'm doing:
private void button11_Click(object sender, EventArgs e)
{
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
var rcontent = string.Empty;
// HEADERS (URL + Access Tokens)
//string _ContentType = "multipart/form-data";
string _Uri = Properties.Settings.Default.GLPI_URL + "/Document/";
client.BaseAddress = new Uri(_Uri);
//client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(_ContentType));
client.DefaultRequestHeaders.Add("Session-Token", Properties.Settings.Default.GLPI_SESSION_TOKEN);
client.DefaultRequestHeaders.Add("App-Token", Properties.Settings.Default.GLPI_APP_TOKEN);
// JSON Content (input string array with file uploaded informations)
JSON_C.DocumentAdder JSONContent = new JSON_C.DocumentAdder();
JSONContent.name = "sth";
JSONContent._filename = filebytes;
HttpContent _JSONContent = new StringContent("uploadManifest={\"input\": " + JsonConvert.SerializeObject(JSONContent).ToString() + "}", Encoding.UTF8, "application/json");
content.Add(_JSONContent);
// File Content in bytes
var fileContent = new ByteArrayContent(filebytes);
fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("_filename") { FileName = filepath };
//fileContent.ReadAsByteArrayAsync();
content.Add(fileContent);
// Request
HttpResponseMessage reponse;
var _Method = new HttpMethod("POST");
reponse = client.PostAsync(_Uri, content).Result;
// Request response
rcontent = reponse.Content.ReadAsStringAsync().Result;
textBox2.Text = reponse.ToString() + Environment.NewLine + rcontent.ToString();
}
}
}
But this is what I got in response:
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: close
Cache-Control: no-store, must-revalidate, no-cache
Date: Mon, 26 Nov 2018 12:50:09 GMT
Server: Apache/2.4.29
Server: (Ubuntu)
Content-Length: 61
Content-Type: application/json; charset=UTF-8
Expires: Mon, 26 Jul 1997 05:00:00 GM
}
With:
["ERROR_UPLOAD_FILE_TOO_BIG_POST_MAX_SIZE","The file seems too big"]
The file I'm trying to upload is 592bytes! Max overall limit in one request is 2Mo. And post_max_size in php.ini is "8M", the same result after I changed it to "0" (for no limit at all). And then set it to 20M to match upload_max_filesize (/etc/php/7.2/apache2/php.ini).
upload_max_filesize_.. is also "20M"
If anyone finding this post and needs help, here is how i managed to succeed :
After separatly creating a "Session-Token", and using "RestSharp".
// Upload
var RSClient = new RestClient(Properties.Settings.Default.GLPI_URL);
var request = new RestRequest("Document", Method.POST);
request.AddHeader("Session-Token", Properties.Settings.Default.GLPI_SESSION_TOKEN);
request.AddHeader("App-Token", Properties.Settings.Default.GLPI_APP_TOKEN);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "multipart/form-data");
request.AddQueryParameter("uploadManifest", "{\"input\": {\"name\": \"UploadFileTest\", \"_filename\": \"GiletsJaunes.jpg\"}}");
request.AddFile("test", #"C:\path\to\File.jpg");
IRestResponse response = RSClient.Execute(request);
var content = response.Content;
textBox2.Text = textBox2.Text + Environment.NewLine + content;
Details :
I couldn't use RestSharp.Authenticator = new SimpleAuthenticator for some reasons, so i added these Auth params with AddHeader.
I couldn't use a Serialised Json string in a new StringContent, because of AddQueryParameter, so i wrote it manually.
Alleluyah.

HttpPost Async retunrs BadRequest from hosted application c#

I am calling a JVA RESTful API from my c# code and passing a data type "MultipartFormDataContent" as one of the parameters.
This has an object named "attachments" and the size of it could be as big as 2GB.
All this works fine when I run the code locally from my PC.
However, when I host the code on my IIS app server it fails when the file size is >20MB. It works fine for files <20MB.
In IIS, I do have the "RequestFiltering maxAllowedContentLength set to 2147483647".
Here is the code:
HttpContent messageContent = new StringContent(jss.Serialize(new
{
to ="abc#xyz.com"
cc ="abc#xyz.com",
subject = "Subject",
body ="body"
}));
using (var client = new HttpClient())
{
client.Timeout = new TimeSpan(12, 0, 0);
var section = System.Configuration.ConfigurationManager.GetSection("secureAppSettings") as NameValueCollection;
byte[] credentials = Encoding.UTF8.GetBytes(section["username"] + ":" + section["password"]);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(credentials));
using (var formData = new MultipartFormDataContent())
{
formData.Add(messageContent, "message");
List<Tuple<string, string, long>> listOfFiles = new List<Tuple<string, string, long>>();
if (Directory.Exists(HttpContext.Current.Server.MapPath(System.Configuration.ConfigurationManager.AppSettings["RootDocumentTemplateFileRecreatePath"] + instanceID)))
{
string[] filePaths = Directory.GetFiles(HttpContext.Current.Server.MapPath(System.Configuration.ConfigurationManager.AppSettings["RootDocumentTemplateFileRecreatePath"] + instanceID));
// listOfFiles.Add(new Tuple<string, string, long>(Path.GetFileName(filePaths[0]), filePaths[0], new FileInfo(filePaths[0]).Length));
foreach (var eachFilePath in filePaths)
{
string filename = Path.GetFileName(eachFilePath);
string filePath = eachFilePath;
long fileSize = new FileInfo(eachFilePath).Length;
var stream = new FileStream(eachFilePath,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
{
client.Timeout = new TimeSpan(12, 0, 0);
var fileContent = new StreamContent(stream, 1024 * 1024 * 100);
{
var size = fileSize;
fileContent.Headers.ContentDisposition = new
ContentDispositionHeaderValue("attachments")
{
FileName = filename,
DispositionType = DispositionTypeNames.Attachment,
Name = "attachments"
};
fileContent.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
fileSizes.Add(filename, size);
formData.Add(fileContent, "attachments", filename);
}
}
}
fileSizesContent = new StringContent(jss.Serialize(fileSizes));
formData.Add(fileSizesContent, "fileSizes");
}
var response = client.PostAsync(<java RESTful service url>,formData).Result;
Here is the response object I get on sending files >20MB:
adRequestMethod: POST, RequestUri: 'RESTful service url', Version: 1.1, Content: System.Net.Http.MultipartFormDataContent, Headers:
{
Authorization: Basic TWVzc2FnZUNvdXJpZXJVc2VyOlN0YXJzTWVzc2FnZUNvdXJpZXIwMQ==
Content-Type: multipart/form-data; boundary="08c7381e-a190-4c90-98b3-a0a1dae5107b"
Content-Length: 19998604
}Bad RequestPragma: no-cache
Connection: close
Cache-Control: no-store, must-revalidate, no-cache
Date: Thu, 30 Mar 2017 17:40:02 GMT
Appreciate your help.
Thanks in advance.
Regards,
Sridhar

HttpClient post request for WebApi using asp.net mvc application

I'm trying to consume WebApi but I'm having issues. My 'IsSuccessStatusCode' is always false and I have 404 in response.
I have tried multiple methods but can't be able to do it correctly.
Constants:
const string baseUri = ""; // base url of API
const string setDealFlagUri = "Deals/SetDealFlag";
Method 1, using PostAsync:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUri);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("deadId", "3"),
new KeyValuePair<string, string>("flagValueToSet", "true")
});
var response = await client.PostAsync(setDealFlagUri, content);
if (response.IsSuccessStatusCode)
{
return true;
}
}
Method 2, using PostAsJsonAsync:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUri);
DealFlag content = new DealFlag
{
deadId = 3,
flagValueToSet = true
};
var response = await client.PostAsJsonAsync(setDealFlagUri, content);
if (response.IsSuccessStatusCode)
{
return true;
}
}
WebApi request detail:
Curl:
curl -X POST --header 'Accept: application/json' '{baseApiurl}/Deals/SetDealFlag?dealId=3&flagValueToSet=true'
Request URL
{baseApiurl}/Deals/SetDealFlag?dealId=3&flagValueToSet=true
Response Body
{
"Successful": true,
"ErrorMessages": [],
"ValidationResults": {
"IsValid": false,
"ValidationErrors": []
}
}
Response Headers
{
"pragma": "no-cache",
"date": "Wed, 24 Aug 2016 18:38:01 GMT",
"content-encoding": "gzip",
"server": "Microsoft-IIS/8.0",
"x-aspnet-version": "4.0.30319",
"x-powered-by": "ASP.NET",
"vary": "Accept-Encoding",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"content-length": "198",
"expires": "-1"
}
Please help me to use this webapi function correctly.
Thanks!
I think that the problem is that your controller method has signature like
[HttpPost]
public HttpResponseMessage SetDealFlag(int dealId, bool flagValueToSet)
Am I right? If your answer is "Yes" so your method wants parameters in the URL.
And so you get 404 error becouse no one of yours Web API methods matches to that URL.
Send your parameters dealId and flagValueToSet in the URL is the solution.
I wrote simple console app for testing my theory and it works perfectly:
public static void Main(string[] args)
{
using (var client = new HttpClient())
{
try
{
// Next two lines are not required. You can comment or delete that lines without any regrets
const string baseUri = "{base-url}";
client.BaseAddress = new Uri(baseUri);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("deadId", "3"),
new KeyValuePair<string, string>("flagValueToSet", "true")
});
// response.Result.IsSuccessStatusCode == true and no errors
var response = client.PostAsync($"{baseUri}/Deals/SetDealFlag?dealId=3&flagValueToSet=true", null);
// response.Result.IsSuccessStatusCode == false and 404 error
// var response = client.PostAsync($"{baseUri}/Deals/SetDealFlag", content);
response.Wait();
if (response.Result.IsSuccessStatusCode)
{
return;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
}

Set the response message content but I can't retrieve it

I've got a server method that takes and codifies a list of strings, since IE9 doesn't read json format, what I want is to set the string in the content of an http response message. I seems to do it well but when I get the response I can's find the response on the body, what I can see is only the length of what I set in the response message.
here is the code:
public HttpResponseMessage Upload()
{
HttpResponseMessage m = new HttpResponseMessage(HttpStatusCode.OK);
List<string> returnlist = new List<string>();
for (int i = 0; i < Request.Files.Count; i++)
{
//string treatment
}
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new StringContent(string.Join(",", returnlist));
return response;
}
this is what the string contains "file1,file2,file3"
but I can't find it debugging in visual studio or firebug
The response that I get is:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Content-Type: text/plain; charset=utf-8
}
How can I set and then get the response message?
In case of need the js here is it:
self.uploadfiles = function () {
//startSpinner();
if (!self.isOldIE()) {
var loc = window.location;
base_url = loc.protocol + "//" + loc.host;
baseUrl = base_url + "/";
var save = true;
var xhr = new XMLHttpRequest();
xhr.open('POST', baseUrl + 'Home/Upload');
xhr.send(formdata);
xhr.onreadystatechange = function (data) {
//The responseText is the same as above
if (xhr.responseText.length > 0) {
//do stuff
}
};
Try this code
var response = Request.CreateResponse(HttpStatusCode.OK, string.Join(",", returnlist));
return response;
Try this to get the response using Javascript:
var xhr = new XMLHttpRequest();
xhr.open('POST', baseUrl + 'Home/Upload', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
alert(xhr.responseText);
} else {
// do something about the error
}
};
xhr.send(formdata);
Note the third boolean parameter of the open() method for getting asynchronously.
For some reason the browsers doesn't show the entire body of the http response. So my solution was to write the header of the response and get the header from js.
Maybe somebody knows why the browsers doesn't show the body, or has a better solution.
This is my controller:
public HttpResponseMessage Upload()
{
HttpResponseMessage m = new HttpResponseMessage(HttpStatusCode.OK);
List<string> returnlist = new List<string>();
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase file = Request.Files[i]; //Uploaded file
//Use the following properties to get file's name, size and MIMEType
int fileSize = file.ContentLength;
if (file.FileName != "")
{
string fileName = string.Format("{0}.{1}", Guid.NewGuid().ToString(), file.FileName.ToString().Split('.')[1].ToString());
returnlist.Add(fileName);
}
}
//Here I write the response message headers
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new StringContent(string.Join(",", returnlist), Encoding.UTF8, "text/html");
response.Headers.Add("data", string.Join(",", returnlist));
return response;
}
And here is how I get the header response:
var xhr = new XMLHttpRequest();
xhr.open('POST', baseUrl + 'Home/Upload');
xhr.send(formdata);
xhr.onreadystatechange = function (data) {
if (xhr.responseText.length > 0) {
//header response
var response = xhr.responseText;
}

Categories