Search code examples
c#asp.net-mvcentity-frameworkasp.net-mvc-5dropdownlistfor

Dropdown of associated entities using MVC 5 and Entity framework


I'm using MVC 5 and Entity Framework. I have 2 entities, a Person and a PersonType. I have created an Association between them, so that a Person has a PersonType property :

namespace Test.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Person
    {
        public int PersonId { get; set; }
        public virtual PersonType personType { get; set; }
    }
}

This code was generated by the Entity Data Model (.edmx).

In the controller, I then add all the PersonTypes to a ViewBag, so that they can be added to a dropdown control in the page :

ViewBag.PersonTypeList = new SelectList(db.PersonTypes, "Id", "Description");

The model for the page is set to 'Person' and contains a dropdown :

<div class="form-group">
    @Html.LabelFor(model => model.personType, "Person Type", htmlAttributes: new { @class = "control-label col-md-4" })
    <div class="col-md-8">
        @Html.DropDownListFor(model => model.personType.Id, ViewBag.PersonTypeList as SelectList, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.personType.Id, "", new { @class = "text-danger" })
    </div>
</div>

This seems to work OK, but when it comes to saving the Person it seems to be trying to create a new PersonType using the Id I selected, rather than simply referencing the one that exists in the PersonType table already? Am I doing this wrong? Many Thanks


Solution

  • If you set up the relation using an .edmx file, you should also get a FK property, e.g. myPerson.PersonType_Id (usually the name is {classname}_{PKfieldname}).
    If that field already exists, assign the chosen ID from the dropdownlist to that property.

    However, there is a bug in the edmx generation.

    I noticed this about a year ago, and it only occurs under very specific circumstances.

    When you set up a relation via an .edmx (Right click > Add > Association...), you will get a window asking you to select the two entities you wish to relate.

    Random example image found online.

    For 1-to-many relations, you must make sure the MANY-entity is on the right side of that window. (just like in the image above)

    The wizard perfectly allows you to do the opposite (basically setting up a many-to-1, if you read it from left to right). If you do this, that secondary FK field I mentioned will not be set up.

    When that field is not set up, and you try to add it via the .PersonType field instead, it seems that EF often tries to create the object.

    To fix this, you'll have to remove the association, and add it again when the MANY entity is on the right side of the window.

    For your case, that means PersonType should be on the left, Person should be on the right.

    When that is done, have your dropdownlist fill in the PersonType_Id field (should be an int if you use default PKs). Leave the PersonType property blank, and save the Person object you just created.
    EF should then correctly look for an existing PersonType instead of trying to create a new one.

    Can you confirm if this solution works for you?