Aspnetcore: Posting Entity With Child Having IFormFile Property Causes Child To Be Initialized

Created on 29 Mar 2019  路  4Comments  路  Source: dotnet/aspnetcore

Describe the bug

I have a form that creates a ShopProduct, which is a join between a Shop and a Product.

The ShopProduct Create form sends up the ShopId/ProductId/etc. When the ShopProduct is received by the method, the Shop field is null (as expected). This was working fine, until I added this field to Shop:

[JsonIgnore, NotMapped, Display(Name = "Background Image")]
public IFormFile BackgroundImage { get; set; }

Now, despite the actual ShopProduct form not changing at all, the ShopProduct entity received by the Create method has a NON NULL Shop entity - a Shop with all of its values set to their defaults.

This is problematic because this shop isn't null, which means it causes the ModelState to become invalid.

So there seems to be something which is causing entities that have an IFormFile property to initialized where they shouldn't be.

To Reproduce

Use ASP.Net Core 2.2

Expected behavior

The child of a posted entity should be null if it isn't included in the form - regardless of whether the child has an IFormFile input.

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

.NET Core SDK (reflecting any global.json):
 Version:   2.2.103
 Commit:    8edbc2570a

Runtime Environment:

 OS Name:     Windows
 OS Version:  10.0.16299
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.2.103\

Host (useful for support):
  Version: 2.2.1
  Commit:  878dd11e62
area-mvc

Most helpful comment

@DanielStout5 we made a few changes in this area as part of the 3.0 release. I verified that MVC no longer initializes sub-classes with IFormFile unless a value is present.

All 4 comments

As a (rather hacky) workaround, I created this class:

public class IFormFileWrapper
{
    public IFormFile File { get; set; }
}

And then changed the property on Shop like so:

[JsonIgnore, NotMapped]
public IFormFileWrapper BackgroundImage { get; set; }

The ShopProduct.Shop field is now null again, as it should be - but I'd rather not have to use this silly wrapped instead of IFormFile directly!

Thanks for contacting us, @DanielStout5.
The reason for the Shop to be initialized for you is because of how the model binding treats the inner IFormFile property. If a greedy (that's the case here) model binder finds an applicable property in the value graph, it'll automatically initialize the parent object (to it's default value).
@pranavkm, can we investigate why the binding doesn't happen if the IFormFile property is further down in the tree?

It seems to me that the model binder shouldn't be greedy here - there is no value being posted by the form, so I don't understand why it would instantiate it. The Shop.BackgroundImage value itself was null - the form isn't sending up any files.

@DanielStout5 we made a few changes in this area as part of the 3.0 release. I verified that MVC no longer initializes sub-classes with IFormFile unless a value is present.

Was this page helpful?
0 / 5 - 0 ratings