Issue
I am trying to pass a model that contains about 8 properties and an IFormFile property. When I pass the model without the file the request will be okay or otherwise, But when I add the file to the model and try to send it I get an internal server error with this description "Error: Deserialization of interface types is not supported. Type 'Microsoft.AspNetCore.Http.IFormFile'. Path: $.corePhoto | LineNumber: 0 | BytePositionInLine: 173. "
Angular 14:
component sheet:
userForm = this.fb.group({
userName: ['', [ Validators.required, Validators.minLength(8), Validators.maxLength(24)]],
email: ['', [ Validators.required, Validators.email]],
phoneNumber: [''],
passwordHash: ['', [ Validators.required, Validators.pattern('(?=.*[A-Za-z])(?=.*[0-9])( ?=.* [$@$!#^~%*?&,.<>"\'\\;:\{\\\}\\\[\\\]\\\|\\\+\\\-\\\=\\\_\\\)\\\(\\\)\\\`\\\/\\\\\\]])[A-Za-z0-9\d$@].{7,}'),
Validators.minLength(8), Validators.maxLength(16)]],
firstName: ['', [ Validators.minLength(3), Validators.maxLength(24)]],
lastName: ['', [ Validators.minLength(3), Validators.maxLength(24)]],
gender: [true]
}) as FormGroup;
userFormSubmition(files: any){
let fileToUpload = <File>files[0];
const formData = new FormData();
formData.append('file', fileToUpload, fileToUpload.name);
this.userService.createUser(this.userForm.value).subscribe(response => {
service
createUser(userCreation: UserCreation){
return this.http.post(this.url + 'CreateUser', userCreation);
}
Asp.net core 6 web api
Model
public class ApplicationUserCreationDto : ApplicationUserDto
{
[Required]
public string UserName { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
public string PasswordHash { get; set; }
public string PhoneNumber { get; set; }
public IFormFile CorePhoto { get; set; }
}
Controller Method
[HttpPost]
[Route("CreateUser")]
public async Task<IActionResult> CreateUser(ApplicationUserCreationDto userCreationDto)
{
if (ModelState.IsValid)
{
//upload photo
var file = userCreationDto.CorePhoto;
var folderName = Path.Combine("Resources", "Users/Images");
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
if (file.Length > 0)
{
var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName;
var fullPath = Path.Combine(pathToSave, fileName.ToString());
var dbPath = Path.Combine(folderName, fileName.ToString());
using (var stream = new FileStream(fullPath, FileMode.Create))
{
file.CopyTo(stream);
}
}
Solution
In order to do that you need to have both correct API definition and UI request.
- API should look like this (notice that I've added [FromForm] attribute
[ApiController]
[Route("[controller]")]
public class UploadController : Controller
{
[HttpPost]
[Route("CreateUser")]
public async Task<IActionResult> CreateUser([FromForm]ApplicationUserCreationDto userCreationDto)
{
return Json(new
{
user = userCreationDto.UserName,
fileName = userCreationDto.Photo.FileName
});
}
}
public class ApplicationUserCreationDto
{
[Required]
public string UserName { get; set; }
public IFormFile Photo { get; set; }
}
- UI should sent a request with
Content-Type
header equal tomultipart/form-data
value, check it in network. Code probably should look like this
let formData = new FormData();
Object.keys(this.form.controls).forEach(formControlName => {
formData.append(formControlName, this.form.get(formControlName).value);
});
this.http.post('http://localhost:4200/api/trip',formData).subscribe(
(response) =>console.log(response),
(error) =>console.log(error)
)}
Answered By - Lonli-Lokli
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.