You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Azure Function时PostAsJsonAsync请求体丢失问题排查

问题场景与疑问

我定义了如下测试Azure Function端点:

public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "projects")] HttpRequestData req)
{
    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    if (string.IsNullOrWhiteSpace(requestBody))
    {
        // 返回错误请求
    }
    
    // 执行其他操作
}

在NUnit运行的客户端应用中,调用以下代码会返回错误请求:

var dtoClient = new DtoClient(p1, p2, etc);
var response = await _httpClient.PostAsJsonAsync("api/MyAzureFunctionPath", dtoClient);

但调用以下代码则能成功:

var dtoClient = new DtoClient(p1, p2, etc);
var content = new StringContent(JsonConvert.SerializeObject(dtoClient), System.Text.Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("api/copilot/projects", content);

疑问:

  • PostAsJsonAsync 是否存在问题?为何在微软生态中无法正常工作?
  • 有资料称这是因为HttpClient将内容大小设为0导致的,这是bug吗?
  • 我应该直接避免使用PostAsJsonAsync还是学习正确的使用方式?

问题原因与解决方案

核心原因:序列化库行为差异

PostAsJsonAsync 默认使用System.Text.Json做序列化,而你手动写的代码用的是Newtonsoft.Json(Json.NET)。两者的序列化规则有明显差异:

  • 如果DtoClient类里有System.Text.Json默认忽略的属性(比如非公开字段、只加了Newtonsoft版[JsonIgnore]的属性,或者类型处理逻辑不同),会导致序列化后的内容为空或不完整,被Azure Function的空白请求校验拦截。
  • 另一种可能是DtoClient实例用System.Text.Json序列化后生成了空JSON(比如所有属性都是默认值且被配置为忽略),直接导致请求体为空。

关于“内容大小设为0”的说法

这不是HttpClient的bug,本质是序列化结果为空导致的。当System.Text.Json无法正确序列化对象时,会生成空内容,此时请求体大小自然为0,触发你Azure Function里的错误请求逻辑。

正确使用方式(无需弃用PostAsJsonAsync)

你可以通过以下方式让它正常工作:

  1. 统一序列化库:
    • 若继续用System.Text.Json,检查DtoClient的序列化配置:确保需要序列化的属性是公开的,没有被System.Text.Json的[JsonIgnore]标记,或者手动配置序列化选项包含所需内容。
    • 或者给HttpClient扩展一个基于Newtonsoft.Json的PostAsJsonAsync方法,内部逻辑和你手动实现的一致——用JsonConvert.SerializeObject生成JSON后包装成StringContent。
  2. 核对请求路径:注意到你两次调用的路径不同(api/MyAzureFunctionPath vs api/copilot/projects),确认PostAsJsonAsync用的路径是否正确指向Azure Function的projects路由(不过你的情况是返回错误请求,更大概率是序列化问题)。
  3. 调试序列化结果:在客户端提前用System.Text.Json序列化dtoClient,看看结果是否为空或不符合预期:
    var json = System.Text.Json.JsonSerializer.Serialize(dtoClient);
    // 输出json查看内容是否正常
    

总结

PostAsJsonAsync本身没有问题,问题出在序列化库的差异或对象的序列化配置上。不需要弃用它,只要统一序列化规则或调整对象的序列化配置就能解决问题。

内容的提问来源于stack exchange,提问作者Ama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:50:17