来自 Ajax 调用的 Asp.Net 核心中的模型绑定

Model Binding in Asp.Net Core from an Ajax call

我有一个 Javascript 函数调用 Asp.Net 核心控制器:

    const details =
    {
        thisModel: {
            Id: '@Model.OrderId',
            Name: '@Model.Name',
            Data: data,
            StringData: ''
        }
    };

    const data = JSON.stringify(details);

    $.ajax({                    
        type: "POST",
        url: "/Orders/CreateOrder",
        data: data,
        datatype: "json",
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            // Success!
        }
    });

我正在尝试调用 Asp.Net 核心控制器方法:

    [HttpPost]
    public async Task<IActionResult> CreateOrder([FromBody]OrderDetails orderDetails)
    {

OrderDetails 模型如下所示:

public class OrderDetails
{
    public string Id { get; set; }
    public string Name { get; set; }
    public IFormFile Data { get; set; }
    public string StringData { get; set; }
}

我遇到的问题是,虽然确实调用了控制器方法,但 orderDetails 中的每个值都是 null。我查看了 at the MS documentation,据我所知,我遵守了所有规则,所以我有点不确定为什么数据没有被传递。有人可以帮忙吗?

由于您的模型中有一个 IFormFile 属性,我了解到您想将文件上传到您的 API。

这里的问题是您无法在 JSON 中上传文件。它是 HTTP 协议的“限制”。要上传文件,您应该使用 FormData

鉴于您已经有了这样的 html 表格:

<form method="post" name="fileinfo">
  <label>Your file:</label>
  <input type="file" name="data" required />
  <input type="submit" value="Upload" />
</form>

那么你应该添加新的隐藏字段来存储 @Model.OrderId@Model.Name:

<form method="post" id="fileUploadForm">
  <input type="hidden" name="OrderId" value="@Model.OrderId" />
  <input type="hidden" name="Name" value="@Model.Name" />
  <label>Your file:</label>
  <input type="file" name="Data" required />
  <input type="submit" value="Upload" />
</form>

现在,在您的 javascript 代码中,您需要将表单输入转换为新的 FormData 变量,然后将其提交给您的 api。最简单的方法是:

var form = $('#fileUploadForm')[0];

var data = new FormData(form);

$.ajax({                    
    type: "POST",
    url: "/Orders/CreateOrder",
    data: data,
    enctype: 'multipart/form-data', // Important!!!!
    processData: false,  //prevent jQuery transforming the data into a query string
    contentType: false,
    cache: false,
    success: function (data) {
        // Success!
    }
});