I'm trying to use IFormFile as a property in a nested ViewModel. I am running into issues trying to bind the ViewModel to the controller action at runtime. The AJAX request stalls and never reaches the action.
This conceptual question is in reference to my specific issue at IFormFile property in .NET Core ViewModel causing stalled AJAX Request
public class ProductViewModel
{
public ProductDTO Product { get; set; }
public List<ProductImageViewModel> Images { get; set; }
}
public class ProductImageViewModel
{
public ProductImageDTO ProductImage { get; set; }
public IFormFile ImageFile { get; set; }
}
[HttpPost]
public IActionResult SaveProduct([FromForm]ProductViewModel model)
{
//save code
}
I am wondering if an IFormFile Property needs to be a direct property of the ViewModel you are binding to a controller action.
The IFormFile Documentation does not seem to answer my question.
The AJAX request stalls and never reaches the action.
This is a known issue that has been fixed in v3.0.0-preview
and won't be merged into 2.2.x
branch. See see #4802.
When posting a form with IList<Something> Something
where Something
has a property of IFormFile
directly, it will result in an infinite loop. Because the model binding happens before the invocation of action method, you'll find that it never enters the action method. Also, if you inspect the Task Manager, you'll find that a crazy memory usage.
To walk around it, as suggested by @WahidBitar, simply create a wrapper on the IFormFile
so that Something
doesn't have a IFormFile
directly .
As for your question itself, change your code as below:
public class ProductViewModel { public ProductDTO Product { get; set; } public List<ProductImageViewModel> Images { get; set; } } public class ProductImageViewModel { public ProductImageDTO ProductImage { get; set; } // since this ProductImageViewModel will be embedded as List<ProductImageViewModel> // make sure it has no IFormFile property directlypublic IFormFile ImageFile { get; set; }public IFormFileWrapper Image{ get; set; } // a dummy wrapper public class IFormFileWrapper { public IFormFile File { get; set;} } }
Now your client side should rename the field name as below:
Images[0].ProductImage.Prop1 # Your DTO prop's
Images[0].Image.File # instead of Images[0].ImageFile
Images[0].ProductImage.Prop2 # Your DTO prop's
Images[1].Image.File # instead of Images[1].ImageFile
... # other images
Product.Prop1
Product.Prop2
... # other props of Product
A Working Demo :
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With