[CSHARP-3780] For GuidRepresentationMode.V3, an exception is thrown when saving an ExpandoObject with a Guid Created: 04/Aug/21  Updated: 27/Oct/23  Resolved: 11/Aug/21

Status: Closed
Project: C# Driver
Component/s: Serialization
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Major - P3
Reporter: Markus Wildgruber Assignee: James Kovacs
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

When saving an ExpandoObject that contains a GUID property, GuidSerializer throws an exception if BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3.

See this code: mongo-csharp-driver/GuidSerializer.cs at master · mongodb/mongo-csharp-driver (github.com)

Exception is thrown at line 174: 

 

throw new BsonSerializationException("GuidSerializer cannot serialize a Guid when GuidRepresentation is Unspecified.");

 

The following code reproduces the issue:

BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;
var client = new MongoClient("mongodb://localhost:27017");
var db = client.GetDatabase("test");
var coll = db.GetCollection<ExpandoObject>("expando");
var exp = new ExpandoObject();
((IDictionary<string, object>)exp)["MyGuid"] = Guid.NewGuid();
await coll.InsertOneAsync(exp);

If the first line is omitted, the expandoobject is serialized and saved to db, but not as a UUID, but as binary, e.g.

Binary('RlOOu1meGkOh0ZMoDqcAiA==', 3)
 
 



 Comments   
Comment by Markus Wildgruber [ 11/Aug/21 ]

Hi James, 

thank you for the workaround and the explanation. That did the trick and the serialization works now.

Have a great day,

Markus

 

Comment by James Kovacs [ 10/Aug/21 ]

Hi, m.wildgruber@sevantage.de,

Thank you for reaching out to us about this issue.

When using GuidRepresentationMode.V3:

In V3 mode the central principle is that the representation of Guids is controlled at the level of each individual property of a document by configuring the serializer for that property.

Since you are using an ExpandoObject, you cannot specify attributes on GUID properties to configure the serializer for those properties. You don't have a class definition that you can annotate with serialization attributes. You also don't have an explicit BsonClassMap, which can be configured.

ExpandoObject instances are serialized by the ObjectSerializer, which defaults to GuidRepresentation.Unspecified - which is why you are encountering this exception when in V3 mode. We can work around this issue by specifying the default desired GuidRepresentation for the ObjectSerializer during the application bootstrapping process:

BsonSerializer.RegisterSerializer(new ObjectSerializer(BsonSerializer.LookupDiscriminatorConvention(typeof(object)), GuidRepresentation.Standard));
BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;

Regarding your other question of why GUIDs are serialized as Binary('RlOOu1meGkOh0ZMoDqcAiA==', 3) rather than UUID, binary subtype 3 is the old UUID format. The new UUID format is binary subtype 4 and has the advantage of well-defined byte-ordering across platforms, which subtype 3 didn't have. See the BSON Specification for more details. Thus Binary('RlOOu1meGkOh0ZMoDqcAiA==', 3) is the correct raw format for a V2-mode GUID.

Please try the above solution of explicitly registering an ObjectSerializer during application startup to see if that resolves your issue. Based on our initial investigation, the GuidRepresentationMode.V3 behaviour works as designed though it is admittedly somewhat confusing.

Sincerely,
James

Comment by Esha Bhargava [ 06/Aug/21 ]

m.wildgruber@sevantage.de Thank you for reporting this issue. We'll look into it and get back to you soon.

Generated at Wed Feb 07 21:46:17 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.