繁体   English   中英

将表单数据从 React 发送到 ASP.NET Core API

[英]Send form data from React to ASP.NET Core API

我编辑了整个问题,因为它很长而且令人困惑。

清晰简洁的新问题

我将表单中的所有数据作为字符串化 JSON 发送,但现在我需要附加一个文件,所以我不能再这样做了。 如何以允许附加文件的格式将表单数据从 React 发送到 ASP.NET Core API?

老问题

我有几种工作正常的表单:我使用 React 中的 fetch 发送数据,并在我的 ASP.NET Core API 中正确接收它作为正文。

但是,我现在需要发送文件,而且我不知道如何附加它们,因为我只是将我的所有内容都发送到一个精简的 JSON 中。

fetch("localhost/api/test", {
    method: 'POST',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(body)
}).then(result => result.json()).then(
    (result) => {
        console.log(result);
    }
);

我尝试发送这样构建的 FormData 对象而不是JSON.stringify(body)

let formData = new FormData();
for (var property in body) {
    formData.append(property, body[property]);
}

但是当我发送这个对象而不是字符串化的 JSON 时,对于 ASP.NET Core 中的所有值,我总是得到 null。

我也试过发送这个:

URLSearchParams(data)

和这个:

let formBody = [];
for (var property in details) {
    var encodedKey = encodeURIComponent(property);
    var encodedValue = encodeURIComponent(details[property]);
    formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

我尝试了每种类型的数据编码的不同标头组合:

  • 没有标题
  • 'Content-Type': 'multipart/formdata'
  • 'Content-Type': 'application/json'
  • 'Content-Type': 'application/x-www-form-urlencoded'

我还尝试使用[FromBody][FromForm]从 ASP.NET 获取数据。

我想我已经尝试了上面解释过的所有选项的所有可能组合,但没有结果。 我总是在我的 API 中得到空值。

编辑:

现在,我什至没有尝试发送文件。 在尝试附加文件之前,我正在尝试以正确的格式成功发送通用数据。 我不知道我是否应该更改问题的标题。

这是我的 API 代码:

[HttpPost]
[Route("login")]
public object Login([FromBody] Credentials cred)
{
    // check credentials
    return CustomResult.Ok;
}

Credentials

public class Credentials
{
    public string Username { get; set; }
    public string Password { get; set; }
}

React 的对象body如下所示:

{
    username: "user",
    password: "pass"
}

现在还有一点时间。 (捕获了 10 条鱼。)我从您的代码中注意到您使用了标题“multipart/formdata”,它应该有一个连字符; “多部分/表单数据”。

在我的 API 上,我指定它使用相同的类型: [Consumes("multipart/form-data")]

我不清楚 .net 核心默认值是什么以及它是否应该自动反序列化表单数据,但指定它应该排除任何歧义。

使用我的代码,我正在发送一个带有一些参数的文件。 在 api 方面,它看起来像:

    public class FileUpload_Single
    {
        public IFormFile DataFile { get; set; }
        public string Params { get; set; }
    }

    // POST: api/Company (Create New)
    [HttpPost]
    [Authorize(PermissionItem.SimulationData, PermissionAction.Post)]
    [RequestSizeLimit(1024L * 1024L * 1024L)]  // 1 Gb
    [RequestFormLimits(MultipartBodyLengthLimit = 1024L * 1024L * 1024L)] // 1 Gb
    [Consumes("multipart/form-data")]
    public async virtual Task<IActionResult> Post([FromForm] FileUpload_Single data)

....然后在客户端它看起来像:

  let formData = new FormData();
  formData.append("DataFile", file);
  formData.append("Params", JSON.stringify(params));
  fetch(apicall, {
    method: "POST",
    mode: "cors",
    headers: {
      Authorization:
        "Bearer " + (localStorage.getItem("token") || "").replace(/['"]+/g, ""),
      Accept: "multipart/form-data",
    },
    body: formData,
  })

文件来自

  const changeHandler = (event) => {
    setSelectedFile(event.target.files[0]);
    setIsSelected(true);
  };

(来自我的 React 组件)

我的整个问题都是一团糟,就我而言,问题在于for循环。 但是,我将尝试清楚地解释我需要什么,因为网上有很多关于如何使用 React 将表单提交到 API 的误导性信息。

解决方案

后端

在后端,接受 POST 请求并使用FromForm获取数据。 如果您需要使用凭据,最好通过标题传递它们,而不是将它们作为隐藏输入放在每个表单中。

[HttpPost]
[Route("test")]
public object Test([FromHeader] string token, [FromForm] MyDataClass data)
{
    // check token
    // do something with data
    return CustomResult.Ok;
}

如果绑定对象,则属性必须与从前端发送的属性名称相同,并且必须具有公共 setter

public class MyDataClass
{
    public string SomeInfo { get; set; }
    public string SomeOtherInfo { get; set; }
}

前端

将数据作为FormData发送。 为此,您可以按照本教程进行操作。 这样,您无需担心在提交数据之前处理输入更改和格式化数据。

但是,如果您的数据已经在纯 JavaScript 对象中,您可以将其转换为FormData ,如下所示。

let formData = new FormData();
Object.keys(data).forEach(function (key) {
    formData.append(key, data[key]);
});

尽管如此,这是非常基本的,如果您有一个复杂的对象(包含数组、嵌套对象等),您将需要以不同的方式处理它。

最后,我使用fetch来调用我的 API。 如果您使用它,请务必不要设置Content-Type标头,因为您将覆盖fetch自动为您选择的标头,在大多数情况下这将是正确的标头。

fetch("localhost/api/test", {
    method: 'POST',
    headers: {
        'Token': "dummy-token"
        // DON'T overwrite Content-Type header
    },
    body: formData
}).then(result => result.json()).then(
    (result) => {
        console.log(result);
    }
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM