Open Closed

Issue adding user as navigation property from abp suite #338


User avatar
0
KittyJuggins created

When adding the user as a navigation property via the abp suite, there is always a build error pre add-migration. * Severity Code Description Project File Line Suppression State Suppression State Error CS0246 The type or namespace name 'AppUserDto' could not be found (are you missing a using directive or an assembly reference?) VideoMarking.Application.Contracts \aspnet-core\src\VideoMarking.Application.Contracts\Notes\NoteWithNavigationPropertiesDto.cs 12 Active

If we manually add the AppUserDto, the build error goes but when we manually run add-migration it errors with: The property 'AppUser.ExtraProperties' could not be mapped, because it is of type 'Dictionary<string, object>' which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

The AppUserDto looks like this:

    public class AppUserDto : FullAuditedEntityDto<Guid>
    {
        public Guid? TenantId { get; private set; }

        public string UserName { get; private set; }

        public string Name { get; private set; }

        public string Surname { get; private set; }

        public string Email { get; private set; }

        public bool EmailConfirmed { get; private set; }

        public string PhoneNumber { get; private set; }

        public bool PhoneNumberConfirmed { get; private set; }


        public bool SEN { get; set; }
        public bool PupilPremium { get; set; }
        public bool EAL { get; set; }
        public bool ChildInCare { get; set; }
        public DateTime DateOfBirth { get; set; }
       }

We have tried adding b.ConfigureExtraProperties(); to the model builder in the dbcontext to no effect as suggested here: https://github.com/abpframework/abp/issues/1517 We have not been able to find a solution to this issue and we require the ability to link numerous entities to the user table.

Please can someone advise the proper way to achieve this.

Thanks

  • ABP Framework version: v3
  • UI type: Angular
  • Tiered (MVC) or Identity Server Seperated (Angular): no

