CodeProg
CodeProg

Reputation: 129

ModelState.isValid()==False + Required-notation

I am using Identity framework for my project and have added some properties such as JobExperience to the User class.

A user should have the possibility of adding a JobExperience to their User. Naturally, that means that a JobExperience shouldn't be able to exist without the User.

For that reason I am using the [Required]-notation in my JobExperienceclass

JobExperience class

public class JobExperience
{
    public int JobExperienceId { get; set; }
    public string Employer { get; set; }
    public DateTime? DateOfEmployment { get; set; }
    public DateTime? DateOfExit { get; set; }
    public ICollection<Subject> Subjects { get; set; }
    [Required]
    public virtual User ApplicationUser { get; set; }
}

User class

public class User : IdentityUser
{
    public Boolean Available { get; set; }
    public Boolean ActivelySeeking { get; set; }
    public Boolean AcceptedUseOfData { get; set; }
    public int ExpectedHourlySalary { get; set;}
    public Boolean Gender { get; set;}
    public DateTime? DateOfBirth { get; set; }
    public String FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<JobExperience> JobExperiences { get; set; }
    public ICollection<Language> Languages { get; set; }
    public ICollection<Certificate> Certificates { get; set; }
}

Scaffolded JobExperienceController - Create method

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "JobExperienceId,Employer,DateOfEmployment,DateOfExit")] JobExperience jobExperience)
{
    var UserId = User.Identity.GetUserId();
    jobExperience.ApplicationUser = db.Users.Where(x => x.Id == UserId).First();

    if (ModelState.IsValid)
    {
       db.JobExperiences.Add(jobExperience);
       db.SaveChanges();
       return RedirectToAction("Index");
    }

    return View(jobExperience);
}

After having added the Required-notation the modelstate.isValid() in the create method returns false. I'm guessing it needs to receive a reference to the User but I have no idea how to go about it. The current attempt is the LINQ-expression shown.

ApplicationUserDb

 public class ApplicationUserDb : IdentityDbContext<User>
{

    public virtual DbSet<JobExperience> JobExperiences { get; set; }
    public virtual DbSet<Language> Languages { get; set; }
    public virtual DbSet<Certificate> Certificates { get; set; }

    public ApplicationUserDb() : base("DefaultConnection")
    {

    }

    internal static ApplicationUserDb Create()
    {
        return new ApplicationUserDb();
    }

}

Upvotes: 1

Views: 138

Answers (1)

Georg Patscheider
Georg Patscheider

Reputation: 9463

You want to model the relationship between User <-> JobExperience as 1 (required) <-> 0-N (optional list). You will not achieve this by marking the ApplicationUser as [Required]. Instead, configure the multiplicity constraints in the ModelBuilder and remove the [Required] attribute.

ModelBuilder.Entity<User>()
   .HasMany(u => u.JobExperiences)
   .WithRequired(j => j.ApplicationUser)
   .WillCascadeOnDelete(true);

Tutorial: Configure One-to-Many Relationships in EF 6.

As a further note, you should introduce ViewModels instead of binding your Entity Models to the controller. This way you will not mix annotations that are used for frontend validation (e.g. [Required]) and annotations that are used for data persistance (e.g. [ForeignKey]).

If User inherits from IdentityUser, also make sure to call the base.OnModelCreating(modelBuilder) in your ModelBuilder (see EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType ).

Upvotes: 3

Related Questions