I have problem with automapper and have no idea if it is possible to do what I am trying to do.
Result should be: For users role 1: Documents with isFavourite null.
For users role 2: Documents with isFavourite true or false. Role is checked in cqrs handler and there i have userId or other data about user.
I don't think I can write where logic where user will be filtered out, without losing documents from final result. Maybe my database design is wrong.
I have 2 database entities like this (one to many):
public class Document {
long DocumentId {get; set;}
//relationships
List<FavouritedDocuments> Favourites {get; set;}
}
and second entity
public class FavouritedDocuments {
public long Id {get; set;}
public long UserId {get; set;}
//relationships
public long DocumentId {get; set;}
public Document Document {get; set;}
}
It will be mapped to specified dto.
public DocumentDto {
public long DocumentId {get; set;}
public bool isFavourited {get; set;}
}
So every document have lists of users who favourited this document.
await _context.Documents.Include(a => a.Favourites)
I am getting this data from database and I have something like this Documents with correspoding collections of favourited Documents. Thing is it will get all data from corresponding table and that's almost ok - except user A will see favourites of user B. I want to inject userId and check if FavouritedDocuments contains userId who sent request so if he did it,it will resolve to true, if not to false if user don't have proper permissions it should be null. (some roles cannot have favourites) In the end collection will be mapped to bool for specified user and data will be hidden.
It works properly, thing is I want to map it like this in automapper to specified Dto.
Now i am trying to map it like this but have no idea how to do it with ProjectTo. Can't directly use map, there is tons of records - it is list.
What i think should work somehow. - runtime
CreateMap<Document , DocumentDto>()
.ForMember(a => a.IsFavourited, opt => opt.MapFrom(c => c.Favourites.Any(b.UserId == _currentUserId)) //how to pass _currentUserId here?
- How to pass userId to ProjectTo ? I've seen other stackoverflow threads, sadly in my cases between ProjectTo and handler there is lot of business logic, paging, services, filters etc. And if i understand correctly I can't use this approach with ProjectTo.
Sadly program have tons of business logic and i need to do it in one endpoint, so it should be quite elastic. Property IsFavourite should be visible only by specified types of users, others should get null there.
So this endpoint should return normal Documents Data and if user has record in favourites table and permission it should resolve it too bool, otherwise it should return normal documents table.
I also thought about getting only data for specified users sadly it will filter out cases for other users. So this approach won't work. Other way would be writing mapping by hand but it is quite ugly approach.
CodePudding user response:
https://docs.automapper.org/en/latest/Queryable-Extensions.html#parameterization
string currentUserName = null;
cfg.CreateProjection<Course, CourseModel>()
.ForMember(m => m.CurrentUserName, opt => opt.MapFrom(src => currentUserName));
dbContext.Courses.ProjectTo<CourseModel>(Config, new { currentUserName = Request.User.Name });