Search code examples
.netasp.net-identityautomapper

Use current Identity user ID with AutoMapper in .NET 5


I would like to know how I can access the current user ID inside AutoMapper when using Identity Framework.

{
    public class MovieDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool HasLiked { get; set; } // indicates if the current has liked the movie
        ...
    }
}

I would like to be able to access ClaimsPrincipal from inside AutoMapper profile, for example:

CreateMap<Movie, MovieDto>()
    .ForMember(dst => dst.HasLiked, opt => opt.MapFrom(src => 
               src.UserLike.Any(ul => 
               ul.UserId == User.FindFirst(ClaimTypes.NameIdentifier)?.Value));

Is it possible to achieve that with AutoMapper?

If that is not possible or not indicated, what should I do perform such query in my repository in a reusable way?


Solution

  • After @LucianBargaoanu comment, I was able to figure out how to do this properly, so I've decided to answer to help others starting with .Net:

    Create a currentUserId to hold the user id.

    public class AutoMapperProfiles : Profile
    {
        public AutoMapperProfiles()
        {
            string currentUserId = null;
    
            CreateMap<Movie, MovieDto>()
                .ForMember(dst => dst.HasLiked, opt => opt.MapFrom(src => 
                        src.UserLikes.Any(ul => ul.UserId == currentUserId)));
        }
    }
    

    When projecting using AutoMapper, pass currentUserId as a parameter:

    public async Task<MovieDto> GetMoviesdAsync(string userId)
    {
        return await _context.Movies
            .ProjectTo<MovieDto>(_mapper.ConfigurationProvider, new { currentUserId = userId })
            .ToListAsync();
    }
    

    And, this is how I get the UserId in the Controller:

    [HttpGet]
    public async Task<ActionResult<IEnumerable<MovieDto>>> GetMovies()
    {
        var userId = User.GetUserId();
        return Ok(await _unitOfWork.AuctionRepository.GetMoviesdAsync(userId));
    }
    

    This is the extensions method that I use to get the UserId:

    public static class ClaimsPrincipleExtension
    {
        public static string GetUserId(this ClaimsPrincipal user)
        {
            return user.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        }
    }