locked
[Identity] How to correctly link an entity to an Identity User ? RRS feed

  • Question

  • User-1370514677 posted

    Hi everyone,

    I have some issues linking / using a Foreign Key between a Message entity and an Identity User entity :

    User.cs

    using Microsoft.AspNetCore.Identity;
    
    namespace Blog.Models
    {
        public class User : IdentityUser
        {
            // Identity fields
            public byte[] Avatar { get; set; }
        }
    }

    Message.cs

    using System.ComponentModel.DataAnnotations;
    
    namespace Blog.Models
    {
        public class Message
        {
            [Key]
            public int Id { get; set; }
    [Required] public User Author { get; set; }
    public string Text { get; set; } } }

    MessageController.cs

            [HttpPost]
            public async Task<IActionResult> PublishMessage(string Text)
            {
                var new_message = new Message{
                    Author = await _usermanager.GetUserAsync(User),
                    Text = Text
                };
    
                System.Console.WriteLine("new_message.Author.UserName = " + new_message.Author.UserName);
                System.Console.WriteLine("new_message.Author.Avatar = " + new_message.Author.Avatar);
                System.Console.WriteLine("new_message.Text = " + new_message.Text);
    
                _context.Add(new_message);
                await _context.SaveChangesAsync();
    
                return RedirectToAction("Index", "Home");
            }

    If one runs the PublishMessage() method above, it will work 100% : 

    > new_message.Author.UserName = test@mail.com
    > new_message.Author.Avatar = System.byte[]
    > new_message.Text = Hello World

    This shows that the new_message object contains a non null reference to current Identity's User.

    Yet, when I load my Index.cshtml page : 

    HomeController.cs

    using System.Linq;
    using Blog.Data;
    using Microsoft.AspNetCore.Mvc;
    
    namespace Blog.Controllers
    {
        public class HomeController : Controller
        {
            private readonly AppDbContext _context;
    
            public HomeController(AppDbContext context)
            {
                _context = context;
            }
            
            public IActionResult Index()
            {
                ViewData["message_list"] = _context.Message.ToList();
    
                return View();
            }
        }
    }

    Index.cshtml

            <div id="page_messages">
            @foreach(var message in (List<Message>)ViewData["message_list"])
            {
                <div class="message">
                    <div class="message_header">
                        <p>@message.Author.UserName</p>
                    </div>
                    <p>@message.Text</p>
                </div>
            }
            </div>

    I get a NullReferenceException..

    I've been searching on the web and couldn't find a clue.

    Except a topic here : How to assign ASP.NET Identity User Id as foreign key to another table? | The ASP.NET Forums

    Thank you in advance

    Thursday, January 21, 2021 9:41 AM

Answers

All replies

  • User475983607 posted

    Lazy loading in EF Core is not enabled by default.  The following link explains how to load related data in EF Core; https://docs.microsoft.com/en-us/ef/core/querying/related-data/

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, January 21, 2021 12:34 PM
  • User-1370514677 posted

    Hi @mgebhard,

    Thanks a lot for your answer, it works !

    So I added the "virtual" keyword t the ForeignKey :

    using System.ComponentModel.DataAnnotations;
    
    namespace Blog.Models
    {
        public class Message
        {
            [Key]
            public int Id { get; set; }
            [Required]
            public virtual User Author { get; set; }
            public string Text { get; set; }
        }
    }

    And added LazyLoadingProxies in Startup.cs :

                services.AddDbContext<AppDbContext>(options =>
                    options.UseLazyLoadingProxies()
                            .UseSqlite(_configuration.GetConnectionString("AppDbContext"))
                );

    Why do we need to do that in EF Core by the way ? If I compare it to Django with Python, I just add to call the entity and that was all, is there any security reasons ? (Just curious about it)

    Thursday, January 21, 2021 1:56 PM
  • User475983607 posted

    Why do we need to do that in EF Core by the way ? If I compare it to Django with Python, I just add to call the entity and that was all, is there any security reasons ? (Just curious about it)

    The link in my first post explains the hazards of lazy loading and explains why lazy loading is not enabled by default in EF Core.

    Thursday, January 21, 2021 3:32 PM