1

我正在尝试使用 mongoDB 为 CRUD 操作创建一个 API 控制器。现在请记住,我不知道这些集合的结构,使用 mongoDB 的整个想法是我们可以真正利用文档存储选项以及查询能力,而不必担心设计模型。这是我以前的:

// GET api/mongo
public IEnumerable<BsonDocument> Get(String database, String collection)
{
    db = server.GetDatabase(database);
    return db.GetCollection(collection).FindAll().AsEnumerable();
}

但是上面我收到了这个错误:

{
    "Message": "An error has occurred.",
    "ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
    "ExceptionType": "System.InvalidOperationException",
    "StackTrace": null,
    "InnerException": {
        "Message": "An error has occurred.",
        "ExceptionMessage": "Error getting value from '__emptyInstance' on 'MongoDB.Bson.ObjectId'.",
        "ExceptionType": "Newtonsoft.Json.JsonSerializationException",
        "StackTrace": "   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value)\r\n   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value)\r\n   at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)\r\n   at System.Net.Http.Formatting.JsonMediaTypeFormatter.<>c__DisplayClassd.<WriteToStreamAsync>b__c()\r\n   at System.Threading.Tasks.TaskHelpers.RunSynchronously(Action action, CancellationToken token)",
        "InnerException": {
            "Message": "An error has occurred.",
            "ExceptionMessage": "Common Language Runtime detected an invalid program.",
            "ExceptionType": "System.InvalidProgramException",
            "StackTrace": "   at Get__emptyInstance(Object )\r\n   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)"
        }
    }
}

MongoCusror 有一个方法 ToJson() 使用它我能够得到这个:

[
    {
        "_id": ObjectId("520d4776a9a3f31f54ebdba6"),
        "name": "john"
    },
    {
        "_id": ObjectId("520d4b77a9a3f31f54ebdba7"),
        "name": "chi",
        "nickname": "cdawg"
    },
    {
        "_id": ObjectId("520d4c13a9a3f31f54ebdba8"),
        "name": "ak",
        "nickname": "afro",
        "address": {
            "state": "ny"
        }
    }
]

因此,据我所知,Web API 管道无法使用可用的格式化程序来序列化 ObjectId 类型,因为它不是一个简单的类型。即使使用 XML 格式化程序也是如此。

我重写了我的方法如下:

// GET api/mongo
public JArray Get(String database, String collection)
{
    db = server.GetDatabase(database);
    return JArray.Parse(db.GetCollection(collection).FindAll().ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.Strict }));
}

这对我有用并返回以下内容:

[
    {
        "_id": {
            "$oid": "520d4776a9a3f31f54ebdba6"
        },
        "name": "john"
    },
    {
        "_id": {
            "$oid": "520d4b77a9a3f31f54ebdba7"
        },
        "name": "chi",
        "nickname": "cdawg"
    },
    {
        "_id": {
            "$oid": "520d4c13a9a3f31f54ebdba8"
        },
        "name": "akash",
        "nickname": "ak",
        "address": {
            "state": "ny"
        }
    }
]

但我不喜欢这种方法有几个原因:

  1. 将接受标头设置为“text/xml”不起作用,因此它有点扼杀了 Web API 的强大功能
  2. 将集合序列化为 JSON,然后再次解析它只是为了返回它,这似乎是一种浪费
  3. 我真的很不喜欢它,必须有另一种更好的方法来完成这个

我已经阅读了有关使用[BsonId]or[JsonIgnore]属性等的信息,但是,我没有强类型模型来应用这些。我真的很想有一种方法可以帮助我利用 Web API 的内容协商。

非常感谢您的建议。

4

0 回答 0