Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MongoDB.Bson.Serialization.Attributes;

namespace MongoDB.Bson.Serialization.Conventions
{
Expand Down Expand Up @@ -119,6 +120,12 @@ private bool IsValidIdMember(BsonClassMap classMap, MemberInfo member)
return false;
}
}

var bsonElement = member.GetCustomAttribute<BsonElementAttribute>();
if (bsonElement != null && !string.IsNullOrEmpty(bsonElement.ElementName) && bsonElement.ElementName != "_id")
{
return false;
}
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,83 @@
*/

using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Conventions;
using Xunit;

namespace MongoDB.Bson.Tests.Serialization.Conventions
{
public class ElementNameConventionsTests
{
private class TestClass

[Fact]
public void TestBsonElementAttributeOverridesNamedIdMemberConvention()
{
public string FirstName { get; set; }
public int Age { get; set; }
public string _DumbName { get; set; }
public string lowerCase { get; set; }
var classMap = new BsonClassMap<BookWithBsonElementAttribute>();
classMap.AutoMap();

classMap.Freeze();
Assert.Null(classMap.IdMemberMap);
Assert.Equal("notId", classMap.GetMemberMap(x => x.Id).ElementName);
}

[Fact]
public void TestBsonIdAttributeOverridesNamedIdMemberConvention()
{
var classMap = new BsonClassMap<BookWithBsonIdAttribute>();
classMap.AutoMap();

classMap.Freeze();
Assert.Equal("_id", classMap.GetMemberMap(x => x.Title).ElementName);
Assert.Equal("_id", classMap.IdMemberMap.ElementName);
Assert.Equal("Title", classMap.IdMemberMap.MemberName);
Assert.Equal("id", classMap.GetMemberMap(x => x.id).ElementName);
}

[Fact]
public void TestBsonIdAttributeWinsWhenBsonElementSkipsIdProperty()
{
var classMap = new BsonClassMap<BookWithBsonElementAndBsonId>();
classMap.AutoMap();
classMap.Freeze();

Assert.Equal("Title", classMap.IdMemberMap.MemberName);
Assert.Equal("notId", classMap.GetMemberMap(x => x.Id).ElementName);
}

[Fact]
public void TestBsonElementWithUnderscoreIdOnIdPropertyAlsoBecomesIdMember()
{
var classMap = new BsonClassMap<BookWithExplicitBsonElementId>();
classMap.AutoMap();
classMap.Freeze();

Assert.NotNull(classMap.IdMemberMap);
Assert.Equal("Id", classMap.IdMemberMap.MemberName);
Assert.Equal("_id", classMap.GetMemberMap(x => x.Id).ElementName);
}

[Fact]
public void TestBsonElementWithUnderscoreIdButNoIdPropertyDoesNotBecomeIdMember()
{
var classMap = new BsonClassMap<BookWithExplicitBsonElementIdButNoIdProperty>();
classMap.AutoMap();
classMap.Freeze();

Assert.Null(classMap.IdMemberMap);
Assert.Equal("_id", classMap.GetMemberMap(x => x.Title).ElementName);
}

[Fact]
public void TestBsonElementOnIdFallsThroughToLowercaseId()
{
var classMap = new BsonClassMap<BookWithBsonElementAndFallthrough>();
classMap.AutoMap();
classMap.Freeze();

Assert.Equal("id", classMap.IdMemberMap.MemberName);
Assert.Equal("_id", classMap.GetMemberMap(x => x.id).ElementName);
Assert.Equal("notId", classMap.GetMemberMap(x => x.Id).ElementName);
}

[Fact]
Expand Down Expand Up @@ -58,5 +122,55 @@ public void TestCamelCaseElementNameConvention()
Assert.Equal("_DumbName", classMap.GetMemberMap(x => x._DumbName).ElementName);
Assert.Equal("lowerCase", classMap.GetMemberMap(x => x.lowerCase).ElementName);
}

private class BookWithBsonElementAttribute
{
[BsonElement("notId")]
public ObjectId Id { get; set; } // should not be set to _id
}

private class BookWithBsonIdAttribute
{
public ObjectId id { get; set; }

[BsonId]
public string Title { get; set; } // should be set to _id
}

private class BookWithBsonElementAndBsonId
{
[BsonElement("notId")]
public ObjectId Id { get; set; }

[BsonId]
public string Title { get; set; } // should be set to _id
}

private class BookWithExplicitBsonElementId
{
[BsonElement("_id")]
public string Id { get; set; } // should not be set to _id
}

private class BookWithExplicitBsonElementIdButNoIdProperty
{
[BsonElement("_id")]
public string Title { get; set; } // should be set to _id
}

private class BookWithBsonElementAndFallthrough
{
[BsonElement("notId")]
public ObjectId Id { get; set; }
public ObjectId id { get; set; } // should be set to _id
}

private class TestClass
{
public string FirstName { get; set; }
public int Age { get; set; }
public string _DumbName { get; set; }
public string lowerCase { get; set; }
}
}
}