Derek Stegelman

Foreign Key Dropdowns with .NET MVC 5

Winter in the Mountains

One of the more difficult form controls in web development is adding drop downs for foreign key relationships. .NET MVC gives you several different options for generating form markup from different types of models. However, the method for foreign keys and drop down lists is a bit more work than the rest.

Given the following models:

JobPosting.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace CMJobs.Models
{
    public class JobPosting
    {
        public JobPosting()
        {
            this.IsDeleted = false;
        }

        public int ID { get; set; }
        public string PositionTitle { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public string JobDescription { get; set; }
        public int CompanyID { get; set; }
        public virtual Company Company { get; set; }
        public int? CategoryID { get; set; }
        public virtual Category Category { get; set; }
        public bool IsDeleted { get; set; }
    }
}

Company.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace CMJobs.Models
{
    public class Company
    {
        public Company()
        {
            this.IsDeleted = false;
        }

        public int ID { get; set; }
        public string CompanyName { get; set; }
        public string ContactFirstName { get; set; }
        public string ContactLastName { get; set; }
        public string ContactEmail1 { get; set; }
        public string ContactEmail2 { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
        public string ZipCodeExtension { get; set; }
        public string PhoneNumber { get; set; }
        public string PhoneNumberExtension { get; set; }
        public string FaxNumber { get; set; }
        public bool IsDeleted { get; set; }

    }
}

Within the controller for adding a new JobPosting. This controller action is the initial blank form for creating a new Job Posting object.

// AdminJobPostingController.cs

public ActionResult New()
{
    this.PopulateCompanySelectList();
    this.PopulateCategorySelectList();
    return View();
}

As you can see this calls to private methods that will populate our two foreign key relationships.

// AdminJobPostingController.cs

private void PopulateCategorySelectList(object selectedItem = null)
{
    ViewBag.CategoryDropDown = new SelectList(this._categoryRepository.GetCategories(), "ID", "Name", selectedItem);
}


private void PopulateCompanySelectList(object selectedItem = null)
{
    ViewBag.CompanyDropDown = new SelectList(this._companyRepository.GetCompanies(), "ID", "CompanyName", selectedItem);
}

In addition, when you want to start editing entries, you'll need to pass in the object to the select list as well.

// AdminJobPostingController.cs

public ActionResult Edit(int id)
{
    JobPosting jobPosting = this._jobRepository.GetJobPosting(id);
    CreateEditJobPostingViewModel jobViewModel = new CreateEditJobPostingViewModel();

    jobViewModel.ID = jobPosting.ID;
    jobViewModel.PositionTitle = jobPosting.PositionTitle;
    jobViewModel.StartDate = jobPosting.StartDate;
    jobViewModel.EndDate = jobPosting.EndDate;
    jobViewModel.JobDescription = jobPosting.JobDescription;

    this.PopulateCompanySelectList(jobPosting.Company);
    this.PopulateCategorySelectList(jobPosting.Category);

    jobViewModel.CompanyId = jobPosting.Company.ID;
    jobViewModel.CategoryId = jobPosting.Category.ID;

    return View(jobViewModel);
}

We now need to turn our attention to the form and rendering the controls in the views.

Form.cshtml

<!-- These two elements are the dropdown controls -->

<div class="form-group">
    @Html.LabelFor(model => model.CategoryId, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-5">
        @Html.DropDownListFor(model => model.CategoryId, (IEnumerable<SelectListItem>)ViewBag.CategoryDropDown, new { @class = "form-control selectpicker" })
        @Html.ValidationMessageFor(model => model.CategoryId, "", new { @class = "text-danger" })
    </div>
</div>


<div class="form-group">
    @Html.LabelFor(model => model.CompanyId, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-5">
        @Html.DropDownListFor(model => model.CompanyId, (IEnumerable<SelectListItem>) ViewBag.CompanyDropDown, new { @class = "form-control selectpicker", @data_live_search = "true" })
        @Html.ValidationMessageFor(model => model.CompanyId, "", new { @class = "text-danger" })
    </div>
</div>