Home > database >  System.InvalidOperationException: The LINQ expression.... 'could not be translated. Asp.Net 6 .
System.InvalidOperationException: The LINQ expression.... 'could not be translated. Asp.Net 6 .

Time:12-06

In ASP.NET Core-6 Web API Project, I'm trying to retrieve and decode the password from the database before comparing it with the entered password.

I have this code:

public async Task<User> GetUser(string email, string password)
{
     return await _context.Set<User>().Where(e => e.Email == email
                    && DecodeFrom64(e.Password) == password).FirstOrDefaultAsync();
}

I got this error:

System.InvalidOperationException: The LINQ expression 'DbSet<User>()
    .Where(u => u.Email == __email_0 && 
DbHelper.DecodeFrom64(u.Password) == __password_1)'
could not be translated. Additional information: 
Translation of method 'UserOnboardingApi.Model.DbHelper.DecodeFrom64' > failed.

How do I get this resolved?

Thanks

Expected to retrieve and decode the password from the database and compare to what the user entered

CodePudding user response:

EF translates LINQ (when working with IQueryable) into SQL and it does not know anything about your method DecodeFrom64 and can't translate it. Options are

  • Encoding password and checking it server-side (db side):
public async Task<User> GetUser(string email, string password)
{
     return await _context.Set<User>()
          .Where(e => e.Email == email
                    && e.Password == YourEncodeMethod(password))
          .FirstOrDefaultAsync();
}
  • Fetching the user by email (I suppose it should be unique) and check password client-side. Something along this lines:
public async Task<User> GetUser(string email, string password)
{
     var user = await context.Set<User>()
          .FirstOrDefaultAsync(e => e.Email == email);
     if(user is not null && DecodeFrom64(user.Password) == password)
     {
          return user;
     }
     return null;
}
  • Implementing the decode function on the db side and mapping it.

But in general you should consider storing password hashes (see this question), not the encoded ones and check them.

CodePudding user response:

Here is your solution

public async Task<User> GetUser(string email, string password)
{
  Func<User, bool> isValidUser = (User user) => {
                return user.Email == email &&
                   DecodeFrom64(user.Password) == password;
            };
     return await _context.Set<User>().Where(e => isValidUser(e)).FirstOrDefaultAsync();
}

Or your can encode the password before passing and do not decode user.Password

  • Related