asp.net core identity. insert logged in user ID to a table as FK - asp.net-core

How can I insert current user into the Invite table ask FK?
Invite Model have been scaffolded
Models
{
public int ID { get; set; }
[ForeignKey("UserId")] //ICollection<Invite> in User
[Display(Name = "Users")]
public virtual ApplicationUser User { get; set; }
}
=================
public class ApplicationUser : IdentityUser
{
public string Description { get; set; }
[ForeignKey("GameID")]
public int? GameID { get; set; }
public Game Game { get; set; }
public string GameTag { get; set; }
public virtual ICollection<Invite> Invite { get; set; }

For your Invite model does not specify the ForeingnKey as a property,you just get the current user and add to the Invite instance:
public class InvitesController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<ApplicationUser> _userManager;
public InvitesController(ApplicationDbContext context, UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
_context = context;
}
[HttpPost]
public async Task<IActionResult> Create(Invite invite)
{
if (ModelState.IsValid)
{
invite.User = await _userManager.GetUserAsync(User); //add this...
_context.Add(invite);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(invite);
}
}
Model:
public class Invite
{
public int ID { get; set; }
[ForeignKey("UserId")] //ICollection<Invite> in User
[Display(Name = "Users")]
public virtual ApplicationUser User { get; set; }
}
public class ApplicationUser : IdentityUser
{
public string Description { get; set; }
[ForeignKey("GameID")]
public int? GameID { get; set; }
public Game Game { get; set; }
public string GameTag { get; set; }
public virtual ICollection<Invite> Invite { get; set; }
}
public class Game
{
public int Id { get; set; }
public string Name { get; set; }
}

Related

Entity Framework: get data from many-to-many relationship

I work on an API and when I want to get data from a many-to-many relationship, I get back null.
The connection with the database is OK, and Post date work.
But when I get info from the database, the table for the many-to-many relationship is empty
public class User
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(30)]
public string Pseudo { get; set; }
[EmailAddress]
public string Mail { get; set; }
[Required]
public string Pwd { get; set; }
[Required]
public bool IsAdmin { get; set; }
public ICollection<Project> UsersProjectstry { get; set; }
public ICollection<UserProjectMTM> UsersProjects { get; set; }
}
public class Project
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(30)]
public string Name { get; set; }
[Required]
[MinLength(100)]
public string Description { get; set; }
public string? img { get; set; }
[Required]
public DateTime StartDate { get; set; }
[Required]
public DateTime EndDate { get; set; }
[Required]
public int SumGoal { get; set; }
public int Sum { get; set; }
[Required]
public User ProjectManager { get; set; }
public ICollection<UserProjectMTM> Donator { get; set; }
}
public class UserProjectMTM
{
public int PId { get; set; }
public Project Project { get; set; }
public int UId { get; set; }
public User User { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new ProjectConfig());
modelBuilder.ApplyConfiguration(new UserConfig());
modelBuilder.ApplyConfiguration(new CommentConfig());
modelBuilder.Entity<UserProjectMTM>().HasKey(x => new { x.UId, x.PId });
modelBuilder.Entity<UserProjectMTM>().HasOne(p=> p.Project).WithMany(u=> u.Donator).HasForeignKey(x=>x.PId);
modelBuilder.Entity<UserProjectMTM>().HasOne(u => u.User).WithMany(p=> p.UsersProjects).HasForeignKey(x => x.UId);
}
public IEnumerable<TEntity> GetAll()
{
return _Context.Set<TEntity>();
}
public TEntity? GetById(params object[] Id)
{
return _Context.Set<TEntity>().Find(Id);
}
I try a lot of things - so far without success.
I'm junior and I can't find the solution - please help.

Eager loading use Include got error in .Net

