0

Using C# Mongo DB Driver version, 2.4.4 and I try to deserialize a complex class. It has been stored correctly in the MongoDB, but when being deserialized it is null.

This is my datamodel:

public abstract class Document
{
    public DocumentId Id { get; private set; }

    public DocumentProperty TestProperty { get; private set; }

    protected Document() { }

    public void SetId(string value)
    {
        if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("value");
        Id = new DocumentId(value);
    }

    public void AddProperty(DocumentProperty property)
    {
        if (property == null) throw new ArgumentNullException("property");
        TestProperty = property;
    }
}

public class DocumentId
{
    public string Value { get; }

    public DocumentId(string value)
    {
        Value = value;
    }
}

public abstract class DocumentProperty
{
    public string Value { get; }

    protected DocumentProperty()
    {
    }

    protected DocumentProperty(string value)
    {
        Value = value;
    }
}

public class TitleDocumentProperty : DocumentProperty
{
    public TitleDocumentProperty() { }

    public TitleDocumentProperty(string value) : base(value)
    {
    }
}

This is my mapping code:

public class MongoClassMapper
{
    public static void InitializeMap()
    {
        BsonClassMap.RegisterClassMap<DocumentProperty>(map =>
        {
            map.MapProperty(property => property.Value).SetDefaultValue("123");
            map.SetIsRootClass(true);
        });

        BsonClassMap.RegisterClassMap<TitleDocumentProperty>(map =>
        {
        });

        BsonClassMap.RegisterClassMap<Document>(map =>
        {
            map.MapProperty(document => document.Id);
            map.MapProperty(document => document.TestProperty);
            map.SetIsRootClass(true);
        });

    }
}

This is my methods for adding and retrieving data from Mongo:

public async Task<string> Add(Document document)
    {
        await _documents.InsertOneAsync(document);
        return document.Id.Value;
    }

    public async Task<Document> Get(DocumentId id)
    {
        var mongoDocuments = await _documents.Find(document => document.Id == id)
            .ToListAsync();

        return mongoDocuments.SingleOrDefault();
    }

This is the code that I use for testing:

private static MongoCache _cache;

    static void Main(string[] args)
    {
        MongoClassMapper.InitializeMap();
        _cache = new MongoCache(ConfigurationManager.ConnectionStrings["connName"].ConnectionString, "dbName");
        string id = ItShouldCreateRecord().Result;
        var doc = ItShouldGetRecord(id).Result;
    }

    private static Task<string> ItShouldCreateRecord()
    {
        //Arrange
        Document document = new FakeDocument();
        document.SetId(Guid.NewGuid().ToString());
        document.AddProperty(new TitleDocumentProperty("this is a title"));

        //Act
        string id = _cache.Add(document).Result;

        //Assert
        //Assert.NotEmpty(id);
        return Task.FromResult(id);
    }

    private static Task<Document> ItShouldGetRecord(string id)
    {
        //Arrange

        //Act
        return _cache.Get(new DocumentId(id));

        //Assert
        //Assert.NotNull(doc);
    }
}

[BsonIgnoreExtraElements]
public class FakeDocument : Document
{
}

I expected that when I retrieve the document (using _cache.Get()) from the DB, that the property TestProperty would have an actual value. Currently, it is NULL.

1 Answer 1

1

The problem is the absence of a setter on your Value property which will cause MongoDB to not deserialize this property:

public abstract class DocumentProperty
{
    public string Value { get; /* no setter*/ }
}

You can fix this by simply adding the setter (using any accessibility setting, even private works):

public abstract class DocumentProperty
{
    public string Value { get; /* private if you want */ set; }
}

I have captured a JIRA issue and a pull request to get that fixed.

Sign up to request clarification or add additional context in comments.

1 Comment

I can't thank you enough! Spent an entire workday trying different things: (custom serializers, custom typeformatters) and then the solution were so simple. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.