Click here to Skip to main content
15,312,535 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I'm somewhat new to MVC and have been following along with a tutorial but it has no answers regarding my question. For my Create page, the Foreign keys are not showing up. Basically, on the Projects page I created a project, on the People page I created a person. So when I try to create a ProjectRole on the ProjectRoles page, the ProjectId and PersonId are not showing up in the drop-down menu. Down below all of my code, I have provided a screenshot of what I have tried to put into words.

What I have tried:

I have tried:

Models:
public class Project
{
    public int Id { get; set; }

    [Required]
    [MaxLength(30)]
    public string Name { get; set; }

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

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

    public ICollection<ProjectRole> ProjectRoles { get; set; }
}

public class Person
{
    public int Id { get; set; }

    [Required]
    [MaxLength(30)]
    public string FirstName { get; set; }

    [Required]
    [MaxLength(30)]
    public string MiddleName { get; set; }

    [Required]
    [MaxLength(30)]
    public string LastName { get; set; }

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

    public ICollection<ProjectRole> ProjectRoles { get; set; }
}
public class ProjectRole
{
    public int Id { get; set; }

    [Required]
    public double HourlyRate { get; set; }

    [ForeignKey("Person")]
    public int PersonId { get; set; }

    [ForeignKey("Project")]
    public int ProjectId { get; set; }

    [ForeignKey("AppRole")]
    public int RoleId { get; set; }

}

Controller:
<pre>public IActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,HourlyRate,PersonId,ProjectId,RoleId")] ProjectRole projectRole)
{
    if (ModelState.IsValid)
    {
        _context.Add(projectRole);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(projectRole);
}

View:
<pre>@model Project2.Models.Entities.ProjectRole

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>ProjectRole</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="HourlyRate" class="control-label"></label>
                <input asp-for="HourlyRate" class="form-control" />
                <span asp-validation-for="HourlyRate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="PersonId" class="control-label"></label>
                <select asp-for="PersonId" class ="form-control" asp-items="ViewBag.PersonId"></select>
            </div>
            <div class="form-group">
                <label asp-for="ProjectId" class="control-label"></label>
                <select asp-for="ProjectId" class ="form-control" asp-items="ViewBag.ProjectId"></select>
            </div>
            <div class="form-group">
                <label asp-for="RoleId" class="control-label"></label>
                <input asp-for="RoleId" class="form-control" />
                <span asp-validation-for="RoleId" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Screenshot of example of what I mean
Posted
Updated 2-Nov-21 0:02am

1 solution

You're not populating the ViewBag collections used in your view. Either the tutorial you're following hasn't got to that part yet, or it's not a good tutorial.

Create a method in your controller to populate the lookups, and call it before displaying the view.
C#
private void PopulateLookups(ProjectRole role)
{
    var projects = _context.Projects.OrderBy(p => p.Name).ToList();
    ViewBag.ProjectId = projects.Select(p => new SelectListItem
    {
        Value = p.Id.ToString(),
        Text = p.Name,
        Selected = p.Id == role.ProjectId,
    });
    
    var people = _context.People.OrderBy(p => p.LastName).ThenBy(p => p.FirstName).ToList();
    ViewBag.PersonId = people.Select(p => new SelectListItem
    {
        Value = p.Id.ToString(),
        Text = $"{p.LastName}, {p.FirstName} {p.MiddleName}",
        Selected = p.Id == role.PersonId,
    });
}

[HttpGet]
public IActionResult Create()
{
    ProjectRole model = new ProjectRole();
    PopulateLookups(model);
    return View(model);
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,HourlyRate,PersonId,ProjectId,RoleId")] ProjectRole projectRole)
{
    if (ModelState.IsValid)
    {
        _context.Add(projectRole);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    
    PopulateLookups(projectRole);
    return View(projectRole);
}
The Select Tag Helper | Tag Helpers in forms in ASP.NET Core | Microsoft Docs[^]
   
Comments
mrnewguy2020 2-Nov-21 16:37pm
   
You are a life saver. Much appreciated!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900