4

我正在尝试通过 ASP.NET MVC 4 中内置的 REST api 检索 MongoDB 集合中的所有文档,当我输入 localhost:50491/api/document 时遇到错误:

反序列化 Acord_Rest_API.Models.Document 类的 Id 属性时出错:无法从 BsonType ObjectId 反序列化字符串。

我的控制器看起来像:

public class DocumentController : ApiController
{
    public readonly MongoConnectionHelper<Document> docs;

    public DocumentController()
    {
        docs = new MongoConnectionHelper<Document>();
    }

    public IList<Document> getAllDocs()
    {
        var alldocs = docs.collection.FindAll();
        return alldocs.ToList();
    }
}

我的 MongoDB 文档看起来像这样? 在此处输入图像描述

我在这里想念什么?

我连接到数据库的类:

public class MongoConnectionHelper<T> where T: class
{
    public MongoCollection<T> collection { get; private set; }

    public MongoConnectionHelper()
    {
        string connectionString = "mongodb://127.0.0.1";
        var server = MongoServer.Create(connectionString);
        if (server.State == MongoServerState.Disconnected)
        {
            server.Connect();
        }
        var conn = server.GetDatabase("Acord");
        collection = conn.GetCollection<T>("Mappings");
    }
}

编辑这里是我的解决方案: 在此处输入图像描述

MongoConnectionHelper 连接到数据库, DocumentController 具有检索所有文档的方法,并且 Document 包含您在答案中建议的内容。

编辑这里是文档类:

[DataContract]
public class Document
{
    public ObjectId _id { get; set; }

    [DataMember]
    public string MongoId
    {
        get { return _id.ToString(); }
        set { _id = ObjectId.Parse(value); }
    }
    public IList<string> alldocs { get; set; }
}
4

3 回答 3

6

Mongo Id 不是“字符串”,Mongo.Bson 库不会自动将其序列化为字符串。如果您使用的是 Mongo.Bson 库,则需要将类上的 id 属性设置为该库中可用的 ObjectId 类型。

这里的问题是.net 序列化程序不知道如何序列化自定义类型 ObjectId,它是 mongo 内置的 Id(不知道为什么)。它没有标记为 [Serializable],因此您必须让 ASP.NET 绕过它或创建另一个没有的类并将其转换为字符串。

如果您需要在您的应用程序中使用一个字符串,您应该禁用 MongoId 到 xml 的序列化(如果这是您想要做的),那么您可以将这样的属性添加到您的类中:

[XmlIgnore]
public ObjectId _id { get; set; }

public string MongoId
{
    get { return _id.ToString(); }
    set { _id = ObjectId.Parse(value); }
}

另一种方法是创建一个单独的映射类来管理返回数据。

编辑在这种情况下,您应该使用“选择加入”方法。这涉及将您的班级装饰成如下所示:

[DataContract]
public class Document
{
    public ObjectId _id { get; set; }

    [DataMember]
    public string MongoId
    {
        get { return _id.ToString(); }
        set { _id = ObjectId.Parse(value); }
    }

...

DataMember 将仅标记这些属性以进行序列化。您是否为“文档”对象使用 POCO 类?如果是这样,上面应该可以正常工作。

但是,我建议创建“文档”对象的映射视图以公开传递。在这些情况下,您几乎总是想要与您的实际数据库实体略有不同的“合同”

于 2013-01-11T11:10:13.940 回答
6

更简单的方法是告诉 MongoDB 将字符串字段视为 ObjectId。BsonType您可以通过使用属性轻松做到这一点。

[BsonRepresentation(BsonType.ObjectId)]
public string _id { get; set; }
于 2016-01-19T07:46:16.347 回答
1

我认为您缺少 [BsonId] 约定,因此您的课程应如下所示:

[DataContract]
public class Document
{
    [BsonId]
    public ObjectId _id { get; set; }

    [DataMember]
    public string MongoId
    {
        get { return _id.ToString(); }
        set { _id = ObjectId.Parse(value); }
    }
于 2016-08-09T14:16:22.620 回答