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"
}
}
]
しかし、私はいくつかの理由でこの方法が好きではありません:
- Acceptヘッダーを「text/xml」に設定しても機能しないため、Web APIの素晴らしさを台無しにします
- コレクションをJSONにシリアル化し、それを返すためだけに再度解析するのは無駄のようです
- 私は本当にそれが好きではありません。これを達成するための別のより良い方法があるはずです
[BsonId]
または属性などの使用について読んだことが[JsonIgnore]
ありますが、これらを適用するための強く型付けされたモデルがありません。そして、Web API のコンテンツ ネゴシエーションを活用するのに役立つ方法が本当に必要です。
あなたの提案は大歓迎です。