Reputation: 921
I am having a hard time figuring out how to send an IFormFile object part of the request. It is an API call to upload an image. I have found a few resources and have tried each suggestion but I always get a 400 Bad Request response when I try and hit the API. Both the API and client are ASP.NET Core 2.1
Call to the API
public async Task<ApiResponse<ImageDto>> AddImageToWebsite(AddImageToWebsiteRequest request)
{
try
{
HttpClient client = new HttpClient();
var url = $"{_apiInfo.Url}/portal/AddImageToWebsite";
byte[] data;
using (var br = new BinaryReader(request.Image.OpenReadStream()))
{
data = br.ReadBytes((int) request.Image.OpenReadStream().Length);
}
var bytes = new ByteArrayContent(data);
MultipartFormDataContent multiContent = new MultipartFormDataContent();
multiContent.Add(bytes, "file", request.Image.FileName);
multiContent.Add(new StringContent(request.WebsiteId.ToString()), "WebsiteId");
multiContent.Add(new StringContent(request.AltText), "AltText");
// BREAKS AFTER THIS POST CALL
var apiResponse = await client.PostAsync(url, multiContent);
// DESERIALIZE RESPONSE TO RESPONSE OBJECT HERE
}
catch (Exception ex)
{
Log.Error(ex, "Error calling api");
return ApiResponse.InternalError<ImageDto>(ex.Message);
}
}
AddImageToWebsiteRequest
public class AddImageToWebsiteRequest
{
public int WebsiteId { get; set; }
public IFormFile Image { get; set; }
public string AltText { get; set; }
}
API CALL
[HttpPost]
[Route("AddImageToWebsite")]
public async Task<JsonResult> AddImageToWebsite(AddImageToWebsiteRequest request)
{
return await this.HandleRequest(async () =>
{
var website = _dataAccess.GetWebsite(request.WebsiteId);
if (website == default(Website))
{
return ApiResponse.NotFound<ImageDto>("Website not found");
}
// UPLOAD IMAGE CODE HERE
}
}
It does not even hit the API call. I also tried posting it as follows, and it worked as long as I did not have an image in the serialized object.
Another Attempt
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var apiResponse = await client.PostAsync(url, stringContent);
// DESERIALIZE RESPONSE TO RESPONSE OBJECT HERE
I have tried so many different recommendations online and none seem to work.
Upvotes: 0
Views: 2529
Reputation: 53
How are you sending this from the view? If you are using a form, you can just give it the multipart/form-data type, give the input type of file and then bind it to the IFormFile in the parameter.
View:
<form id="fileupload" action="yourpath/AddImageToWebsite/" method="POST" enctype="multipart/form-data">
<button type="submit" class="btn btn-primary start">
</button>
<input type="file" name="YourFile"/>
<!--Whatever other things you need to input, use hidden fields-->
</form>
Controller:
[HttpPost]
[Route("AddImageToWebsite")]
public async Task<JsonResult> AddImageToWebsite(IFormFile YourFile)
{
//Do what you need....
}
Upvotes: 0
Reputation: 239290
IFormFile
is only for multipart/form-data
encoded POST requests, i.e. a traditional form post. If you're sending JSON, your "upload" needs to be a Base64 string and you need to bind to a byte[]
:
public class AddImageToWebsiteRequest
{
public int WebsiteId { get; set; }
public byte[] Image { get; set; }
public string AltText { get; set; }
}
JsonConvert.SerializeObject
will automatically convert byte[]
s into Base64 strings.
Upvotes: 3