【问题标题】:Values are null when POSTing to Razor Handler via JavaScript fetch()通过 JavaScript fetch() POST 到 Razor 处理程序时,值为 null
【发布时间】:2021-02-03 21:39:36
【问题描述】:

我正在尝试将电子邮件内容发布到 Razor 处理程序,但请求值似乎没有正确绑定。我一直在尽我所能(包括许多关于 SO 的问题)寻找答案,但没有运气。

我从“网络”选项卡中可以看出,该代码正确地发送了数据。我在处理程序中的断点被命中,但请求具有空值。 (我正在运行 .NET Core 3.0,值得。)

我试过了:

  • Content-Type 添加到fetch 标头
  • 在请求参数中添加[FromBody]属性
  • 将正文作为对象发送而不是序列化
  • List<int> 更改为int[]
  • 将我的请求类属性更改为小写、驼峰等,以防我的默认 SerializerSettings 中有不同的 ContractResolver

我的代码和一些截图如下。任何建议/答案表示赞赏。

JS

//sample data
const To = "stack@overflow.com";
const Body = "This is the email body.";
const Subject = "Hello world!";
const PortraitId = 17;
const FileIds = [1,2,3];
const body = { PortraitId, To, Subject, Body, FileIds };

const handler = "SendEmail";
const url = new URL(window.location.href.split('?')[0]);
const parameters = { handler };
url.search = new URLSearchParams(parameters).toString();

await fetch(url, {
  method: "POST",
  body: JSON.stringify(body),
  headers: {
    "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val()
  }
});

C#

public class SendEmailRequest
{
  public int PortraitId { get; set; }
  public string To { get; set; }
  public string Subject { get; set; }
  public string Body { get; set; }
  public List<int> FileIds { get; set; }
}
public async Task<IActionResult> OnPostSendEmail(SendEmailRequest request) {
  //do stuff
}

【问题讨论】:

  • 不是为了让你远离fetch,但你可以使用jQuery $.ajax(...) POST 来测试数据是否被发送到服务器吗?我几乎只将它用于我所有的 POST 调用;发现它更灵活。如果您需要帮助,请告诉我

标签: javascript c# ajax razor fetch


【解决方案1】:

您的代码看起来很正确。尝试在javascript中创建对象如下:

{
  portraitId: 1,
  to: "string",
  subject: "string"
  body: "string"
  fileIds: [1,2]
}

请注意,键是 camelCase 而不是 PascalCase。 另请注意,这种“空对象”错误几乎总是与您将请求发送到后端的方式有关。

IE: 如果您将此对象发送到后端服务器:

{
  portraitId: "string", //notice that I change the data type expected from number to string
  to: "string",
  subject: "string"
  body: "string"
  fileIds: [1,2]
}

整个模型绑定中断,并且您在属性中获得空值。就像控制器说的,“嘿,我只接受THIS 模型,没有其他。我不会妥协”。这很好,因为我们希望确保我们的数据保持某种一致性

【讨论】:

    【解决方案2】:

    因此,模型被作为 null 发送,并且来自 ajax 端的值被很好地传递。我明白了,要初始化您的对象模型,您需要指定对象映射器应该从哪里映射值。在您的情况下,您需要在参数中明确指定 [FromBody] 以及您的对象,以便可以确保这些值将来自 ajax 调用的主体。喜欢:

    public async Task<IActionResult> OnPostSendEmail([FromBody] SendEmailRequest request)
    {
        //do stuff
    }
    

    这将告诉对象映射器从 json 调用中发送的 json 主体映射类型为 SendEmailRequest 的对象,它将直接进入主体并选择相关字段并初始化SendEmailRequest request 具有提供值的对象。

    由于您的浏览器已经将您的请求正文作为JSON,但我希望您明确告诉ajax 调用您发送的数据是json 类型。

    await fetch(url, {
      method: "POST",
      body: JSON.stringify(body),
      headers: {
        "Content-Type": "application/json; charset = utf-8;", // By Adding this header.
        "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val()
      }
    });
    

    正如我所见,您已经尝试了上面建议的更改,所以我想带您回到传统的 ajax 调用。让我知道这是否适合您?

    $.ajax({
        method: 'POST',
        contentType: 'application/json; charset=utf-8;',
        dataType: 'json',
        data: JSON.stringify(body),
        success: function(response){
            console.log(response);
        },
        fail: function(err){
            console.log(err);
        }
    });
    

    【讨论】:

      【解决方案3】:

      好的,所以我复制了它,添加了 [FromBody]"Content-Type": "application/json"

      ([FromBody] SendEmailRequest request)
      

      headers: {
         "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val(),
         "Content-Type": "application/json"
      }
      

      这开始正常工作。因此,如果通过这些修复无法正常工作,请分享您的所有 Middlewares(或身份验证提供程序)。

      【讨论】:

      • 我喜欢这个选项,我通常将 __RequestVerificationToken 添加到模型中,并使用 Newtonsoft 使框架绑定,因为它更易于管理 services.AddControllersWithViews().AddNewtonsoftJson(options=>{...} );
      猜你喜欢
      • 2014-11-19
      • 2019-11-30
      • 2018-12-15
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      • 2019-10-16
      • 1970-01-01
      相关资源
      最近更新 更多