私は、エンティティを他のエンティティと多対多の関係で更新するフォームを持っており、 select
タグを使用してMultiSelectList
コントロールを作成しようとしていselect
。私はEntity FrameworkでASP.NET Core 1.0を使用しています。
次のエンティティがあるとします。
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public List<StudentCourse> Courses { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Name { get; set; }
public List<StudentCourse> Students { get; set; }
}
public class StudentCourse
{
public int StudentId { get; set; }
public Student Student { get; set; }
public int CourseId { get; set; }
public Course Course { get; set; }
}
ビューモデル:
public class StudentVM
{
public Student Student { get; set; }
public IEnumerable<SelectListItem> CourseList { get; set; }
}
景色:
@model StudentVM
<form asp-action="Edit">
<div class="form-horizontal>
<div class="form-group">
<select asp-for="CourseList" asp-items="Model.CourseList" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
コントローラのアクションメソッド:
[HttpGet]
public async Task<IActionResult> Edit(Student student)
{
var viewmodel = new StudentVM {
Student = student,
CourseList = new MultiSelectList(
_db.Courses,
"Id",
"Name",
student.Courses
.Select(sc => sc.CourseId));
};
return View(viewmodel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(StudentVM viewmodel)
{
if (viewmodel.Student == null)
return NotFound();
if (ModelState.IsValid)
{
Student student = viewmodel.Student;
var newCourses = viewmodel.CourseList
.Where(i => i.Selected)
.Select(c => new StudentCourse {
StudentId = student.Id,
CourseId = Convert.ToInt32(c.Value)
});
student.Courses.RemoveAll(sc => !newCourses.Contains(sc));
student.Courses.AddRange(
newCourses.Where(nc => !student.Courses.Contains(nc)));
_db.Update(student);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewmodel);
}
今質問に来て...
StudentVM
がEdit
のHttpPost
バリアントに入ると、両方のプロパティがnull
。なぜ、 Edit
機能に入る前に、ビューモデルのプロパティがクリアされるのですか? HttpGet
バリアントで正しく設定されていること、およびデータがビューに正しく表示されていることを確認しました。
Edit
入ったデータが無効であるため、データベースの更新をテストできません。 SelectList
から選択したアイテムを取得し、 Student.Courses
アイテムを追加/削除する方法は正しいですか?私はEFコアの多対多関係に関する多くの文書を見つけることができませんでした。
私はむしろASP.NETとEntity Frameworkの新機能ですので、ヒントや批判は大いに感謝しています。
<select>
を複合オブジェクトのコレクションにバインドすることはできません(これはMultiSelectList
とMultiSelectList
です)。 <select multiple>
要素は、選択したオプション値の配列をMultiSelectList
ます(この場合、Courses Id
値の配列になります) 。あなたのモデルは、彼と仮定。にバインドするプロパティを必要とするId
のプロパティCourse
あるint
は、次のプロパティを追加します。
public IEnumerable<int> SelectedCourses { get; set; }
また、 MultiSelectList
コンストラクタでselectedValues
プロパティを設定すると、タグヘルパーによって無視されます(内部的には、プロパティの値に基づいて新しいIEnumerable<SelectListItem>
メソッドが構築selectedValues
ます) MultiSelectList
メソッドのコードは、
var viewmodel = new StudentVM
{
Student = student,
CourseList = new SelectList(_db.Courses, "Id", "Name"),
SelectedCourses = student.Courses.Select(sc => sc.CourseId)
};
return View(viewmodel);
次に、ビューで、
<select asp-for="SelectedCourses" asp-items="Model.CourseList"></select>
また、POSTメソッドでは、 SelectedCourses
の値には、ビューで選択したCourse Id
値の配列が含まれます。