Mike Barnes Mike Barnes - 3 months ago 15
reST (reStructuredText) Question

Deserialization Error ASP.NET MongoDB

I am trying to retireve all the documents in my MongoDB collection via a REST api built in ASP.NET MVC 4 and I have encoutered an error when i enter localhost:50491/api/document:


An error occurred while deserializing the Id property of class Acord_Rest_API.Models.Document: Cannot deserialize string from BsonType ObjectId.


My controller looks like:

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();
}
}


My MongoDB document looks like this?
enter image description here

What am I missing here?

My class that connects to the DB:

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");
}
}


EDIT here is my solution:
enter image description here

MongoConnectionHelper does the connection to the DB, DocumentController has the methods to retrive all the documents and Document contains what you have suggested in your answer.

EDIT here is the Document class:

[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; }
}

Answer

The Mongo Id is not a "string" and the Mongo.Bson library will not serialize it to a string automatically. If you are using the Mongo.Bson library, you need to set the id property on your class to be a ObjectId type which is available in that library.

The problem here is that the .net serializer doesn't know how to serialize the custom type ObjectId that's the mongo built in Id (not sure why). It is not marked as [Serializable] so you have to get ASP.NET to bypass it or create another class that doesn't have one and convert it to a string.

If you need a string to use in your app, you should disable the serialization of the MongoId to xml (if that's what you're trying to do), then you can add a property like this to your class:

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

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

The alternative it to create a seperate mapped class to manage the return data.

EDIT In that case you should use the "opt-in" approach. This involves decorating your class to look like the following:

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

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

...

DataMember will flag only those properties for serialization. Are you using POCO classes for your "Document" object? If so the above should work fine.

I would however recommend creating a mapped view of the "Document" object for passing out publically. In these situations youalmost always end up wanting a slightly different "contract" to your actual database entity

Comments