I'd like to display the 'ApplicationRole' Name with the 'ApplicationUser' data together using Eager loading.
here is my ApplicationUser
public class ApplicationUser : IdentityUser
{
public string? Name { get; set; }
public string? Department { get; set; }
public bool IsDeleted { get; set; }
public string RoleId { get; set; }
public virtual ApplicationRole Role { get; set; } = new ApplicationRole();
}
public class ApplicationUserDTO
{
public string Id { get; set; }
public int UserId { get; set; }
public string Name { get; set; }
public string UserName { get; set; }
// Foreign Key
public string RoleId { get; set; }
public virtual ApplicationRoleDTO Role { get; set; } = new ApplicationRoleDTO();
}
here is ApplicationRole
[NotMapped]
public class ApplicationRole : IdentityRole
{
public string Id { get; set; }
public string Name { get; set; }
//[InverseProperty(nameof(ApplicationUser.Role))]
public virtual ICollection<ApplicationUser> Users { get; set; } = new List<ApplicationUser>();
}
public class ApplicationRoleDTO
{
public string Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ApplicationUserDTO> Users { get; set; } = new List<ApplicationUserDTO>();
}
and here is the UserRepository
public async Task<IEnumerable<ApplicationUser>> GetAllUsersAsync()
{
//return await _dbContext.User.Where(u => u.IsDeleted == false).ToListAsync();
return await _dbContext.User.Include(u => u.Role).Where(u => u.IsDeleted == false).ToListAsync();
}
public async Task<ApplicationUser> GetUserAsync(string id)
{
return await _dbContext.User.Where(u => u.Id == id).Where(u => u.IsDeleted == false).FirstOrDefaultAsync();
}
But when I use the 'Include' keyword it show this error
When I try to use the string "Role", it also show error
public async Task<IEnumerable<ApplicationUser>> GetAllUsersAsync()
{
return await _dbContext.User.Include("Role").Where(u => u.IsDeleted == false).ToListAsync();
}
Here is the error show

ASP.Net core - make a search inside a nested collection

I'm trying to make a nested collection search and I'm really struggling.
My expected result is: I would like to make a search and find all the powerUp objects by a certain date. (PowerUpDate property - that's the searching criteria)
User Model:
public class AppUser : IdentityUser
{
public ICollection<Hero> Heroes { get; set; }
}
Hero Model:
[Table("Heroes")]
public class Hero
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Ability { get; set; }
[Required]
public string SuitColors { get; set; }
public double CurrentPower { get; set; }
public double StartingPower { get; set; }
public DateTime Created { get; set; } = DateTime.Now;
public ICollection<PowerUp> PowerUps { get; set; }
public AppUser AppUser { get; set; }
[Required]
public string AppUserId { get; set; }
}
PowerUp Model:
[Table("PowerUps")]
public class PowerUp
{
public int Id { get; set; }
[Required]
public double PowerUpIncrement { get; set; }
[Required]
public DateTime PowerUpDate { get; set; } = DateTime.Now;
public Hero Hero { get; set; }
[Required]
public int HeroId { get; set; }
}
DataContext:
public class DataContext : IdentityDbContext<AppUser>
{
public DataContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Hero>().HasMany(hero => hero.PowerUps).WithOne(powerUp => powerUp.Hero)
.OnDelete(DeleteBehavior.Cascade);
builder.Entity<AppUser>().HasMany(user => user.Heroes).WithOne(hero => hero.AppUser)
.OnDelete(DeleteBehavior.Cascade);
}
}
Could someone please explain to me how can I implement such a search on a nested collection?
Inject your AppUser user using Dependency injection
(better use the repository pattern) anyway it should be something like this: user.Heroes.PowerUps.OrderBy(x=>x.PowerUpDate == Datetime.Now).ToList();
x.PowerUpDate == To whatever date you will insert

Recommended approach to show a custom user property in a view?

