78

When using a FindOne() using MongoDB and C#, is there a way to ignore fields not found in the object?

EG, example model.

public class UserModel
{
    public ObjectId id { get; set; }
    public string Email { get; set; }
}

Now we also store a password in the MongoDB collection, but do not want to bind it to out object above. When we do a Get like so,

  var query = Query<UserModel>.EQ(e => e.Email, model.Email);
  var entity = usersCollection.FindOne(query);

We get the following error

Element 'Password' does not match any field or property of class 

Is there anyway to tell Mongo to ignore fields it cant match with the models?

Aviram Fireberger
  • 3,910
  • 5
  • 50
  • 69
LiamB
  • 18,243
  • 19
  • 75
  • 116

3 Answers3

172

Yes. Just decorate your UserModel class with the BsonIgnoreExtraElements attribute:

[BsonIgnoreExtraElements]
public class UserModel
{
    public ObjectId id { get; set; }
    public string Email { get; set; }
}

As the name suggests, the driver would ignore any extra fields instead of throwing an exception. More information here - Ignoring Extra Elements.

Victor Yarema
  • 1,183
  • 13
  • 15
i3arnon
  • 113,022
  • 33
  • 324
  • 344
  • 1
    @l3arnon Can this be set globally? – LiamB May 03 '14 at 19:52
  • 6
    It can be set globally using a convention, as noted here: https://jira.mongodb.org/browse/CSHARP-965. We don't ignore extra elements by default because it means you are losing data, and that isn't safe. – Craig Wilson May 03 '14 at 23:58
48

Yet Another possible solution, is to register a convention for this.

This way, we do not have to annotate all classes with [BsonIgnoreExtraElements].

Somewhere when creating the mongo client, setup the following:

        var pack = new ConventionPack();
        pack.Add(new IgnoreExtraElementsConvention(true));
        ConventionRegistry.Register("My Solution Conventions", pack, t => true);
Vetras
  • 1,609
  • 22
  • 40
  • 8
    Thanks.. that helped me a lot to not decorage all my poco's with the ObjectId. This way i have a clean datacontract without any mongo specific dependencies. – Pascalsz Nov 15 '17 at 18:33
  • 2
    This solution is also very useful when the models you save on DB are from third party libraries such in this case: https://github.com/souzartn/IdentityServer4.Samples.Mongo – jcasas Feb 18 '19 at 07:18
  • Please also see the comment from screig, you need to do this before create the MongoClient. (I'm not sure but I think in the last few version this was not the case) – MAGYS Nov 24 '20 at 23:21
32

Yes. Another way (instead of editing you model class) is to use RegisterClassMap with SetIgnoreExtraElements.

In your case just add this code when you initialize your driver:

BsonClassMap.RegisterClassMap<UserModel>(cm =>
{
     cm.AutoMap();
     cm.SetIgnoreExtraElements(true);
});

You can read more about ignoring extra elements using class mapping here - Ignoring Extra Elements.

Victor Yarema
  • 1,183
  • 13
  • 15
Aviram Fireberger
  • 3,910
  • 5
  • 50
  • 69
  • 18
    FYI, this only works if called BEFORE initialising the Mongo client (one day wasted). – screig Aug 14 '18 at 12:10
  • In my ASP.NET Core application I need to restart the application in order for the Class Map to take effect.I first do the mappings, then populate initial data in the DB. If I don't restart I get a deserialization exception from the MongoDb C# Driver. Do you know how can I avoid the restart? – jcasas Feb 15 '19 at 12:18
  • 1
    Note, this doesn't ignore extra properties on nested properties bound to a class – Craig Wayne Jun 05 '20 at 00:46