Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB Element name _id not valid (Update)

I've been attempting to update a user through mongodb, and whenever I run the method it gives me back an exception.

MongoDB.Bson.BsonSerializationException: Element name '_id' is not valid'.

The method I called was a unit test.

public void TestPutMethod()
    {
        UserEdit userEditSuccess = new UserEdit()
        {
            Password = "newpassword",
            Email = "newemail",
            FirstName = "newfirstname",
            Id = ObjectId.Parse("5828491d63b2a67418591517")
        };

        IHttpActionResult httpActionResult = _controller.Put(userEditSuccess);
        OkNegotiatedContentResult<User> httpActioNResultCast = httpActionResult as OkNegotiatedContentResult<User>;

        Assert.IsInstanceOfType(httpActionResult, typeof(OkNegotiatedContentResult<User>));

    }

The unit test uses the put method which looks like this.

[HttpPut]
    public IHttpActionResult Put(UserEdit userEdit)
    {

        if (userEdit.FirstName == null || userEdit.Email == null || userEdit.Password == null)
            return BadRequest("Incorrect input.");
        {
            using (DataContext db = new DataContext())
            {
                User user = new User
                {
                    FirstName = userEdit.FirstName,
                    Email = userEdit.Email
                };

                byte[] password = Encoding.Unicode.GetBytes(userEdit.Password);

                byte[] salted = Password.CreateSalt();
                user.Salt = Encoding.Unicode.GetString(salted);

                byte[] passHash = Password.GernarateSaltedHash(password, salted);
                user.PassHash = Encoding.Unicode.GetString(passHash);
                db.Update("user", i => i.Id == userEdit.Id, user);
                return Ok(user);
            }
        }
    }

And the method the exception is thrown from is the update method that looks like this.

public void Update<T>(string collectionName, Expression<Func<T, bool>> filter, T obj)
    {
        Update(GetCollection<T>(collectionName), filter, obj);
    }

I've already added attributes for the User class and the UserEdit class which looks like this.

public class UserEdit
{
    [BsonId, BsonRepresentation(BsonType.ObjectId)]
    public ObjectId Id { get; set; }
    public string FirstName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

And this.

public class User
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public ObjectId Id { get; set; }
    public string FirstName { get; set; }
    public string Email { get; set; }
    [IgnoreDataMember]
    public string PassHash { get; set; }
    [IgnoreDataMember]
    public string Salt { get; set; }

If anyone here knows what's going wrong or you are in need of additional information please let me know.

Update : GetCollection was asked to be explained, it looks like this.

_database = client.GetDatabase("campanion");

public IMongoCollection<T> GetCollection<T>(string name)
    {
        return _database.GetCollection<T>(name);
    }

And it's basically returning a collection from the database with whatever name input I give it.

like image 444
Alex Pedersen Avatar asked Nov 28 '16 09:11

Alex Pedersen


2 Answers

I just ran into the same scenario and Michael Kirkegaard is correct. When you use the ReplaceOne method instead it will overwrite the Json document.

That's precisely what was needed for the scenario. Otherwise I believe you have to remove the _id property from the object.

like image 134
Keith Hodo Avatar answered Nov 12 '22 04:11

Keith Hodo


It is trying to access an Id property of an update definition object, which should have operators to update specific properties of your document.

something like:

var updateDefinition = new BsonDocument("$set", new BsonDocument("FirstName", "newfirstname"));

If you want to update the full document use ReplaceOne.

like image 42
Victor SDK Avatar answered Nov 12 '22 04:11

Victor SDK