I'm trying to build a simple helpdesk application. In this app, when a ticket is created and displayed, I want to show the first name of the creating user. I am trying to solve how to do this in the best possible way.
I've extended the ApplicationUser class and added FirstName and LastName columns. I also created two foreign keys in my Tickets table, one for the user who created the ticket and one for the agent gets assigned to that ticket. So when the ticket is displayed, I need to show both creators and agents first name + last name's, instead of their UserId's.
This is my ApplicationUser class
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<Ticket> Users { get; set; }
public ICollection<Ticket> Agents { get; set; }
}
This is my model:
public class Ticket
{
public int Id { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public int Status { get; set; }
public string UserId { get; set; }
public string AgentId { get; set; }
public DateTime Created { get; set; }
public DateTime LastUpdated { get; set; }
public DateTime? Completed { get; set; }
public bool Muted { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser TicketUser { get; set; }
[ForeignKey("AgentId")]
public virtual ApplicationUser TicketAgent { get; set; }
}
This is my DbContext:
public DbSet Tickets { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity()
.HasOne(m => m.TicketUser)
.WithMany(t => t.Users)
.HasForeignKey(m => m.UserId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity()
.HasOne(m => m.TicketAgent)
.WithMany(t => t.Agents)
.HasForeignKey(m => m.AgentId)
.OnDelete(DeleteBehavior.Restrict);
}
This is the controller action to display a specific ticket:
[HttpGet]
public ViewResult Tickets(int id)
{
TicketDetailsViewModel ticketDetailsViewModel = new TicketDetailsViewModel()
{
Ticket = _ticketRepo.GetTicket(id)
};
return View(ticketDetailsViewModel);
}
This is my viewmodel:
public class TicketDetailsViewModel
{
public Ticket Ticket { get; set; }
}
Now, I can display the full name in my view if I do this:
#inject UserManager userManager;
#{
var ticketUser = (await userManager.FindByIdAsync(Model.Ticket.UserId)).FirstName + " " + (await userManager.FindByIdAsync(Model.Ticket.UserId)).LastName;
}
But I am not sure if this is a good way to do it. I'd like to learn what is the best way to achive this.
Thank you very much.
You can define a _fullname in your ApplicationUser , and then if firstname and lastname both exist, you can directly call Fullname, like:
public class ApplicationUser : IdentityUser
{
private string _fullName; //new property
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string FullName
{
get
{
return _fullName = this.FirstName + "." + this.LastName;
}
set
{
_fullName = value;
}
}
public ICollection<Ticket> Users { get; set; }
public ICollection<Ticket> Agents { get; set; }
}
In view, just call FullName:
#{
var ticketUser = (await userManager.FindByIdAsync(Model.Ticket.UserId)).FullName;
}
In these scenarios I usually prefer to go with an extension method instead of an additional property like proposed by user Jerry Cai, the model remains lighter and cleaner imho:
public static class ApplicationUsersExtensions
{
public static string GetFullname(this ApplicationUser user)
{
return $"{user.FirstName}.{user.LastName}";
}
}

The problem with Include method using on Db context - Asp.Net Core

I'v got a backend on Asp.Net Core. Structure of the database looks that:
User - the basics information about user: login, password etc.
Profile - this entity is connected to the"User" one to one relation
Profile photos- each of the users has a own collection of photos.
This entity is connected to the "Profile"
Here is the "User" entity:
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }
public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; }
public Profile Profile { get; set; }
}
Then Profile:
public class Profile
{
[ForeignKey("User")]
public int Id { get; set; }
public string BannerImageUrl { get; set; }
public string ProfileImageUrl { get; set; }
public string ShortDescription { get; set; }
public string Description { get; set; }
public User User { get; set; }
public ICollection<ProfilePhotos> ProfilePhotos { get; set; }
}
And "ProfilePhotos":
public class ProfilePhotos
{
public int Id { get; set; }
public string ImageUrl { get; set; }
public int ProfileId { get; set; }
public Profile Profile { get; set; }
}
I want to get all profile photos so I created a endpoint to to that:
[HttpGet("{username}/photos")]
public IActionResult GetPhotos(string username)
{
var profilePhotos = _profileService.GetAllPhotos(username);
var model = _mapper.Map<IList<ProfilePhotosModel>>(profilePhotos);
return Ok(model);
}
To get all photos I use a method from "profileService":
public IEnumerable<ProfilePhotos> GetAllPhotos(string username)
{
return _context.ProfilePhotos.Include(a=>a.Profile).ThenInclude(b=>b.User).Where(x => x.Profile.User.Username == username);
}
On response I want to get a id of photo, photoUrl and username so I mapped my profile photos to "ProfilePhotosModel"
public class ProfilePhotosModel
{
public int Id { get; set; }
public string ImageUrl { get; set; }
public string Username { get; set; }
}
but unfortunately on response I only get Id and photoUrl. The username is null :(
What am I doing wrong?
You could add custom mapping for the Username property.
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ProfilePhotos, ProfilePhotosModel>()
.ForMember(m => m.Username, exp => exp.MapFrom(p => p.Profile.User.Username));
});