J'ai donc ces 2 classes représentant des tables dans une base de données locale à l'aide de la migration de base ef dans une application de base asp.net
<form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Teacher" class="control-label"></label> <select asp-for="Teacher" class ="form-control" asp-items="ViewBag.Teachers"></select> </div> <div class="form-group"> <label asp-for="Name" class="control-label"></label> <input asp-for="Name" class="form-control" /> <span asp-validation-for="Name" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-default" /> </div> </form>
et
public IActionResult Create() { var teachers = from s in _context.Teachers where s.Class == null select s; ViewData["Teachers"] = new SelectList(teachers.ToList()); return View(); } [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(Class @class) { if (ModelState.IsValid) { @class.TeacherID = @class.Teacher.ID; _context.Add(@class); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View("Index"); }
Je veux ajouter dans mon contrôleur de classes la fonctionnalité pour créer une nouvelle instance de la classe "Classe" en tapant un nom dans une zone de texte et en sélectionnant un enseignant dans une liste déroulante.
Voici mon créer des méthodes http get & post
public class Class { public int ID { get; set; } public int TeacherID { get; set; } public string Name { get; set; } public Teacher Teacher { get; set; } public ICollection<Student> Students { get; set; } }
et le formulaire de soumission de données saisies par l'utilisateur
public class Teacher { public int ID { get; set; } public string FistName { get; set; } public string LastName { get; set; } public Class Class { get; set; } public string FullName { get { return $"{LastName} {FistName}"; } } public override string ToString() { return FullName; } }
Je vois le bon données dans la liste déroulante mais pour une raison quelconque dans la méthode POST @ class.Teacher est nul. Qu'est-ce que je fais mal?
4 Réponses :
Une liste de sélection ne renverra qu'un type primitif (string, int, etc.), pas une instance de classe entière. En conséquence, vous devrez lier la valeur à une propriété qui est également un type primitif. Puisque vous avez déjà une propriété TeacherID
, vous pouvez simplement l'utiliser. Lorsque vous enregistrez, EF corrigera la référence Teacher
avec l'ID correspondant.
<select asp-for="TeacherID" class ="form-control" asp-items="ViewBag.Teachers"></select>
Ok, je l'ai fait, mais maintenant ModelState.IsValid est désactivé et si j'utilise le débogueur, je peux voir que la valeur TeacherID dans la méthode POST est 0, même si mon enseignant sélectionné a un ID de 2
et c'est parce que l'élément sélectionné dans la liste déroulante se traduit en une chaîne .. et ensuite il essaie de le mapper à la propriété TeacherID qui est un int. Existe-t-il un moyen d'afficher la propriété du nom complet dans la liste déroulante mais de mapper correctement l'identifiant de l'enseignant?
"Teacher"
est une classe complexe, qui sera toujours nulle, je pense que vous êtes confus, remplacez "Teacher"
par "teacherID"
. EF fera le travail.
Commencez par mettre à jour votre méthode Create
GET
comme suit:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(Class @class) { if (ModelState.IsValid) { _context.Classes.Add(@class); // now your @class is containing the `TeacheID` value selected from drop-down. await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View("Index"); }
Ensuite, écrivez votre FormGroup
pour sélectionnez la liste comme suit:
<div class="form-group"> <label asp-for="TeacherID" class="control-label">Teacher</label> <select asp-for="TeacherID" class ="form-control" asp-items="ViewBag.Teachers"> </select> <span asp-validation-for="TeacherID" class="text-danger"></span> </div>
Maintenant, mettez à jour votre méthode Create
POST
comme suit:
public async Task<IActionResult> Create() { var teachers = await _context.Teachers.Where(t => t.Class == null).ToListAsync(); ViewData["Teachers"] = new SelectList(teachers,"ID","FullName"); return View(); }
Maintenant, tout devrait bien fonctionner!
Apportez les modifications suivantes
Créez la méthode http get, affichez SelectList Class , définissez ID
sur le dataValueField
de la selectList et définissez FullName code > au
dataTextField
de selectList
<select asp-for="TeacherID" class="form-control" asp-items="ViewBag.Teachers"></select>
La balise de sélection dans le formulaire
public IActionResult Create() { var teachers = from s in _context.Teacher where s.Class == null select s; ViewData["Teachers"] = new SelectList(teachers.ToList(),"ID","FullName"); return View(); }