Listbox per MVC 6 EF 7 Proprietà non popolate

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

Domanda

Ho cercato per un po 'di tempo per ottenere una casella di riepilogo da compilare e non riesco a capirlo. Ho studiato la documentazione di entity framework 7 in modo abbastanza estensivo, ma ne sono ancora nuovo. Non ci sono molti tutorial per MVC6 / EF7, quindi è stato difficile sapere quale sia la migliore pratica per associare una classe di entità con un'istanza di un'altra. Per favore, scusa la lunghezza della domanda, sto solo cercando di essere esauriente.

Sto usando entity framework 7, asp.net 5 e MVC 6.

Passaggi per riprodurre il problema

  1. Creare una nuova applicazione Web ASP.Net â † 'Nome del progetto: ListBox.Web â †' Nome della soluzione ListBox
  2. Scegli Modelli APS.NET 5 â † ' Applicazione Web
  3. Crea due classi nella cartella Modelli

    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; }
        }
    }
    

    Child.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. Crea controller e viste per ciascuna classe di dati usando lo scaffolding Controller per impalcature

  5. Aggiungi collegamenti ai controller in _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. Crea il database

    ListBox\src\ListBox.Web>dns ef migrations add Initial
    ListBox\src\ListBox.Web>dnx ef database update     
    
  7. Esegui l'applicazione web

  8. Aggiungi un paio di genitori.

    inserisci la descrizione dell'immagine qui

  9. Tentativo di aggiungere un bambino.

    • Viene visualizzata una casella di rilascio per i genitori ma non ci sono elementi nella casella di selezione da selezionare
    • inserisci la descrizione dell'immagine qui
    • L'HTML per la casella di riepilogo è: <select class="form-control" data-val="true" data-val-required="The ParentId field is required." id="ParentId" name="ParentId"></select>

Codice sorgente del controller

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");
        }
    }
}

Bambino 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>
}

Risposta accettata

Cambia il metodo Create() in ChildrenController , cambia

    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();
    }

In Create.cshtml , cambia

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

a

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

Risposta popolare

Il codice generato non è corretto, è un bug https://github.com/aspnet/Scaffolding/issues/149

Una soluzione che utilizza "tag helper" è:

controllore

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

vista

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



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché