使用mongoDB进行CRUD操作的Web API控制器

时间:2013-08-16 02:57:16

标签: json mongodb asp.net-web-api objectid

我正在尝试使用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. 我真的不喜欢它,必须有另一种更好的方法来实现这个目标
  4. 我已经阅读了有关使用[BsonId][JsonIgnore]属性等的内容,但是,我没有强类型模型来应用这些属性。我真的想要一种可以帮助我利用Web API内容协商的方法。

    非常感谢您的建议。

0 个答案:

没有答案