I'm refactoring a code that retrives a document from MongoDb collection as a BsonDocument
.
As C# offers us the possibility to make our code more secure with strongly typed class, I wanted to create class to represents the document saved in the collection.
The problem that I've is that a property that should be saved in collection as document, sometimes, somehow is being saved as empty string. So when MongoDbDriver tries to deserialize it, throws me an Exception saying that it was expected a nested document instead of an string.
In that scenario I wanted to set the propery value as null
.
So i've tried to implement my on deserializer to workarround this scenario:
My Class:
[BsonIgnoreExtraElements]
public class ExampleModel
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public ObjectId Id { get; set; }
.
.
.
[BsonElement("usedTemplate")]
[BsonSerializer(typeof(ExampleModelTemplateSerializer ))]
public TemplateModel Template { get; set; }
}
Serializer
public class ExampleModelTemplateSerializer : SerializerBase<TemplateModel>
{
public override TemplateModel Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return context.Reader.CurrentBsonType == BsonType.String
? null
: base.Deserialize(context, args);
}
}
Exception
Message: ReadBsonType can only be called when State is Type, not when State is Value.
The reason you're getting this error is that your context.Reader
needs to read the string anyway so you can call context.Reader.ReadString();
but return null
as you wish.
The next issue is that you're invoking base.Deserialize()
on SerializerBase<T>
which is an abstract class and an exception will be throw (implementation here). So you need to handle deserialization by calling BsonSerializer
:
public class ExampleModelTemplateSerializer : SerializerBase<TemplateModel>
{
public override TemplateModel Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
if (context.Reader.CurrentBsonType == BsonType.String)
{
context.Reader.ReadString();
return null;
}
return BsonSerializer.Deserialize<TemplateModel>(context.Reader);
}
}