'ASP.NET Core Web API - Cannot implicitly convert type 'ServiceResult<AuthResult>' to 'AuthResult'

In my ASP.NET Core-6 Web API, I am using IdentityDbContext. I am developing a User login authentication with response to be displayed after successful login. I have this model:

ApplicationUser

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    [DefaultValue(false)]
    public bool? IsAdmin { get; set; }

    public ICollection<ApplicationUserRole> UserRoles { get; set; }
}

AuthResult:

public class AuthResult
{
    public string AccessToken { get; set; }
    public string TokenType { get; set; }
    public int ExpiresIn { get; set; }
    public string RefreshToken { get; set; }
    public UserDto User { get; set; }
    public IList<string> Role { get; set; }
}

Result:

public class Result
{
    public bool Successful { get; set; }
    public string[] Errors { get; set; }

    #region Helper Methods

    internal Result(bool successful, IEnumerable<string> errors)
    {
        Successful = successful;
        Errors = errors.ToArray();
    }

    public static Result Success()
    {
        return new Result(true, System.Array.Empty<string>());
    }

    public static Result Failure(IEnumerable<string> errors)
    {
        return new Result(false, errors);
    }
    #endregion
}

I have this service for trapping error:

public class ServiceResult<T> : ServiceResult
{
    public T Data { get; set; }

    public ServiceResult(T data)
    {
        Data = data;
    }

    public ServiceResult(T data, ServiceError error) : base(error)
    {
        Data = data;
    }

    public ServiceResult(ServiceError error) : base(error)
    {

    }
}

public class ServiceResult
{
    public bool Succeswsful => this.Error == null;

    public ServiceError Error { get; set; }

    public ServiceResult(ServiceError error)
    {
        if (error == null)
        {
            error = ServiceError.DefaultError;
        }

        Error = error;
    }

    public ServiceResult() { }

    #region Helper Methods

    public static ServiceResult Failed(ServiceError error)
    {
        return new ServiceResult(error);
    }

    public static ServiceResult<T> Failed<T>(ServiceError error)
    {
        return new ServiceResult<T>(error);
    }

    public static ServiceResult<T> Failed<T>(T data, ServiceError error)
    {
        return new ServiceResult<T>(data, error);
    }

    public static ServiceResult<T> Success<T>(T data)
    {
        return new ServiceResult<T>(data);
    }

    #endregion
}

UserDto:

public class UserDto
{
    public long Id { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Email { get; set; }
    public string UserName { get; set; }
    public bool? IsAdmin { get; set; }
}

JwtTokenManager

public interface IJwtTokenManager
{
    Task<ServiceResult<AuthResult>> GenerateClaimsTokenAsync(string username, CancellationToken cancellationToken);
}

public async Task<ServiceResult<AuthResult>> GenerateClaimsTokenAsync(string username, CancellationToken cancellationToken)
{
    var user = await _userManager.FindByNameAsync(username);
    var role = await _userManager.GetRolesAsync(user);

    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret);
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new[]
        {

            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), // TODO: encrypt user id for added security
            new Claim(ClaimTypes.Name, username),
            new Claim(JwtRegisteredClaimNames.Sub, username),
            new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()),
            new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddMinutes(5)).ToUnixTimeSeconds().ToString()),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),

        }),
        Expires = DateTime.UtcNow.Add(_jwtSettings.Expiration),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };

    var refreshTokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), // TODO: encrypt user id for added security
            new Claim(ClaimTypes.Name, username),
            new Claim(JwtRegisteredClaimNames.Iss, _jwtSettings.Issuer),
            new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()),
            new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()),
            new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddMinutes(30)).ToUnixTimeSeconds().ToString()),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),

        }),
        Expires = DateTime.UtcNow.Add(_jwtSettings.Expiration),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };

    // Create JWT tokens
    var token = tokenHandler.CreateToken(tokenDescriptor);
    var refreshtoken = tokenHandler.CreateToken(refreshTokenDescriptor);

    return ServiceResult.Success(new AuthResult
    {
        AccessToken = tokenHandler.WriteToken(token),
        TokenType = "Bearer",
        ExpiresIn = _jwtSettings.Expiration.Seconds,
        RefreshToken = tokenHandler.WriteToken(refreshtoken),
        User = _mapper.Map<UserDto>(user),
        Role = role,
    });
}

SignInCommandHandler:

using Common.Exceptions;
using MediatR;

public class SignInCommandHandler : IRequestHandler<SignInCommand, AuthResult>
{
    private readonly ISignInManager _signInManager;
    private readonly IJwtTokenManager _jwtTokenManager;

    public SignInCommandHandler(ISignInManager signInManager, IJwtTokenManager jwtTokenManager)
    {
        _signInManager = signInManager;
        _jwtTokenManager = jwtTokenManager;
    }

    public async Task<AuthResult> Handle(SignInCommand request, CancellationToken cancellationToken)
    {
        // validate username & password 
        var result = await _signInManager.PasswordSignInAsync(request.Username, request.Password, false, false);

        // Throw exception if credential validation failed
        if (!result.Successful)
        {
            throw new UnauthorizedException("Invalid username or password.");
        }

        // Generate JWT token response if validation successful
        AuthResult response = await _jwtTokenManager.GenerateClaimsTokenAsync(request.Username, cancellationToken);

        return response;
    }
}

After successful login, the user should get a response as shown below:

{
    "status_code": 200,
    "message": "Successfully logged In",
    "result": {
        "AccessToken": "",
        "TokenType": "Bearer",
        "expires": "2021-12-21T11:17:16Z"
        "user": {
            "id": 3,
            "UserName": "",
            "Email": "",            
            "FirstName": "",
            "LastName": "",
        },
        "role": [
            ""
        ],       
    }
}

But I have this error:

Cannot implicitly convert type 'ServiceResult' to 'AuthResult'

I got this code highlighted:

await _jwtTokenManager.GenerateClaimsTokenAsync(request.Username, cancellationToken)

I changed to:

   public class SignInCommandHandler : IRequestHandler<SignInCommand, AuthResult>
    {
        private readonly ISignInManager _signInManager;
        private readonly IJwtTokenManager _jwtTokenManager;

        public SignInCommandHandler(ISignInManager signInManager, IJwtTokenManager jwtTokenManager)
        {
            _signInManager = signInManager;
            _jwtTokenManager = jwtTokenManager;
        }

        public async Task<AuthResult> Handle(SignInCommand request, CancellationToken cancellationToken)
        {
            // validate username & password 
            var result = await _signInManager.PasswordSignInAsync(request.Username, request.Password, false, false);

            // Throw exception if credential validation failed
            if (!result.Successful)
            {
                throw new UnauthorizedException("Invalid username or password.");
            }

            // Generate JWT token response if validation successful
            ServiceResult<AuthResult> response = await _jwtTokenManager.GenerateClaimsTokenAsync(request.Username, cancellationToken);
            return response;
        }
    }

But still got the same error in the code.

How do I resolve it?

Thanks



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source