简体   繁体   中英

Getting JsonElement into CosmosDB in ASP.NET Core 3.1

You'd think this would be easy as falling off a log, but I'm stumped. I have an ASP.NET 3.1 core web api (using System.Text.Json):

[HttpPost]
public async Task<ActionResult> CreateAsync(JsonElement dzc)

Which in turn calls a service:

public async Task AddItemAsync(JsonElement dzc)
{
    var id = dzc.GetProperty("id").GetString();  // these are both valid
    var userid = dzc.GetProperty("userid").GetString();

    await this._container.CreateItemAsync<JsonElement>(dzc, new PartitionKey(userid));
}

This results in: Message: {"Errors":["The input content is invalid because the required properties - 'id; ' - are missing"]}

Or if I get the raw text:

public async Task AddItemAsync(JsonElement dzc)
{
    var id = dzc.GetProperty("id").GetString();  // these are all valid
    var userid = dzc.GetProperty("userid").GetString();
    var raw = dzc.GetRawText();

    await this._container.CreateItemAsync<string>(raw, new PartitionKey(userid));
}

and raw is:

{
    "id": "foozy",
    "userid": "foozy",
    "name": "Jayb",
    "fc": {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "properties": {
                    "capacity": "10",
                },
                "geometry": {
                    "type": "Point",
                    "coordinates": [
                        -71.073283,
                        42.417500
                    ]
                }
            }
        ]
    }
}

This results in: Message: {"Errors":["One of the specified inputs is invalid"]}

All I'm really trying to do is shovel some Json directly from an API into CosmosDB without using C# classes. What is the magic incantation?

Short answer...you can't via CreateItemAsync . The documentation explicitly states that an id prop is required, which by definition does not exist on on either JsonElement or string .

A better option would be to use CreateItemStreamAsync which allows you to pass in the raw stream directly and appears to bypass an Id property requirement, per the example in the documentation .

using (Response response = await this.Container.CreateItemStreamAsync(partitionKey: new PartitionKey("streamPartitionKey"), streamPayload: stream))
{
    using (Stream responseStream = await response.ContentStream)
    {
        //Read or do other operations with the stream
        using (StreamReader streamReader = new StreamReader(responseStream))
        {
            string responseContentAsString = await streamReader.ReadToEndAsync();
        }
    }
}

Thanks David L, your suggestion worked great! Here's what I ended up with:

public async Task AddItemAsync(JsonElement dzc)
{
    var id = dzc.GetProperty("id").GetString();
    var userid = dzc.GetProperty("userid").GetString();

    var raw = dzc.GetRawText();
    byte[] bytes = Encoding.UTF8.GetBytes(raw);
    using (var stream = new MemoryStream(bytes))
    {
        await this._container.CreateItemStreamAsync(stream, new PartitionKey(userid));
    }
}

I'm curious if the copy can be avoided.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM