How to post file and data to api using httpclient - c#

I am at learning phase and i want to post file and data to api using httpclient.
i have tried this.
Here is my controller code
string baseUrl = ServerConfig.server_path + "/api/Payment/AddMedicineOrder";
Dictionary parameters = new Dictionary();
parameters.Add("username",user.Username);
parameters.Add("FullName", FullName);
parameters.Add("Phone", Phone);
parameters.Add("CNIC", CNIC);
parameters.Add("address", address);
parameters.Add("Email", Email);
parameters.Add("dateofbirth", dateofbirth.ToShortDateString());
parameters.Add("Gender", Gender);
parameters.Add("PaymentMethod", PaymentMethod);
parameters.Add("Title", Title);
parameters.Add("PhramaList", medList);
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://localhost:44391/");
MultipartFormDataContent form = new MultipartFormDataContent();
HttpContent content = new StringContent("fileToUpload");
HttpContent DictionaryItems = new FormUrlEncodedContent(parameters);
form.Add(content, "fileToUpload");
form.Add(DictionaryItems, "medicineOrder");
var stream = PostedPrescription.InputStream;
content = new StreamContent(stream);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "fileToUpload",
FileName = PostedPrescription.FileName
};
form.Add(content);
var response =await client.PostAsync("/api/Payment/AddMedicineOrder", form);
var k =response.Content.ReadAsStringAsync().Result;
How to pass this in Web api Method
[HttpPost]
public async Task<API> AddMedicineOrder()//string key, [FromUri]MedicineOrder medicineOrder
{
var request = HttpContext.Current.Request;
bool SubmittedFile = (request.Files.Count != 0);
this.Request.Headers.TryGetValues("medicineOrder", out IEnumerable<string> somestring);
var k = somestring;
return OK("Success");
}
catch (Exception ex)
{
return InternalServerError("Technical Error.");
}
please help me. Thanks in advance

You need to support add multipart/form-data support to your web api. For this you can add custom media type formatter which will read your json content, as well as file content and you can bind that to a concrete model directly.

Related

How to CREATE POST IN C# to an endpoint on BMC REMEDY API to create a ticket with files submited in form-data?

