I am currently working in a C# project and doing some validations with FluentValidator.
I have a doubt about doing the validations in a PUT request.
this is the object i receive from the request
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Contatc { get; set; }
}
There is a rule that 2 different users cant have the same email.
This is its implementaion:
RuleFor(r => r)
.NotEmpty()
.WithErrorMessage("Object is Null")
.MustAsync(async (x, _) =>
{
var emailValidator = await userRepository.CheckIfEmailIsDuplicate(x.Email);
return !emailValidator ;
})
.WithErrorMessage("Email already Existis");
The implementation for "CheckIfEmailIsDuplicate":
private static readonly string QUERY_CHECK_IF_EMAIL_IS_DUPLICATE = "SELECT COUNT(*) " +
"FROM User" +
@"WHERE Email = @email";
public async Task<bool> CheckIfEmailIsDuplicate(string email)
{
using var connection = dbConnectionFactory.Invoke(DbConnections.DEFAULT_CONNECTION);
var validator = await connection.QueryAsync<int>(
sql: QUERY_CHECK_IF_EMAIL_IS_DUPLICATES ,
param: new
{
email
});
return Convert.ToBoolean(validator.FirstOrDefault());
}
I want to know if there is a way to validate only the properties i have changed in the request. For example, imagine there is this 3 Users:
{ 1, "User 1", "[email protected]", "1234567890" };
{ 2, "User 2", "[email protected]", "9876543210" };
{ 3, "User 3", "[email protected]", "5555555555" };
And I want to change only the "Name" of number 1, "User 1" -> "Jonh". When I do that it gives me an error, "Email already Existis"
Is there a way I can compare the original user to the update one and only validate the changed properties?
I also have this function to get an User by Id in my repository:
private static readonly string QUERY_GET_EMAIL_BY_ID = @"SELECT * FROM User WHERE Id = @id";
public async Task<Product> GetEmailByIdAsync(Guid id)
{
using var connection = dbConnectionFactory.Invoke(DbConnections.DEFAULT_CONNECTION);
var product = await connection.QueryAsync<Product>(sql: QUERY_GET_EMAIL_BY_ID, param: new { id });
return product.FirstOrDefault();
}
I dont know if i can use this function in the validation class, when I treid I couldnt figure out how I would pass the request Id as a param.
Thank you guys!
In your rule, pass the Id to the CheckIfEmailIsDuplicate method:
Then modify the SELECT query and the CheckIfEmailIsDuplicate method, using the new Id parameter:
The main change to point out is the usage of Id in the updated SQL query:
If the Id of the object being validated does not exist, it is a brand new record. It will validate the email against all existing records.
Your issue is only with updates. It was trying to validate the email against the same record you are updating.
Solving your problem, this modification will validate the email against all records except the one with the same id.