Home > front end >  ASP.NET model that requires a reference to a IdentityUser?
ASP.NET model that requires a reference to a IdentityUser?

Time:05-12

I have a model Blueprint that requires a reference to an IdentityUser. When I run Add-Migration CreateBlueprintSchema the following error is thrown:

No suitable constructor was found for entity type 'Blueprint'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'author' in 'Blueprint(IdentityUser author, string name, string data)'.

How do I resolve this issue?

Blueprint.cs

using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
using System.Text;

namespace FactorioStudio.Models
{
    public class Blueprint
    {
        [MaxLength(40)]
        public string Id { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public string Data { get; set; }

        [Required]
        public IdentityUser Author { get; set; }

        [Required]
        public DateTime CreationDate { get; set; }

        public Blueprint? ParentBlueprint { get; set; }

        public Blueprint(IdentityUser author, string name, string data)
        {
            Author = author;
            Name = name;
            Data = data;
            CreationDate = DateTime.UtcNow;

            string hashSource = Author.Id  
                Name  
                CreationDate.ToString("s", System.Globalization.CultureInfo.InvariantCulture)  
                Data;

            using SHA1 sha1 = SHA1.Create();
            byte[] hashBytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(hashSource));
            string hash = BitConverter.ToString(hashBytes).Replace("-", String.Empty).ToLower();
            Id = hash;
        }
    }
}

CodePudding user response:

change your model like this:

public class Blueprint
    {
        [MaxLength(40)]
        public string Id { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public string Data { get; set; }

        [Required]
        public IdentityUser Author { get; set; } = new IdentityUser();

        //.......
   }

or just add a non-parameter constructor in your model.

You can refer to enter image description here

CodePudding user response:

Like I wrote in comment, EF Core cannot set navigation properties using a constructor. Instead, use a custom value generator.

    public class BlueprintHashGenerator : ValueGenerator<string>
    {
        public override bool GeneratesTemporaryValues => false;

        public override string Next(EntityEntry entry)
        {
            if (entry.Entity is not Blueprint bp)
            {
                throw new ApplicationException("Unexpected entity");
            }

            string hashSource = bp.Author.Id  
                bp.Name  
                bp.CreationDate.ToString("s", System.Globalization.CultureInfo.InvariantCulture)  
                bp.Data;

            using SHA1 sha1 = SHA1.Create();
            byte[] hashBytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(hashSource));
            return BitConverter.ToString(hashBytes).Replace("-", String.Empty).ToLower();
        }
    }

then in model builder

builder.Entity<Blueprint>().Property(bp => bp.Id).HasValueGenerator<BlueprintHashGenerator>().ValueGeneratedNever();

It will generate the value on SaveChanges, so ensure all properties are set before calling save (Author, Name, CreationDate, Data).

  • Related