WebAPI核心IFormFile始终显示为null

时间:2017-11-07 18:48:32

标签: c# angular asp.net-web-api asp.net-core

我在ASP.NET Core WebAPI中有一个角度为4的前端和一个后端,它们的功能是,将一个人的数据和简历发送到一个数据库,即SQL Server,但是。 ..始终捕获数据并将文件发送到数据库的方法的IFormFile为空。

我已经尝试过在互联网上找到的所有类型的解决方案,但它们都不适用于我。

作为Post方法的响应我收到此异常

<form class="col-md-6 offset-md-3" method="POST" enctype="multipart/form-data" #form="ngForm" (ngSubmit)="onSubmit(form)">
  <div class="form-group row">
    <label for="name" class="col-sm-2 col-form-label">Name</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" placeholder="Nome completo" id="name"  name="name" ngModel />
    </div>
  </div>
  <div class="form-group row">
    <label for="email" class="col-sm-2 col-form-label">Email</label>
    <div class="col-sm-10">
      <input type="email" class="form-control" id="email" placeholder="Email" name="email" ngModel />
      <small id="emailHelp" class="form-text text-muted">
        We'll never share your email with anyone else.
      </small>
    </div>
  </div>
  <div class="form-group row">
    <label for="country" class="col-sm-2 col-form-label">Country</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="country" placeholder="Country" name="country" ngModel />
    </div>
  </div>
  <div class="form-group row">
    <label for="state" class="col-sm-2 col-form-label">State</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="state" placeholder="Estado" name="state" ngModel />
    </div>
  </div>
  <div class="form-group row">
    <label for="city" class="col-sm-2 col-form-label">City</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="city" placeholder="Cidade" name="city" ngModel />
    </div>
  </div>
  <div class="form-group row">
    <label for="file" class="col-sm-2 col-form-label">Curriculum</label>
    <div class="col-sm-10">
        <input type="file" id="file" name="file" ngModel />
    </div>
  </div>
  <div class="container text-center">
    <button type="submit" class="btn btn-outline-dark">Submit</button>
  </div>
</form>

在这里,我粘贴了执行此操作的项目代码的部分内容。

完整代码的github链接:
front-end code
back-end code

HTML

onSubmit(form: NgForm) {
  const { file } = form.value;
  delete form.value.file;

  var data = new FormData();
  data.append('Candidates', JSON.stringify(form.value));
  data.append('file', file);

  console.log(form.value);
  console.log(file);

  const headers = new Headers();
  headers.append('Access-Control-Allow-Origin', '*');

  const options = new RequestOptions({headers: headers});

  this.http.post("http://localhost:54392/api/candidates", data, options)
    .subscribe(
      data => {
        console.log("Foi");
      },
      error => {
        console.log("Não foi");
      });
}

Angular 4

[HttpPost("candidates")]
public async Task<IActionResult> Post(IFormFile file)
{
    var json = HttpContext.Request.Form["Candidates"];      
    var jsonTextReader = new JsonTextReader(new StringReader(json));
    var candidate = new JsonSerializer().Deserialize<Candidate>(jsonTextReader);

    if (!ModelState.IsValid) 
        return BadRequest();

    using (var memoryStream = new MemoryStream())
    {
        await file.OpenReadStream().CopyToAsync(memoryStream);
        candidate.CurriculumVitae = memoryStream.ToArray();
    }
    await dataBase.AddAsync(candidate);
    dataBase.SaveChanges();
    return Ok(candidate);
}

C#

{{1}}

3 个答案:

答案 0 :(得分:3)

Upload images in Angular 4 without a plugin提供了您尝试实现的流程的演练。它使用@ViewChild来获取对DOM中文件输入的引用,然后在构建FormData时使用它。在您的方案中,这涉及一些更改,如下所示:

  1. 使用ngModel替换HTML中文件输入的#file。这会创建template reference variable,在下一步使用@ViewChild时,可以在组件内部访问。
  2. @ViewChild('file') fileInput;添加到构造函数上方的组件中。这会将#file模板引用变量链接到您的组件代码。
  3. 从组件中删除以下代码:

    const { file } = form.value;
    delete form.value.file;
    

    此时file属性将不再存在,因此无需删除任何内容。

  4. data.append('file', file);替换为以下内容:

    let fileBrowser = this.fileInput.nativeElement;
    if (fileBrowser.files && fileBrowser.files[0]) {
        data.append("file", fileBrowser.files[0]);
    }
    

    最后一段代码会抓取文件的句柄并将其附加到FormData

  5. 您可以根据需要为变量和模板引用变量命名。唯一需要具体的是file 中使用的字符串值data.append必须匹配用于C#IFormFile变量的变量名称。

    另外,您还可以删除自定义HeadersRequestOptions作为设置Access-Control-Allow-Origin,因为请求标头在此处不执行任何操作。应在服务器的响应中设置此标头。

答案 1 :(得分:1)

添加[FromBody]属性。您可以在此处阅读更多内容:Binding formatted data from the request body

public async Task<IActionResult> Post(IFormFile file)更改为public async Task<IActionResult> Post([FromBody] IFormFile file)

答案 2 :(得分:1)

我之前有这个问题,已通过删除得到解决。 “内容类型”,“ application / json; charset = utf-8'

此外,您还需要确保在客户端和服务器上发送和接收的参数相同