I am trying to pass an img file from a frontend written in React/Typescript to an API written in C#.
These are the functions that handle uploading a photo and the upload of the state to the C# API, using Axios:
const handleImageUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = event.target.files as FileList
const file = files[0] as File
setRecipeData((prev) => {
return {...prev, RecipePhoto: file}
})
}
const handleRecipeUpload = () => {
axios.post('https://localhost:7104/api/Recipe/Post', recipeData)
.then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error)
console.log(JSON.stringify(error.response.data.errors));
})
}
Here is my controller in C#
[HttpPost]
[Route("Post")]
public async Task<IActionResult> PostRecipeAsync(PostRecipeDto postRecipeDto)
{
return Ok(await _postRecipeServices.PostRecipeService(postRecipeDto));
}
And the model for the Dto:
public class PostRecipeDto
{
public string? Name { get; set; }
public string? Description { get; set; }
public string? Country { get; set; }
public string? IngridientList { get; set; }
public int CookingTimeInMins { get; set; }
public byte[]? RecipePhoto { get; set; }
}
The error that I am getting in browser console, while trying to upload is:
{"postRecipeDto":["The postRecipeDto field is required."],"$.RecipePhoto":["The JSON value could not be converted to System.Byte[]. Path: $.RecipePhoto | LineNumber: 0 | BytePositionInLine: 155."]}
So I guess, I am either passing the file in a wrong way or the model is incorrect and shouldn't be byte[].
I would greatly appeciate any advice on what would be the optimal way to fix this!
CodePudding user response:
You can change your handleRecipeUpload
method to something like below
const handleRecipeUpload = () => {
const formData = new FormData();
formData.append('RecipePhoto', recipeData.RecipePhoto);
// append all other properties of `recipeData`
.
.
.
const config = {
headers: {
'content-type': 'multipart/form-data',
},
};
axios.post('https://localhost:7104/api/Recipe/Post', formData, config)
.then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error)
console.log(JSON.stringify(error.response.data.errors));
})
}
On the C# side change class PostRecipeDto
as below --
public class PostRecipeDto
{
public string? Name { get; set; }
public string? Description { get; set; }
public string? Country { get; set; }
public string? IngridientList { get; set; }
public int CookingTimeInMins { get; set; }
public IFormFile? RecipePhoto { get; set; }
}
And to get bytes from IFormFile you can reference the below link --
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.iformfile?view=aspnetcore-6.0