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

如何通过.NET在Angular与Cosmos DB之间传输无类纯JSON数据

问题根因

你遇到的报错本质是JSON序列化库不兼容:
当前Cosmos DB .NET SDK默认使用Newtonsoft.Json做序列化,你调用ReadItemAsync<dynamic>返回的response.Resource实际是Newtonsoft.Json.Linq.JObject类型,而ASP.NET Core 3.0+默认使用System.Text.Json作为输出序列化器,没有内置对Newtonsoft的JObject类型的支持,因此触发了NotSupportedException异常。

你尝试使用JsonDocument失败的原因是JsonDocument没有公共无参构造函数,Cosmos SDK反序列化时无法构造该类型的实例。

最优解决方案:直接透传原始JSON流

不需要做任何序列化/反序列化操作,完全实现你的"透传通道"需求,性能最高,也不需要定义任何业务类:

查询数据实现

直接调用Cosmos SDK的流读取API,拿到原始JSON流后直接返回给前端:

public async Task<IActionResult> GetItemAsync(string id)
{
    try
    {
        // 直接读取原始JSON流,不做反序列化
        using var response = await _container.ReadItemStreamAsync(id, new PartitionKey(id));
        if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
        {
            return NotFound();
        }
        // 直接返回流,设置正确的Content-Type
        return File(response.Content, "application/json");
    }
    catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
    {
        return NotFound();
    }
}

写入数据实现

前端提交的JSON不需要反序列化,直接读取请求体流写入Cosmos:

public async Task<IActionResult> UpsertItemAsync(string id)
{
    using var requestStream = Request.Body;
    using var response = await _container.UpsertItemStreamAsync(requestStream, new PartitionKey(id));
    
    if (response.IsSuccessStatusCode)
    {
        return NoContent();
    }
    return StatusCode((int)response.StatusCode);
}

提示:该方案会原封不动返回Cosmos DB内置的系统字段(如_etag/_ts/_rid等),如果需要过滤这些字段,可以使用下面的备选方案。

备选方案1:统一序列化库为Newtonsoft.Json

让ASP.NET Core使用Newtonsoft.Json作为输出序列化器,兼容Cosmos SDK返回的JObject类型:

  1. 安装NuGet包:Microsoft.AspNetCore.Mvc.NewtonsoftJson
  2. 在Program.cs中注册控制器时配置:
builder.Services.AddControllers()
    .AddNewtonsoftJson();

配置完成后你之前用dynamic的代码可以直接正常运行。

备选方案2:配置Cosmos SDK使用System.Text.Json序列化

让Cosmos SDK改用ASP.NET Core默认的System.Text.Json做序列化,避免类型不兼容问题:

  1. 安装NuGet包:Microsoft.Azure.Cosmos.Serialization.SystemTextJson
  2. 初始化CosmosClient时配置序列化器:
var cosmosClient = new CosmosClient("你的Cosmos连接串", new CosmosClientOptions
{
    Serializer = new SystemTextJsonCosmosSerializer(new JsonSerializerOptions
    {
        PropertyNameCaseInsensitive = true
    })
});
  1. 调整查询代码,使用JsonElement作为泛型参数:
public async Task<IActionResult> GetItemAsync(string id)
{
    try
    {
        var response = await _container.ReadItemAsync<JsonElement>(id, new PartitionKey(id));
        return Ok(response.Resource);
    }
    catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
    {
        return NotFound();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:09:00