C# 在asp.net core 2.1中,文件始终返回null

C# 在asp.net core 2.1中,文件始终返回null,c#,asp.net,asp.net-web-api,asp.net-core,asp.net-core-webapi,C#,Asp.net,Asp.net Web Api,Asp.net Core,Asp.net Core Webapi,Api方法如下所示 [HttpPost] public async Task<BaseListResponse<MediaStorageModel>> MediaBrand(IFormFile file, int brandId) { var files = new List<IFormFile>(); files.Add(file); var response = await this

Api方法如下所示

    [HttpPost]
    public async Task<BaseListResponse<MediaStorageModel>> MediaBrand(IFormFile file, int brandId)
    {
        var files = new List<IFormFile>();
        files.Add(file);

        var response = await this.Upload(files, "brand", brandId);

        return response;
    }
[HttpPost]
公共异步任务MediaBrand(IFormFile文件,int brandId)
{
var files=新列表();
文件。添加(文件);
var response=wait this.Upload(文件“brand”,brandId);
返回响应;
}
我的邮递员配置

将我的dotnet core从2.0升级到2.1,这样就无法工作了,有人能帮忙吗。
出了什么问题

我找到了一个解决办法,可以让它正常工作:

在控制器操作上使用
HttpPut
而不是
HttPost


我也对这种行为感到惊讶。如果有人能解释为什么它解决了这个问题,这将对我有所帮助。

将您的方法参数更改为采用下面的模型并添加[FromForm],它应该可以工作

public class FileUploadViewModel
{
    public IFormFile File { get; set; }
    public int BrandId { get; set; }
}

public async Task<BaseListResponse<MediaStorageModel>> MediaBrand([FromForm] FileUploadViewModel viewModel)
公共类FileUploadViewModel { 公共文件{get;set;} public int BrandId{get;set;} } 公共异步任务MediaBrand([FromForm]FileUploadViewModel viewModel)
我也遇到了同样的问题,我能够通过将'Name'命名参数应用于表单中具有文件字段名称的FromForm属性来解决这个问题。它指定表单中要绑定到方法参数的字段。如图所示更改方法签名

[HttpPost("status")]
public async Task<BaseListResponse<MediaStorageModel>> MediaBrand([FromForm(Name ="file")] IFormFile file, int brandId)
[HttpPost(“状态”)]
公共异步任务MediaBrand([FromForm(Name=“file”)]ifformfile文件,int brandId)

下面的代码应该可以工作

[HttpPost]
public async Task<BaseListResponse<MediaStorageModel>> MediaBrand([FromQuery] int brandId, IFormFile file)
{
    var files = new List<IFormFile>();
    files.Add(file);

    var response = await this.Upload(files, "brand", brandId);

    return response;
}
[HttpPost]
公共异步任务MediaBrand([FromQuery]int brandId,IFormFile)
{
var files=新列表();
文件。添加(文件);
var response=wait this.Upload(文件“brand”,brandId);
返回响应;
}
在您的表单中使用


enctype=“multipart/form data”

更新[FromForm]属性,并且不将参数放入头中,密钥的put名称是file和brandId

我测试过了,没问题


确保表单类型正确

<form asp-action="Edit" enctype="multipart/form-data">

我还必须根据生成的代码更改模型绑定的工作方式:

public async Task<IActionResult> Edit([Bind("Text,Example")] Example example)
公共异步任务编辑([Bind(“Text,Example”)]示例)
根据本守则:

public async Task<IActionResult> Edit(Example example)
公共异步任务编辑(示例)
将(Name=“body”)添加到from表单对我有效

服务器调用

[HttpPost]
  [Route("UploadImage")]

public IActionResult UploadImage([FromForm(Name = "body")]IFormFile formData)
let formData = new FormData();
formData.append('body', event.target.files[0]);

const config = {
  headers: {
  'content-type': 'multipart/form-data',
  },
}

axios.post(ApiURL,formData, config);
客户端代码

[HttpPost]
  [Route("UploadImage")]

public IActionResult UploadImage([FromForm(Name = "body")]IFormFile formData)
let formData = new FormData();
formData.append('body', event.target.files[0]);

const config = {
  headers: {
  'content-type': 'multipart/form-data',
  },
}

axios.post(ApiURL,formData, config);

如果使用javascript和FormData对象,则需要将每个文件的名称设置为“文件”

this.files.forEach((f) => {
         formData.append("files", f, `${this.path}/${f.name}`);
      }); 
如果在帖子中使用其他名称,则需要在post方法的属性中设置它

formData.append("someName", f, `${this.path}/${f.name}`);

 public async Task<IActionResult> Post([FromForm(Name ="someName")] List<IFormFile> files)

在我的例子中,我有一个angular 6应用程序,它使用一个定制的HttpInterceptor,在发送到api之前向每个Http请求添加内容类型为“application/json”的标记。 像下面这样。删除带有“内容类型”的行:
application/json
。没有这一点,这里的任何解决方案都不起作用。NETCore现在更聪明,可以将您发送到api的任何对象转换为与您在angular中为该对象创建的模型相匹配的对象

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class JwtHttpInterceptor implements HttpInterceptor {
  constructor() {}
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = localStorage.getItem('token');
      let clone: HttpRequest<any>;
      if (token) {
        clone = request.clone({
          setHeaders: {
            Accept: `application/json`,
            'Content-Type': `application/json`,
            Authorization: `Bearer ${token}`
          }
        });
从'@angular/common/http'导入{HttpEvent,HttpHandler,HttpInterceptor,HttpRequest};
从“@angular/core”导入{Injectable};
从“rxjs/Observable”导入{Observable};
@可注射()
导出类JwtHttpInterceptor实现HttpInterceptor{
构造函数(){}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
const token=localStorage.getItem('token');
让克隆:HttpRequest;
如果(令牌){
clone=request.clone({
集合标题:{
接受:`application/json`,
'内容类型':'application/json`,
授权:`Bearer${token}`
}
});

在我的例子中,它在net core中的工作方式如下

控制器:

[HttpPost]
public IActionResult ReadFormFile([FromForm]IFormFile miCsv)
{


}
请求正文:用作与参数同名

请求头:用作内容类型:多部分/表单数据;边界=xxxxxxxxxx 边界可以是任何值


您的控制器是否用
[ApiController]
属性装饰?该属性将默认绑定源从
表单
切换到
表单
,因此如果您需要实际接受
多部分/表单数据
x-www-urleconded
请求主体,则需要添加
[FromForm]
添加到参数中。即使将FromForm属性添加到模型参数中,我的IFileInfo仍然会得到一个空值,而我可以在Request.Form.Files列表中看到该文件……这些文件对我都不起作用。我只是尝试了
[FromForm(Name=”“)]IFormFile文件
属性,它对我有效。宾果。表单需要如下所示:这对我也有效。