我正在尝试使用 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"
}
}
]
但我不喜欢这种方法有几个原因:
- 将接受标头设置为“text/xml”不起作用,因此它有点扼杀了 Web API 的强大功能
- 将集合序列化为 JSON,然后再次解析它只是为了返回它,这似乎是一种浪费
- 我真的很不喜欢它,必须有另一种更好的方法来完成这个
我已经阅读了有关使用[BsonId]
or[JsonIgnore]
属性等的信息,但是,我没有强类型模型来应用这些。我真的很想有一种方法可以帮助我利用 Web API 的内容协商。
非常感谢您的建议。