Cuadro de lista para la propiedad MVC 6 EF 7 no se llena

asp.net-core-mvc asp.net-mvc-scaffolding entity-framework-core

Pregunta

He estado intentando durante un tiempo obtener un cuadro de lista para poblar y parece que no puedo resolverlo. He estudiado la documentación de Entity Framework 7 de forma bastante extensa, pero todavía soy nuevo en ello. No hay muchos tutoriales para MVC6 / EF7, por lo que es difícil saber cuál es la mejor práctica para asociar una clase de entidad con una instancia de otra. Por favor, disculpe la longitud de la pregunta, solo estoy tratando de ser cuidadoso.

Estoy usando Entity Framework 7, asp.net 5 y MVC 6.

Pasos para reproducir el problema

  1. Cree una nueva aplicación web ASP.Net â † 'Nombre del proyecto: ListBox.Web â †' Nombre de la solución ListBox
  2. Elija APS.NET 5 Plantillas â † ' Aplicación Web
  3. Crea dos clases en la carpeta de Modelos

    Parent.cs

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace ListBox.Web.Models
    {
        public class Parent
        {
            public int ParentId { get; set; }
            [Required]
            public string Name { get; set; }
            public ICollection<Child> Children { get; set; }
        }
    }
    

    Niño.cs

    using System.ComponentModel.DataAnnotations;
    
    namespace ListBox.Web.Models
    {
        public class Child
        {
            public int ChildId { get; set; }
            [Required]
            public string Name { get; set; }
            public int ParentId { get; set; }
            public Parent Parent { get; set; }
        }
    }
    
  4. Cree controladores y vistas para cada una de las clases de datos mediante el uso de andamios. Controlador de andamios

  5. Agregue enlaces a los controladores en _Layout.cshtml

                <ul class="nav navbar-nav">
                    <li><a asp-controller="Home" asp-action="Index">Home</a></li>
                    <li><a asp-controller="Parents" asp-action="Index">Parents</a></li>
                    <li><a asp-controller="Children" asp-action="Index">Children</a></li>
                    <li><a asp-controller="Home" asp-action="About">About</a></li>
                    <li><a asp-controller="Home" asp-action="Contact">Contact</a></li>
                </ul>
    
  6. Crear la base de datos

    ListBox\src\ListBox.Web>dns ef migrations add Initial
    ListBox\src\ListBox.Web>dnx ef database update     
    
  7. Ejecutar la aplicación web.

  8. Añadir un par de padres.

    introduzca la descripción de la imagen aquí

  9. Intenta añadir un niño.

    • Se muestra un cuadro desplegable para los padres, pero no hay elementos en el cuadro desplegable para seleccionar
    • introduzca la descripción de la imagen aquí
    • El HTML para el cuadro de lista es: <select class="form-control" data-val="true" data-val-required="The ParentId field is required." id="ParentId" name="ParentId"></select>

Código fuente del controlador

using System.Linq;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Data.Entity;
using ListBox.Web.Models;

namespace ListBox.Web.Controllers
{
    public class ChildrenController : Controller
    {
        private ApplicationDbContext _context;

        public ChildrenController(ApplicationDbContext context)
        {
            _context = context;    
        }

        // GET: Children
        public IActionResult Index()
        {
            var applicationDbContext = _context.Child.Include(c => c.Parent);
            return View(applicationDbContext.ToList());
        }

        // GET: Children/Details/5
        public IActionResult Details(int? id)
        {
            if (id == null)
            {
                return HttpNotFound();
            }

            Child child = _context.Child.Single(m => m.ChildId == id);
            if (child == null)
            {
                return HttpNotFound();
            }

            return View(child);
        }

        // GET: Children/Create
        public IActionResult Create()
        {
            ViewData["ParentId"] = new SelectList(_context.Set<Parent>(), "ParentId", "Parent");
            return View();
        }

        // POST: Children/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(Child child)
        {
            if (ModelState.IsValid)
            {
                _context.Child.Add(child);
                _context.SaveChanges();
                return RedirectToAction("Index");
            }
            ViewData["ParentId"] = new SelectList(_context.Set<Parent>(), "ParentId", "Parent", child.ParentId);
            return View(child);
        }

        // GET: Children/Edit/5
        public IActionResult Edit(int? id)
        {
            if (id == null)
            {
                return HttpNotFound();
            }

            Child child = _context.Child.Single(m => m.ChildId == id);
            if (child == null)
            {
                return HttpNotFound();
            }
            ViewData["ParentId"] = new SelectList(_context.Set<Parent>(), "ParentId", "Parent", child.ParentId);
            return View(child);
        }

        // POST: Children/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Edit(Child child)
        {
            if (ModelState.IsValid)
            {
                _context.Update(child);
                _context.SaveChanges();
                return RedirectToAction("Index");
            }
            ViewData["ParentId"] = new SelectList(_context.Set<Parent>(), "ParentId", "Parent", child.ParentId);
            return View(child);
        }

        // GET: Children/Delete/5
        [ActionName("Delete")]
        public IActionResult Delete(int? id)
        {
            if (id == null)
            {
                return HttpNotFound();
            }

            Child child = _context.Child.Single(m => m.ChildId == id);
            if (child == null)
            {
                return HttpNotFound();
            }

            return View(child);
        }

        // POST: Children/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public IActionResult DeleteConfirmed(int id)
        {
            Child child = _context.Child.Single(m => m.ChildId == id);
            _context.Child.Remove(child);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }
    }
}

Child Create.cshtml

@model ListBox.Web.Models.Child

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

<h2>Create</h2>

<form asp-action="Create">
    <div class="form-horizontal">
        <h4>Child</h4>
        <hr />
        <div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div>
        <div class="form-group">
            <label asp-for="Name" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="Name" class="form-control" />
                <span asp-validation-for="Name" class="text-danger" />
            </div>
        </div>
        <div class="form-group">
            <label asp-for="ParentId" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <select asp-for="ParentId" class ="form-control"></select>
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
</form>

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

@section Scripts {
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
}

Respuesta aceptada

Cambie el método Create() en ChildrenController , cambie

    public IActionResult Create()
    {
        ViewData["ParentId"] = new SelectList(_context.Set<Parent>(), "ParentId", "Parent");
        return View();
    }

a

    public IActionResult Create()
    {
        ViewData["ParentId"] = new SelectList(_context.Set<Parent>(), "ParentId", "Name");
        return View();
    }

En Create.cshtml , cambiar

<select asp-for="ParentId" class="form-control"></select>

a

@Html.DropDownList("ParentId", null, htmlAttributes: new { @class = "form-control" })

Respuesta popular

El código generado es incorrecto, es un error https://github.com/aspnet/Scaffolding/issues/149

Una solución que usa "ayudantes de etiquetas" es:

Controlador

...
ViewData["Parents"] = new SelectList(_context.Set<Parent>(), "ParentId", "Name", child.ParentId);
...

Ver

@{
    var parents = (IEnumerable<SelectListItem>)ViewData["Parents"];
}
...
<select asp-for="ParentId" asp-items="parents" class ="form-control">
     <option disabled selected>--- SELECT ---</option>
</select>
...



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué