Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

BindingSource for IEnumerable<IFormFile> ApiController parameters on is incorrectly inferred as FromBody #7770

Closed
@futuralogic

Description

@futuralogic

Is this a Bug or Feature request?:

Bug

Steps to reproduce or link to a repro project:

I have a working controller action that receives a List<IFormFile> and defaults to mvc model binding to upload files to a web api endpoint.

See File Uploads MS docs article which I used as a reference. It's largely irrelevant because it's not even getting into the action method due to a model binding failure.

I test the file upload behavior by specifying the version in my csproj <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0-preview1-final"/> and it works.

Modify Version attribute from 2.1.0-preview1-final to 2.1.0-rc1-final and the endpoint is never invoked. Breakpoints are never hit within the action method. Model binding errors are seen in the debug output when I turn up logging in appSettings.

Description of the problem:

I'm using axios ajax lib to upload FormData() to a web api endpoint:

[HttpPost( "photo" )]
  public async Task<IActionResult> SavePhotosToDb( string accountId, List<IFormFile> photos ) {
}

string accountId binds ok, but fails at model binding on the upload field, by turning up logging I get the following from asp.net core:

Connection id "0HLDMU63FETUR", Request id "0HLDMU63FETUR:00000006": started reading request body.
Microsoft.AspNetCore.Server.Kestrel:Debug: Connection id "0HLDMU63FETUR", Request id "0HLDMU63FETUR:00000006": started reading request body.
dbug: Microsoft.AspNetCore.Server.Kestrel[26]
      Connection id "0HLDMU63FETUR", Request id "0HLDMU63FETUR:00000006": done reading request body.
Microsoft.AspNetCore.Server.Kestrel:Debug: Connection id "0HLDMU63FETUR", Request id "0HLDMU63FETUR:00000006": done reading request body.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[22]
      Attempting to bind parameter 'accountId' of type 'System.String' ...
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder:Debug: Attempting to bind parameter 'accountId' of type 'System.String' ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder[24]
      Attempting to bind model of type 'System.String' using the name 'accountId' in request data ...
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder:Debug: Attempting to bind model of type 'System.String' using the name 'accountId' in request data ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder[25]
      Done attempting to bind model of type 'System.String' using the name 'accountId'.
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder:Debug: Done attempting to bind model of type 'System.String' using the name 'accountId'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[23]
      Done attempting to bind parameter 'accountId' of type 'System.String'.
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder:Debug: Done attempting to bind parameter 'accountId' of type 'System.String'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[22]
      Attempting to bind parameter 'photos' of type 'System.Collections.Generic.List`1[Microsoft.AspNetCore.Http.IFormFile]' ...
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder:Debug: Attempting to bind parameter 'photos' of type 'System.Collections.Generic.List`1[Microsoft.AspNetCore.Http.IFormFile]' ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[24]
      Attempting to bind model of type 'System.Collections.Generic.List`1[Microsoft.AspNetCore.Http.IFormFile]' using the name '' in request data ...
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder:Debug: Attempting to bind model of type 'System.Collections.Generic.List`1[Microsoft.AspNetCore.Http.IFormFile]' using the name '' in request data ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[2]
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder:Debug: Rejected input formatter 'Microsoft.AspNetCore.Mvc.Formatters.JsonPatchInputFormatter' for content type 'multipart/form-data; boundary=----WebKitFormBoundaryeuzzmB6yYXHml0Rh'.
      Rejected input formatter 'Microsoft.AspNetCore.Mvc.Formatters.JsonPatchInputFormatter' for content type 'multipart/form-data; boundary=----WebKitFormBoundaryeuzzmB6yYXHml0Rh'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[2]
      Rejected input formatter 'Microsoft.AspNetCore.Mvc.Formatters.JsonInputFormatter' for content type 'multipart/form-data; boundary=----WebKitFormBoundaryeuzzmB6yYXHml0Rh'.
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder:Debug: Rejected input formatter 'Microsoft.AspNetCore.Mvc.Formatters.JsonInputFormatter' for content type 'multipart/form-data; boundary=----WebKitFormBoundaryeuzzmB6yYXHml0Rh'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[3]
      No input formatter was found to support the content type 'multipart/form-data; boundary=----WebKitFormBoundaryeuzzmB6yYXHml0Rh' for use with the [FromBody] attribute.
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder:Debug: No input formatter was found to support the content type 'multipart/form-data; boundary=----WebKitFormBoundaryeuzzmB6yYXHml0Rh' for use with the [FromBody] attribute.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[4]
      To use model binding, remove the [FromBody] attribute from the property or parameter named '' with model type 'System.Collections.Generic.List`1[[Microsoft.AspNetCore.Http.IFormFile, Microsoft.AspNetCore.Http.Features, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]]'.
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder:Debug: To use model binding, remove the [FromBody] attribute from the property or parameter named '' with model type 'System.Collections.Generic.List`1[[Microsoft.AspNetCore.Http.IFormFile, Microsoft.AspNetCore.Http.Features, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]]'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder[25]
      Done attempting to bind model of type 'System.Collections.Generic.List`1[Microsoft.AspNetCore.Http.IFormFile]' using the name ''.
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder:Debug: Done attempting to bind model of type 'System.Collections.Generic.List`1[Microsoft.AspNetCore.Http.IFormFile]' using the name ''.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[23]
      Done attempting to bind parameter 'photos' of type 'System.Collections.Generic.List`1[Microsoft.AspNetCore.Http.IFormFile]'.
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder:Debug: Done attempting to bind parameter 'photos' of type 'System.Collections.Generic.List`1[Microsoft.AspNetCore.Http.IFormFile]'.
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter[1]
      The request has model state errors, returning an error response.
Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter:Debug: The request has model state errors, returning an error response.
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Request was short circuited at action filter 'Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Debug: Request was short circuited at action filter 'Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter'.

I don't have [FromBody] attributed to the photos parameter. I have my controller decorated with:

[ApiController]
[Route( "api/v1/[controller]/{accountId}" )]
public class ProfileController : Controller { 
  // where the magic happens
}

I haven't made any client-side changes with vue.js + axios, only upgraded project to use dotnet core
2.1 RC1. I followed ASP.Net core blog post for guidance on migration, which didn't touch the api controller or my client-side code.

To add, I hadn't made any changes to client-side before the issue surfaced, only framework versions. While debugging/researching, I did try changing my default header on axios where I default send Content-Type as application/json, but modifying that didn't seem to affect anything, and from the model binding errors it appears asp.net is still understanding we're posting multi-part form data.

If I switch between version specifiers, then dotnet clean, dotnet restore, and F5 in VS Code - it works under preview1.

dotnet --info:

.NET Core SDK (reflecting any global.json):
 Version:   2.1.300-rc1-008673
 Commit:    f5e3ddbe73

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  10.12
 OS Platform: Darwin
 RID:         osx.10.12-x64
 Base Path:   /usr/local/share/dotnet/sdk/2.1.300-rc1-008673/

Host (useful for support):
  Version: 2.1.0-rc1
  Commit:  eb9bc92051

.NET Core SDKs installed:
  2.0.0 [/usr/local/share/dotnet/sdk]
  2.1.300-preview1-008174 [/usr/local/share/dotnet/sdk]
  2.1.300-rc1-008673 [/usr/local/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0-preview1-final [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.0-rc1-final [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0-preview1-final [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.0-rc1-final [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.0.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0-preview1-26216-03 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0-rc1 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

Version of Microsoft.AspNetCore.Mvc or Microsoft.AspNetCore.App or Microsoft.AspNetCore.All:

2.1.0-preview1-final
2.1.0-rc1-final

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions