MongoDB C# - 如何将任意 JSON 文档保存为动态类型?

问题描述 投票:0回答:3

我正在尝试编写一个通用 Web Api 控制器,它允许我将 JSON 文档保存到集合中,而无需指定 C# 类型。我尝试将代码压缩为要点:

public class PassThroughController : ApiController
{
    [Route("api/mongodb/{collection}")]
    public void Post(string collection, dynamic document)
    {
        const string connectionString = "mongodb://localhost";

        var client = new MongoClient(connectionString);
        var db = client.GetServer().GetDatabase("SampleDb");
        var mongoCollection = db.GetCollection(collection);

        mongoCollection.Save(document,
            new MongoInsertOptions
            {
                WriteConcern = WriteConcern.Acknowledged
            });
        }
}

我正在尝试发布一个简单的文档:

{ id: "2112", name: "Rush" }

但是无论我向该方法发送什么内容,我都会收到类似以下的错误:“保存只能用于具有 Id 的文档。”

我们尝试了许多不同的 Id 属性(Id、id、_id),但它们都会导致类似的问题。

有什么想法吗?

谢谢

mongodb-.net-driver
3个回答
24
投票

在同事的帮助下,我找到了解决方案:

public class PassThroughController : ApiController
{
    [Route("api/mongodb/{collection}")]
    public void Post(string collection, HttpRequestMessage message)
    {
        const string connectionString = "mongodb://localhost";

        var client = new MongoClient(connectionString);
        var db = client.GetServer().GetDatabase("SampleDb");
        var mongoCollection = db.GetCollection(collection);

        var json = message.Content.ReadAsStringAsync().Result;
        var document = BsonSerializer.Deserialize<BsonDocument>(json);

        mongoCollection.Save(document,
            new MongoInsertOptions
            {
                WriteConcern = WriteConcern.Acknowledged
            });
        }
}

8
投票

我试图保存一些与 ProcessID 关联的动态对象,该动态对象完全是“动态的”,有时它可以是具有任意数据和名称的一个属性,有时它可以是 100 个属性,每个属性的名称完全任意。事实上,它是一个来自 Angular 5 应用程序的对象,该应用程序从(令人惊讶的)某个 JSON 对象生成动态表单。我的“基”类,插入到 mongo 中的类是这样的:

public class MongoSave {

    [BsonId(IdGenerator = typeof(StringObjectIdGenerator))]
    public string Id { get; set; }        
    public int ProcessID { get; set; }
    public BsonDocument DynamicData { get; set; }

}

在我第一次尝试时,

DynamicData
属性是类型
object
,控制器方法接收到一切正常,将传入对象分配给类,但是当将对象保存到mongo时,
DynamicData
的值丢失了。我只得到属性名称。尝试在我的课堂上使用
BsonSerialize
注释,但没有成功。

研究了一下,我发现

BsonDocument
有一个类似于 javascript 的
Parse
方法,可以解析包含对象描述的字符串,所以...我将这样的对象发布到我的控制器:

{
    "ProcessID": 987,
    "DynamicData": {
        "name": "Daniel",
        "lastName": "Díaz",
        "employeeID": 654
    }
{

这里有一些事情,我通过 Insomnia(Postman 替代方案)将此 JSON 发送到 API。在现实世界中,我将通过 Angular 发送此对象,因此我必须确保应用

JSON.stringify(obj)
以确保 JSON 对象没问题(不确定 Angular
HttpClient
是否将对象作为字符串化 JSON 发送)或者作为 JS 对象(我将对此进行测试)。将我的控制器操作更改为使用
Parse
方法和
DynamicData
C# 通用
object
来字符串如下:

[HttpPost("~/api/mongotest/save")]
public async Task<IActionResult> PostObjectToMongo (MongoSaveDTO document) {

    MongoSave mongoItem = new MongoSave() {
        ProcessID = document.ProcessID,
        DynamicData = BsonDocument.Parse(document.DynamicData.ToString())
    };

    await _mongoRepo.AddMongoSave(mongoItem);

    return Ok();
}

MongoSaveDTO
它与没有
MongoSave
属性的
BsonId
相同,而不是
BsonDocument
我使用C#通用
object
类型,一切都像魅力一样保存。


0
投票

注册自定义json序列化器是最简单的:

public class BsonDocumentJsonConverter : JsonConverter<BsonDocument>
{
    public override BsonDocument Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options) =>
        BsonDocument.Parse(reader.GetString());

    public override void Write(
        Utf8JsonWriter writer,
        BsonDocument value,
        JsonSerializerOptions options) =>
        writer.WriteStringValue(value.ToString());
}

在实体中使用后:

public class ContentEntity: EntityBase
{
    public string Repository { get; set; }
    public string Branch { get; set; }
    public string FilePath { get; set; }
    public string ContentId { get; set; }
    public string Title { get; set; }

    [JsonConverter(typeof(BsonDocumentJsonConverter))]
    public BsonDocument Content { get; set; }

    [JsonConverter(typeof(BsonDocumentJsonConverter))]
    public BsonDocument Meta { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.