I have this problem. i have to submit a file (or not) to an endpoint on an API of bmc.
the KEY:entry with the VALUE:data_entry.txt is the json to send with the values, as the same of the body.
The attach-z2AF_WIAttachment1 is the file i want to submit. I'm it's always throuwing some error, or headers invalid, or filetype not valid, but in postman is working.
I cant convert to C#.
this is my code so far, or now.
try
{
//authentication
var dict = new Dictionary<string, string>();
dict.Add("username", "applicationUsernameJonDoe");
dict.Add("password", "applicationPassowrdXPTO");
var clientLogin = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Post, Endpoint_loginITSM) { Content = new FormUrlEncodedContent(dict) };
var res = clientLogin.SendAsync(req); //.Result.ToString();
var body = res.GetAwaiter().GetResult().Content.ReadAsStringAsync();
//pedido de criação de registo
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(10);
var request = new HttpRequestMessage
{
RequestUri = new Uri(Endpoint_CreateITSM),
Method = HttpMethod.Post
};
request.Headers.Add("Authorization", body.Result.ToString());
if (!string.IsNullOrEmpty(registos.Objeto.fileName))
{
registos.Objeto.Registo.z2AF_WIAttachment1 = registos.Objeto.fileName;
}
string json = JsonConvert.SerializeObject(new { values = registos.Objeto });
byte[] file_bytes = System.Convert.FromBase64String(registos.Objeto.fileEncoded);
MemoryStream memoryStream = new MemoryStream();
using (BsonDataWriter writer = new BsonDataWriter(memoryStream))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(writer, registos.Objeto.Registo);
}
var data_entry_bytes = memoryStream.ToArray();
// we need to send a request with multipart/form-data
var multiForm = new MultipartFormDataContent();
ByteArrayContent data_entry_json_content = new ByteArrayContent(data_entry_bytes);
data_entry_json_content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
data_entry_json_content.Headers.ContentDisposition = new ContentDispositionHeaderValue("entry")
{
FileName = "data_entry.txt",
Name = "entry",
};
multiForm.Add(data_entry_json_content);
ByteArrayContent z2AF_WIAttachment1_content = new ByteArrayContent(file_bytes);
z2AF_WIAttachment1_content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
z2AF_WIAttachment1_content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attach-z2AF_WIAttachment1")
{
FileName = registos.Objeto.fileName,
Name = "attach-z2AF_WIAttachment1",
};
multiForm.Add(z2AF_WIAttachment1_content);
request.Content = multiForm;
var result = await client.SendAsync(request);
var resBody = result.Content.ReadAsStringAsync().Result.ToString();//.ConfigureAwait(false);
dynamic _resBody = JsonConvert.DeserializeObject<dynamic>(resBody);
string registoID = _resBody["values"].SysRequestID;
return ResponseHandler<string>.Resposta(false, "resposta api bit criar registos", registoID);
}
}
catch (Exception e)
{
string classname = this.GetType().Name;
CentralLibrary.Services.ErrorLoggingService.ErrorLogsForCore(classname, e, _env.WebRootPath);
return ResponseHandler<string>.Resposta(true, "EXCEPTION : resposta api bit criar registos", e.Message);
}
Here is a better solution.
I had a problem with the last, but for someone who doesnt wnat to use de library RestClient that's the way. But this is working 100% and i have JsonProperty Names for NewtonSoft.Json so this workin with names like
[JsonProperty("z1D Action")]
public string z1D_Action { get; } = "CREATE";
so, my code is, and using an object AbrirRegistosITSM with nested object AbrirRegistosITSM_com_anexo my final solution is
AbrirRegistosITSM _registo = new AbrirRegistosITSM
{
Values = new AbrirRegistosITSM_com_anexo
{
Details = registos.Objeto.Comentario,
Customer_Login = registos.username,
Login_ID = registos.username,
SR_Type_Field_3 = registos.Objeto.Tipologia,
SR_Type_Field_28 = registos.Objeto.Categoria,
z2AF_WIAttachment1 = registos.Objeto.FicheiroNome
}
};
var client = new RestClient(Endpoint_CreateITSM);
string baseFolder = _env.WebRootPath;
string pathDir = Path.Combine(baseFolder, DateTime.Now.ToString().Replace('/', '_').Replace(' ', '_').Replace(':', '_'));
Directory.CreateDirectory(pathDir);
string pathDirFile = Path.Combine(pathDir, registos.Objeto.FicheiroNome);
File.WriteAllBytes(pathDirFile, Convert.FromBase64String(registos.Objeto.FicheiroBase64));
string pathEntryDir = Path.Combine(baseFolder, DateTime.Now.ToString().Replace('/', '_').Replace(' ', '_').Replace(':', '_'));
Directory.CreateDirectory(pathEntryDir);
string patnEntrydirFile = Path.Combine(pathEntryDir, "data_entry.txt");
File.WriteAllText(patnEntrydirFile, JsonConvert.SerializeObject(new { values = _registo.Values }));
var request = new RestRequest();
request.Method = Method.Post;
request.AddHeader("Authorization", token);
request.AddFile("entry", patnEntrydirFile, "application/json");
request.AddFile("attach-z2AF_WIAttachment1", pathDirFile, "application/octet-stream");
var reqbody = JsonConvert.SerializeObject(_registo);
request.AddParameter("application/json", reqbody, ParameterType.RequestBody);
RestResponse response = client.Execute(request);
var respostaBody = response.Content.ToString();//.ConfigureAwait(false);
dynamic _respostaBody = JsonConvert.DeserializeObject<dynamic>(respostaBody);
string _registoID = _respostaBody["values"]["Request Number"];
then i return the request number that what i need, but you have a lot of values there. I use NewtonSoft remember that. I dont use JsonSerializer because i wasn't able to save the json property names with spaces with JsonSerializer.
I'm not entirely sure what's going wrong here. It can be a lot of things, but I might be able to get you going. The last couple of weeks I build a HttpClient that sends a file with metadata to a GraphQL endpoint.
Please ensure the following:
I think you are requesting the file through an call. Please store it in a variable as a Byte[] using the ReadAsByteArrayAsync(). Do note decode it or cast it to a string or anything. You'll just corrupt the file.
var response = client.GetAsync(fileUrl);
var downloadedFile = await response.Result.Content.ReadAsByteArrayAsync();
The following code might not work entirely in your case, but should help you get going building the right request, since I'm also sending metadata in my request containing the file extension and some other information. This will most likely send the file to your API without a file extension.
using (var client = new HttpClient())
{
var file = new byte[] { 1, 2, 3 };
var fileToUpload = new ByteArrayContent(file);
var formData = new MultipartFormDataContent
{
{ fileToUpload, "entry", "passInFileExtensionForExample"},
{ fileToUpload, "attach-z2AF_WIAttachment1", "passInFileExtensionForExample" }
};
var response = await client.PostAsync("endpoint", formData);
}
Add the Bearer token using the following code:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
So i've discover the solution for my problem. I'm gonna to submit only one file. I have to submit also the Json body as a file "entry" "data_entry.txt" and for HttpRequestMessage you have to have a content MultipartFormDataContent and here you can add as many files as you have. i have to convert the Json body to a file ( in this case i converted to binary Array) with the name entry, and the name of the file data_entry.txt, but it's what the endpoint needs, so...whatever.
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(10);
MultipartFormDataContent content = new MultipartFormDataContent();
//adicionar ficheiro
byte[] file_bytes = System.Convert.FromBase64String(registos.Objeto.fileEncoded);
StreamContent fileContent = new StreamContent(new MemoryStream(file_bytes));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "files[attach-z2AF_WIAttachment1]",
FileName = registos.Objeto.fileName
};
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
content.Add(fileContent);
//adicionar ficheiro entry
StreamContent entryStreamContent = new StreamContent(new MemoryStream(ObjectToByteArray(registos.Objeto.Registo)));
entryStreamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "files[entry]",
FileName = "data_entry.txt"
};
entryStreamContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
content.Add(entryStreamContent);
var request = new HttpRequestMessage
{
RequestUri = new Uri(Endpoint_CreateITSM),
Method = HttpMethod.Post,
Content= content
};
request.Headers.Add("Authorization", body.Result.ToString());
string json = JsonConvert.SerializeObject(new { values = registos.Objeto.Registo});
request.Content = new ByteArrayContent(Encoding.UTF8.GetBytes(json));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var resposta = await client.SendAsync(request);
var respostaBody = resposta.Content.ReadAsStringAsync().Result.ToString();//.ConfigureAwait(false);
dynamic _respostaBody = JsonConvert.DeserializeObject<dynamic>(respostaBody);
string _registoID = _respostaBody["values"].SysRequestID;
return ResponseHandler<string>.Resposta(false, "resposta api bit criar registos", _registoID);
So this is my solution. and it's working :)

Not able to return FileStreamResult asp.net core web API

I am writing HttpPost method and using FromBody attribute to send parameters.
[HttpPost]
public IActionResult TransformData([FromBody]IList<Employee> argument)
{
//logic - output stream is built here
return File(output, MediaTypeNames.Application.Xml, "output.xml");
}
From console application , I am trying to consume web API :
ObjectContent data = new ObjectContent(args.GetType(), args, new JsonMediaTypeFormatter());
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://service:8080/");
MediaTypeWithQualityHeaderValue contentType = new MediaTypeWithQualityHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(contentType);
var response = client.PostAsync("api/controller", data);
response.Wait();
var responseContent = await response.Result.Content.ReadAsAsync<FileStreamResult>();
}
responseContent is null. Please help.
var net = new System.Net.WebClient();
var data = net.DownloadData(link);
var content = new System.IO.MemoryStream(data);
you save the content to your computer

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

Post an image with HTTPClient but also some parameters on windows phone

I want to do a MultipartFormDataContent request. But I also want to pass a lot of params with it. When I'm just doing a post I do this:
public async Task<Webservice> inviteMembrs(List<KeyValuePair<string, string>> values)
{
String strUrl = String.Format("http://*****.com/nl/webservice/abc123/members/invite");
var http = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, new Uri(strUrl));
request.Content = new HttpFormUrlEncodedContent(values);
var result = await http.SendRequestAsync(request);
var data = new Webservice { Status = result.StatusCode };
if (result.StatusCode == Windows.Web.Http.HttpStatusCode.Ok && result.Content != null)
{
data.Data = await result.Content.ReadAsStringAsync();
Debug.WriteLine(data.Data);
}
return data;
}
This works perfect. But now I also want to pass an image with it.
I found a lot of examples but always without extra params.
Anyone can help?
Try the following code:
HttpClient httpClient = new HttpClient();
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StringContent(parameter), "name");
content.Add(new StreamContent(stream), "param", "filename");
HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(address, content);

A method was called at an unexpected time in HttpClient MultipartFormDataContent

I have to post the multipart data to the server but I am getting below error
I am using the below code
public async static Task<string> HttpImagePostMethod(byte[] wInputData, string Uri, string path)
{
string result = string.Empty;
try
{
#region For Https (Secure) Api having SSL
var filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted);
var client = new System.Net.Http.HttpClient(new WinRtHttpClientHandler(filter));
#endregion
MultipartFormDataContent requestContent = new MultipartFormDataContent();
// StreamContent content = new StreamContent(wInputData);
var content = new ByteArrayContent(wInputData);
content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
requestContent.Add(content, "file", path);
requestContent.Headers.Add("X-API-Key", UrlFactory.X_API_Key_Value);
requestContent.Add(new StringContent("144"), "type");
HttpResponseMessage aResp = await client.PostAsync(UrlFactory.BaseUrl + Uri, requestContent);
if (aResp.IsSuccessStatusCode)
{
result = await aResp.Content.ReadAsStringAsync();
}
else
{
result = await aResp.Content.ReadAsStringAsync();
}
}
catch (Exception ex)
{
result = string.Empty;
}
return result;
}
I am getting error at this line
HttpResponseMessage aResp = await client.PostAsync(UrlFactory.BaseUrl + Uri, requestContent);
Due to this line
requestContent.Headers.Add("X-API-Key", UrlFactory.X_API_Key_Value);
Myself Answer this question maybe helpful to my other friends...
HttpRequestMessage httpRequest = new HttpRequestMessage();
httpRequest.Method = HttpMethod.Post;
httpRequest.RequestUri = new System.Uri(UrlFactory.BaseUrl + Uri);
httpRequest.Content = requestContent;
httpRequest.Headers.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
httpRequest.Headers.TryAddWithoutValidation("X-API-Key", UrlFactory.X_API_Key_Value);
Client(HttpClient) shouldn't contain any header, we declaring header in HttpRequestMessage
As the error message says, you're trying to set a header on the content but it doesn't belong there; your API token is a property of the request itself and not of its content.
Try adding that header to client.DefaultRequestHeaders instead.

Categories