public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection values)
        {
            if (context == null) {
                throw TraceException("SetPropertyValues", new ArgumentNullException("context"));
            }
            if (values == null) {
                throw TraceException("SetPropertyValues", new ArgumentNullException("values"));
            }

            var userName = (string) context["UserName"];
            var isAuthenticated = (bool) context["IsAuthenticated"];

            if (string.IsNullOrWhiteSpace(userName) || values.Count == 0) {
                return;
            }

            var updateValues = (from SettingsPropertyValue value in values
                               let allowAnonymous = value.Property.Attributes["AllowAnonymous"].Equals(true)
                               where (value.IsDirty || !value.UsingDefaultValue) && (isAuthenticated || allowAnonymous)
                               select value).ToList();

            // If there are no values to update, then we're done here.
            if (updateValues.Count == 0) {
                return;
            }

            // If the user doesn't exist, and it's anonymous, create it.
            var user = GetMongoUser(userName);
            if (user == null) {
                if (!isAuthenticated) {
                    user = new MongoMembershipUser {
                        UserName = userName,
                        IsAnonymous = true,
                        CreationDate = DateTime.Now,
                    };

                    try {
                        var users = GetUserCollection();
                        users.Insert(user);
                    }
                    catch (MongoSafeModeException e) {
                        var message = ProviderResources.CouldNotCreateUser;
                        throw TraceException("SetPropertyValues", new ProviderException(message, e));
                    }
                } else {
                    var message = ProviderResources.CouldNotFindUser;
                    throw TraceException("SetPropertyValues", new ProviderException(message));
                }
            }

            // Create the properties BSON document.
            var properties = new BsonDocument();
            var propertiesWriterSettings = new BsonDocumentWriterSettings();
            var propertiesWriter = new BsonDocumentWriter(properties, propertiesWriterSettings);
            propertiesWriter.WriteStartDocument();
            foreach (var value in updateValues) {
                propertiesWriter.WriteName(value.Name);
                switch (value.Property.SerializeAs) {
                    case SettingsSerializeAs.String:
                    case SettingsSerializeAs.Xml:
                        BsonSerializer.Serialize(propertiesWriter, typeof (string), value.SerializedValue);
                        break;
                    case SettingsSerializeAs.Binary:
                        BsonSerializer.Serialize(propertiesWriter, typeof (byte[]), value.SerializedValue);
                        break;
                    case SettingsSerializeAs.ProviderSpecific:
                        BsonSerializer.Serialize(propertiesWriter, value.Property.PropertyType, value.PropertyValue);
                        break;
                    default:
                        throw TraceException("SetPropertyValues", new ArgumentOutOfRangeException());
                }
            }
            propertiesWriter.WriteEndDocument();

            // Create the profile BSON document.
            var profile = SerializationHelper.Serialize(typeof (MongoProfile), new MongoProfile {
                Properties = properties,
                LastActivityDate = DateTime.Now,
                LastUpdateDate = DateTime.Now
            });

            try {
                var query = Query.EQ("UserName", userName);
                var update = Update.Set("Profile", profile);
                var users = GetUserCollection();
                users.Update(query, update);
            } catch (MongoSafeModeException e) {
                var message = ProviderResources.CouldNotUpdateProfile;
                throw TraceException("SetPropertyValues", new ProviderException(message, e));
            }
        }
        public override MembershipUser CreateUser(string userName, string password, string email, string passwordQuestion, string passwordAnswer,
            bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            if (string.IsNullOrWhiteSpace(userName)) {
                var message = ProviderResources.UserNameCannotBeNullOrWhiteSpace;
                throw TraceException("CreateUser", new ArgumentException(message, "userName"));
            }
            if (string.IsNullOrWhiteSpace(password)) {
                var message = ProviderResources.PasswordCannotBeNullOrWhiteSpace;
                throw TraceException("CreateUser", new ArgumentException(message, "password"));
            }

            if (email != null) {
                email = email.Trim();
            }
            if (passwordQuestion != null) {
                passwordQuestion = passwordQuestion.Trim();
            }
            if (passwordAnswer != null) {
                passwordAnswer = passwordAnswer.Trim();
            }

            bool hasFailedValidation = false;
            status = MembershipCreateStatus.Success;

            if (string.IsNullOrWhiteSpace(userName) || userName.Contains(",")) {
                status = MembershipCreateStatus.InvalidUserName;
                hasFailedValidation = true;
            }
            if (string.IsNullOrWhiteSpace(password)) {
                status = MembershipCreateStatus.InvalidPassword;
                hasFailedValidation = true;
            }

            var passwordEventArgs = new ValidatePasswordEventArgs(userName, password, true);
            OnValidatingPassword(passwordEventArgs);
            if (passwordEventArgs.Cancel) {
                status = MembershipCreateStatus.InvalidPassword;
                hasFailedValidation = true;
            } else if (RequiresUniqueEmail && EmailIsDuplicate(email)) {
                status = MembershipCreateStatus.DuplicateEmail;
                hasFailedValidation = true;
            } else if (RequiresQuestionAndAnswer && string.IsNullOrWhiteSpace(passwordQuestion)) {
                status = MembershipCreateStatus.InvalidQuestion;
                hasFailedValidation = true;
            } else if (RequiresQuestionAndAnswer && string.IsNullOrWhiteSpace(passwordAnswer)) {
                status = MembershipCreateStatus.InvalidAnswer;
                hasFailedValidation = true;
            } else if (!ValidatePassword(password)) {
                status = MembershipCreateStatus.InvalidPassword;
                hasFailedValidation = true;
            }

            var id = ConvertProviderUserKeyToObjectId(providerUserKey);
            if (providerUserKey != null && !id.HasValue) {
                status = MembershipCreateStatus.InvalidProviderUserKey;
                hasFailedValidation = true;
            }
            if (providerUserKey == null) {
                providerUserKey = ObjectId.GenerateNewId();
            }

            var oldUser = GetUser(userName, false);
            if (oldUser != null) {
                status = MembershipCreateStatus.DuplicateUserName;
                hasFailedValidation = true;
            }

            if (hasFailedValidation) {
                return null;
            }

            var passwordSalt = GeneratePasswordSalt();
            var creationDate = DateTime.Now;

            var newUser = new MongoMembershipUser {
                Id = (ObjectId) providerUserKey,
                UserName = userName,
                Password = EncodePassword(password, _passwordFormat, passwordSalt),
                PasswordFormat = PasswordFormat,
                PasswordSalt = passwordSalt,
                PasswordQuestion = passwordQuestion,
                PasswordAnswer = EncodePassword(passwordAnswer, _passwordFormat, passwordSalt),
                FailedPasswordAttemptCount = 0,
                FailedPasswordAttemptWindowStartDate = creationDate,
                FailedPasswordAnswerAttemptCount = 0,
                FailedPasswordAnswerAttemptWindowStartDate = creationDate,
                Email = email,
                Comment = null,
                IsApproved = isApproved,
                IsLockedOut = false,
                CreationDate = creationDate,
                LastLoginDate = DateTime.MinValue,
                LastActivityDate = DateTime.MinValue,
                LastPasswordChangedDate = DateTime.MinValue,
                LastLockedOutDate = DateTime.MinValue
            };

            try {
                var users = GetUserCollection();
                users.Insert(newUser);
            } catch (MongoSafeModeException e) {
                if (e.Message.Contains("_id_")) {
                    status = MembershipCreateStatus.DuplicateProviderUserKey;
                } else if (e.Message.Contains("UserName_1")) {
                    status = MembershipCreateStatus.DuplicateUserName;
                } else {
                    status = MembershipCreateStatus.ProviderError;
                }
                return null;
            }

            return GetUser(userName, false);
        }