0

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!

1 Answer 1

1

In your rule, pass the Id to the CheckIfEmailIsDuplicate method:

RuleFor(r => r)
            .NotEmpty()
            .WithErrorMessage("Object is Null")
            .MustAsync(async (x, _) =>
            {
                var emailValidator = await userRepository.CheckIfEmailIsDuplicate(x.Id, x.Email);                   
                return !emailValidator ;
            })
            .WithErrorMessage("Email already Existis");

Then modify the SELECT query and the CheckIfEmailIsDuplicate method, using the new Id parameter:

    private static readonly string QUERY_CHECK_IF_EMAIL_IS_DUPLICATE = "SELECT COUNT(*) " +
                "FROM User" +
                @"WHERE Id != @id AND Email = @email";
    
    public async Task<bool> CheckIfEmailIsDuplicate(int id, string email)
        {
            using var connection = dbConnectionFactory.Invoke(DbConnections.DEFAULT_CONNECTION);
    
            var validator = await connection.QueryAsync<int>(
                sql: QUERY_CHECK_IF_EMAIL_IS_DUPLICATES ,
                new
                { 
                    id = id,  
                    email = email               
                });
            return Convert.ToBoolean(validator.FirstOrDefault());
         }
    
            return product.FirstOrDefault();
    
        }

The main change to point out is the usage of Id in the updated SQL query:

SELECT COUNT(*)
FROM User
WHERE Id != @id AND Email = @email

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.