In ASP.NET Core Web API, I have three projects:
API.Infrastructure(for DB) -> API.Core(for DTO, Services) -> API.Web
I am using IdentityDbContext. I have a model for the user profile called Profile.
Model:
namespace API.Infrastructure.Entities.Models
{
public class Employee
{
public long Id { get; set; }
public string StaffNumber { get; set; }
public long? UserId { get; set; }
public DateTime EmploymentDate { get; set; }
public virtual ApplicationUser User { get; set; }
}
}
Mapper:
public class EmployeeMapperProfile : Profile
{
public EmployeeMapperProfile()
{
CreateMap<Employee, EmployeeProfileDto>();
}
}
DTO:
namespace Core.DTOs.Empployee.Response
{
public class EmployeeListDto
{
public string StaffNumber { get; set; }
public DateTime? EmploymentDate { get; set; }
}
}
public class GenericResponseDto<T>
{
public int? StatusCode { get; set; }
public T Result { get; set; }
public ErrorResponseDto Error { get; set; }
}
I created a service for this:
namespace API.Core.Helpers
{
public class UserResolverService
{
private readonly IHttpContextAccessor _httpContext;
private readonly UserManager<ApplicationUser> _userManager;
public UserResolverService(IHttpContextAccessor httpContext, UserManager<ApplicationUser> userManager)
{
_httpContext = httpContext;
_userManager = userManager;
}
public string GetUserId()
{
var userId = _userManager.GetUserId(_httpContext.HttpContext.User);
return userId;
}
}
}
Then I have the employee profile service:
Task<GenericResponseDto<EmployeeProfileDto>> GetEmployeeProfileAsync();
public class EmployeeService : I EmployeeService
{
private readonly HrDbContext _context;
private readonly IMapper _mapper;
private readonly UserResolverService _userResolverService;
public EmployeeService(HrDbContext context, IMapper mapper, UserResolverService userResolverService)
{
_mapper = mapper;
_userResolverService = userResolverService;
}
public async Task<GenericResponseDto<EmployeeProfileDto>> GetEmployeeProfileAsync()
{
var response = new GenericResponseDto<EmployeeProfileDto>();
var userId = long.Parse(_userResolverService.GetUserId());
var employeeId = _context.employees.Where(u => u.UserId == userId).Select(m => m.Id).FirstOrDefault();
var employeeProfile = await _context.employees.Include(e => e.User)
.FirstOrDefaultAsync(e => e.Id == employeeId);
if (employeeProfile != null)
{
response.Result = _mapper.Map<EmployeeProfileDto>(employeeProfile);
response.StatusCode = 200;
}
else
{
response.Error = new ErrorResponseDto()
{
ErrorCode = 404,
Message = "Employee not found!"
};
response.StatusCode = 404;
}
return response;
}
}
Controller:
public async Task<ActionResult<GenericResponseDto<EmployeeProfileDto>>> GetEmployeeProfile()
{
var response = await _employeeService.GetEmployeeProfileAsync();
Response.StatusCode = response.StatusCode ?? StatusCodes.Status200OK;
return new JsonResult(response);
}
startup.cs:
services.AddScoped<IEmployeeService, EmployeeService>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddAutoMapper(typeof(EmployeeMapperProfile));
I want to get the profile of the current logged in user using the id.
When I tested on POSTMAN, instead of getting the profile of the current logged in user I got this ErrorMessage:
Value cannot be null. (Parameter 's')
As I tried to debug the code:
var userId = long.Parse(_userResolverService.GetUserId());
gives null.
Why am I getting this error?
Then current user exists, because I was able to login and also generate the Bearer JWT Token