使用 .NET 在 Angular 和 Cosmos DB 之间传递 "pure"(class-less)json

Passing "pure" (class-less) json between Angular and Cosmos DB with .NET

我在 Cosmos DB 中有 json 数据,我想将其传送到 angular 应用程序。 angular 应用程序可以处理各种 json 结构并允许用户修改数据并推送回 Cosmos(通过 API - 见下文)。

我正在尝试构建一个简单的 C# API,它将仅用于从 Cosmos 查询数据并将“原始”json 推送回 angular,而无需为我正在存储的每种类型的 json 对象创建 classes。 API 只是将数据从 Cosmos 传递到 Angular 并将数据从 Angular.

推回 Cosmos 的机制

我还没有找到一种简单的方法来执行此操作,因为所有方法似乎都需要一个结构化的 class 对象来从 Cosmos 检索数据并将其保存回来。

有什么实现方法的建议吗?

-- 编辑--

这是我在动态中使用的一些示例代码,它在检索数据方面有效,但它不会在中间件中序列化为 Json(请参阅下面的例外情况)。

 public async Task<dynamic> GetItemAsync(string id)
{
  try
  {
    var response = await this._container.ReadItemAsync<dynamic>(id, new PartitionKey(id));
    return response.Resource;
  }
  catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
  {
    return null;
  }

}

[15:12:25 ERR] An unhandled exception has occurred while executing the request. <s:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware> System.NotSupportedException: The collection type 'Newtonsoft.Json.Linq.JObject' is not supported. at System.Text.Json.JsonPropertyInfoNotNullable`4.GetDictionaryKeyAndValueFromGenericDictionary(WriteStackFrame& writeStackFrame, String& key, Object& value) at System.Text.Json.JsonPropertyInfo.GetDictionaryKeyAndValue(WriteStackFrame& writeStackFrame, String& key, Object& value) at System.Text.Json.JsonSerializer.HandleDictionary(JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, WriteStack& state) at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state) at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken) at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|21_0(ResourceInvoker invoker, IActionResult result) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()

我还尝试将 System.Text.JSON 与 JSONDocument 一起使用,但在检索数据时它抱怨说它需要一个构造函数作为 class?

的一部分

发生这种情况的原因是因为 Microsoft.Azure.Cosmos 仍然使用 Newtonsoft.Json 进行序列化和反序列化。

您的 ASP.NET 核心应用程序正在使用 System.Text.Json。在 ASP.NET 核心应用程序中使用 Cosmos 时,我会将解决方案切换为使用 Newtonsoft.Json 而不是 System.Text.Json。你可以通过添加这个包来做到这一点:

Microsoft.AspNetCore.Mvc.NewtonsoftJson

  • 如果您使用的是 .NET Core 3.1,请使用版本 3.1.*
  • 如果您使用的是 .NET5,请使用版本 5.0.*
  • 如果您使用的是 .NET6,请使用版本 6.0.*

然后,在您的 Startup.cs 中,在 ConfigureServices() 方法中将此更改为:

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddControllers();
    // ...
}

为此:

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddControllers().AddNewtonsoftJson();
    // ...
}

由于您只想按原样返回对象,请将代码更改为:

 public async Task<object> GetItemAsync(string id)
{
  try
  {
    var response = await this._container.ReadItemAsync<object>(id, new PartitionKey(id));
    return response.Resource;
  }
  catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
  {
    return null;
  }

}

不需要使用dynamic。只需使用 object.