17 Answer(s)
  • User Avatar
    0
    alper created
    Support Team Director

    you need to ignore ExtraProperties like this;

    CreateMap<AppUser, AppUserDto>().Ignore(x => x.ExtraProperties);
    

    check out the following question, similar one https://support.abp.io/QA/Questions/150/How-To-Create-a-Help-Desk-Ticket-Entity#answer-21da8121-ab88-ab2c-67f0-39f51d1b1819

  • User Avatar
    0
    KittyJuggins created

    Hi @Alper,

    Thanks for the response. I've added that line now, and followed step by step using the example given with the suite, but I am still getting the error

    `The property 'AppUser.ExtraProperties' could not be mapped, because it is of type 'Dictionary&lt;string, object&gt;' which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'` on add-migration.
    
    

    The relevant section of my AutoMapperProfile file looks like:

                CreateMap<AppUser, AppUserDto>().Ignore(x => x.ExtraProperties);
    
                CreateMap<NoteCreateDto, Note>().IgnoreFullAuditedObjectProperties().Ignore(x => x.Id).Ignore(x => x.TenantId);
                CreateMap<NoteUpdateDto, Note>().IgnoreFullAuditedObjectProperties().Ignore(x => x.Id).Ignore(x => x.TenantId);
                CreateMap<Note, NoteDto>();
                CreateMap<NoteWithNavigationProperties, NoteWithNavigationPropertiesDto>();
                CreateMap<AppUser, LookupDto<Guid?>>().ForMember(dest => dest.DisplayName, opt => opt.MapFrom(src => src.Name));
    

    Please can you advise, Kitty

  • User Avatar
    0
    alper created
    Support Team Director

    you need to add the below line in BookStoreApplicationAutoMapperProfile.cs

    CreateMap<AppUser, AppUserDto>().Ignore(x => x.ExtraProperties);
    
  • User Avatar
    0
    KittyJuggins created

    As you can see in my previous reply, I have added it in the AutoMapperProfile file already and it still isn't working.

  • User Avatar
    0
    alper created
    Support Team Director

    kitty, there are multiple AutoMapperProfile classes. I just want to ensure that you have added it in the correct project.

  • User Avatar
    0
    KittyJuggins created

    Yes, its in the ApplicationAutoMapperProfile

  • User Avatar
    0
    yekalkan created
    Support Team Fullstack Developer

    Can you share the AppUser entity? And also the code piece which you add it to ModelBuilder in *DbContextModelCreatingExtensions.cs?

    Normally, using ConfigureByConvention should fix this.

    Example:

    
    builder.Entity&lt;IdentityUser&gt;(b =>
                {
                    b.ToTable(options.TablePrefix + "AppUsers", options.Schema);
    
                    .
                    .
                    .
                    b.ConfigureByConvention();
                    .
                    .
                    .
                }
    
  • User Avatar
    0
    KittyJuggins created

    Hi,

    The AppUser entity looks like:

    public class AppUser : FullAuditedAggregateRoot<Guid>, IUser
        {
            #region Base properties
    
            /* These properties are shared with the IdentityUser entity of the Identity module.
             * Do not change these properties through this class. Instead, use Identity module
             * services (like IdentityUserManager) to change them.
             * So, this properties are designed as read only!
             */
    
            public virtual Guid? TenantId { get; private set; }
    
            public virtual string UserName { get; private set; }
    
            public virtual string Name { get; private set; }
    
            public virtual string Surname { get; private set; }
    
            public virtual string Email { get; private set; }
    
            public virtual bool EmailConfirmed { get; private set; }
    
            public virtual string PhoneNumber { get; private set; }
    
            public virtual bool PhoneNumberConfirmed { get; private set; }
    
            #endregion
    
            public virtual bool SEN { get; set; }
            public virtual bool PupilPremium { get; set; }
            public virtual bool EAL { get; set; }
            public virtual bool ChildInCare { get; set; }
            public virtual DateTime DateOfBirth { get; set; }
            
            [ForeignKey("School")]
            public Guid? SchoolId { get; set; }
    
            public virtual School School { get; set; }
    
            [ForeignKey("Address")]
    
            public Guid? AddressId { get; set; }
    
            public virtual Address Address { get; set; }
    
            [ForeignKey("SchoolYear")]
            public Guid? SchoolYearId { get; set; }
    
            public virtual SchoolYear SchoolYear { get; set; }
    
            /* Add your own properties here. Example:
             *
             * public virtual string MyProperty { get; set; }
             * public string MyProperty { get; set; }
             *
             * If you add a property and using the EF Core, remember these;
             *
             * 1. update VideoMarkingDbContext.OnModelCreating
             * to configure the mapping for your new property
             * 2. Update VideoMarkingEfCoreEntityExtensionMappings to extend the IdentityUser entity
             * and add your new property to the migration.
             * 3. Use the Add-Migration to add a new database migration.
             * 4. Run the .DbMigrator project (or use the Update-Database command) to apply
             * schema change to the database.
             */
    
            private AppUser()
            {
                
            }
    

    The OnModelCreating() method looks like:

    protected override void OnModelCreating(ModelBuilder builder)
            {
                base.OnModelCreating(builder);
    
                /* Configure the shared tables (with included modules) here */
    
    
                builder.Entity<AppUser>(b =>
                {
                   
                    b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Users"); //Sharing the same table "AbpUsers" with the IdentityUser
    
                    b.Property(p => p.DateOfBirth);
                    b.Property(p => p.SEN);
                    b.Property(p => p.ChildInCare);
                    b.Property(p => p.PupilPremium);
                    b.Property(p => p.EAL);
    
                    b.ConfigureByConvention();
    
                    b.ConfigureAbpUser();
    
                    
                    /* Configure mappings for your additional properties.
                     * Also see the VideoMarkingEfCoreEntityExtensionMappings class.
                     */
                });
    
                /* Configure your own tables/entities inside the ConfigureVideoMarking method */
    
                builder.ConfigureVideoMarking();
            }
    

    The Notes section in DbContextModelCreatingExtensions:

                builder.Entity<Note>(b =>
                {
                    b.ToTable(VideoMarkingConsts.DbTablePrefix + "Notes", VideoMarkingConsts.DbSchema);
                    b.ConfigureByConvention();
                    b.Property(x => x.TenantId).HasColumnName(nameof(Note.TenantId));
                    b.Property(x => x.Message).HasColumnName(nameof(Note.Message)).IsRequired();
                });
    
  • User Avatar
    0
    alper created
    Support Team Director

    Don't use navigation properties to other aggregate roots. See https://github.com/abpframework/abp/issues/1517

  • User Avatar
    0
    KittyJuggins created

    Note is not an aggregate root, it's a FullAuditedEntity. We need to be able to link user to it. Please can you advise on how we need to actually implement this.

    using VideoMarking.Users;
    using System;
    using Volo.Abp.Domain.Entities;
    using Volo.Abp.Domain.Entities.Auditing;
    using Volo.Abp.MultiTenancy;
    using JetBrains.Annotations;
    using Volo.Abp;
    
    namespace VideoMarking.Notes
    {
        public class Note : FullAuditedEntity<Guid>, IMultiTenant
        {
            public virtual Guid? TenantId { get; set; }
    
            [NotNull]
            public virtual string Message { get; set; }
            public Guid? AppUserId { get; set; }
    
            public AppUser AppUser { get; set; }
    
            public Note()
            {
    
            }
    
            public Note(Guid id, string message)
            {
                Id = id;
                Check.NotNull(message, nameof(message));
                Message = message;
            }
        }
    }
    
  • User Avatar
    0
    alper created
    Support Team Director

    @KittyJuggins , remove AppUser from Note and keep the AppUserId only. When you fetch Note from database, fetch the user in a seperate query . Then map the both to your DTO. This is the best practise

  • User Avatar
    1
    myke@mycra.co created

    Hey all, I have been following this thread and several similar to it for a while to try and solve the issue I am having of adding a Navigation Property to a User. I must be missing something really simple because no matter what I try I cannot get it to work. I decided to start from scratch with a blank project and take a screen recording of it to upload in hopes you can point out where I am going wrong. And hopefully this helps out everyone else with the issue.

    Here is the video. https://www.youtube.com/watch?v=i1VH8B06njs

    Started from scratch with ABP Suite

    • Created an Entity called "Note"
    • Added a property called Title
    • Generated
    • Rebuilt web project to ensure it worked
    • Added a DTO class
    • Added CreateMap and ignored the ExtraProperties
    • Added navigation property via ABP Suite for a User based on the screnshots provided HERE
    • Generated updates
    • Tweaked a couple of Menu related issues due to regeneration
    • Ran generation again and this is where the Extra Properties mapping issues comes in

    Not seen in the video is the suggestion of removing public AppUser AppUser { get; set; } from the Notes class. I do this, but it gets added back on while generating, which makes sense. I have only ever tried creating an Entity as a FullAuditedAggregateRoot because I want all the properties and features that come along with that. But I can see the OP states that this issue still persists even with a FullAuditedEntity.

  • User Avatar
    0
    alper created
    Support Team Director

    hi myke@mycra.co I just made a sample project for this topic. See https://community.abp.io/articles/how-to-add-the-user-entity-as-a-navigation-property-furp75ex


    Note this example is implemented with ABP Commercial 3.1.0-rc.3. This is a RC version. If you want to install the CLI and Suite RC version follow the next steps:

    1- Uninstall the current version of the CLI and install the specific RC version:

    dotnet tool uninstall --global Volo.Abp.Cli && dotnet tool install --global Volo.Abp.Cli --version 3.1.0-rc.3
    

    2- Uninstall the current version of the Suite and install the specific RC version:

    dotnet tool uninstall --global Volo.Abp.Suite && dotnet tool install -g Volo.Abp.Suite --version 3.1.0-rc.3 --add-source https://nuget.abp.io/<YOUR-API-KEY>/v3/index.json
    

    Don't forget to replace the <YOUR-API-KEY> with your own key!

  • User Avatar
    0
    myke@mycra.co created

    I appreciate you putting up an article about this! Is the source code located somewhere for that?

    I went through the steps outlined again(which mirrored the steps I have tried previously) and I end up with the same error as always 😞 Could it be my ABP Commercial version? I am running 3.0.5 on .NET Core 3.1 on macOS.

  • User Avatar
    0
    alper created
    Support Team Director

    I guess it's related a fix that's done in v3.1.0 (because we fixed some Suite issues in 3.1.0) Today we have released a new RC version (preview) of 3.1.0 - RC4 (the production of 3.1.0 will be released this weekend) Try to create a new project with 3.1.0-RC4 and we'll see if it's related with MAC or the framework.

  • User Avatar
    0
    myke@mycra.co created

    Success!!! Updated to the 3.1.0 release from today and this now works as expected. Screen Shot 2020-09-04 at 6.21.53 PM.png

  • User Avatar
    0
    alper created
    Support Team Director

    super! closing this

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11