Bölüm 7, Razor ASP.NET Core'da olan EF Core sayfalar - İlgili Verileri Güncelleştirme
Tom Dykstra, Jon P Smith ve Rick Anderson tarafından
Contoso University web uygulaması, ve Visual Studio kullanarak EF Core Sayfalar web uygulamalarının nasıl oluşturulacağını Razor gösterir. Öğretici serisi hakkında bilgi için ilk öğreticiye bakın.
Çözemediğiniz sorunlarla karşılaşırsanız, tamamlanmış uygulamayı indirin ve öğreticiyi izleyerek bu kodu oluşturduğunuz kodla karşılaştırın.
Bu öğreticide ilgili verilerin nasıl güncelleştirilecekleri gösterilmektedir. Aşağıdaki çizimlerde tamamlanan sayfalardan bazıları gösterilmektedir.
Kurs Oluşturma ve Düzenleme sayfalarını güncelleştirme
Kurs Oluşturma ve Düzenleme sayfalarının yapı iskelesi oluşturulmuş kodunda, öğesini int
gösteren DepartmentID
bir Bölüm açılan listesi vardır. Açılan listede Departman adı gösterilmelidir, bu nedenle bu sayfaların her ikisinde de bölüm adları listesi gerekir. Bu listeyi sağlamak için Oluştur ve Düzenle sayfaları için bir temel sınıf kullanın.
Kurs Oluşturma ve Düzenleme için temel sınıf oluşturma
Aşağıdaki kodla bir Pages/Courses/DepartmentNamePageModel.cs
dosya oluşturun:
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace ContosoUniversity.Pages.Courses
{
public class DepartmentNamePageModel : PageModel
{
public SelectList DepartmentNameSL { get; set; }
public void PopulateDepartmentsDropDownList(SchoolContext _context,
object selectedDepartment = null)
{
var departmentsQuery = from d in _context.Departments
orderby d.Name // Sort by name.
select d;
DepartmentNameSL = new SelectList(departmentsQuery.AsNoTracking(),
nameof(Department.DepartmentID),
nameof(Department.Name),
selectedDepartment);
}
}
}
Yukarıdaki kod, bölüm adlarının listesini içeren bir SelectList oluşturur. belirtilirse selectedDepartment
, bu bölüm içinde SelectList
seçilir.
Sayfa modeli oluştur ve düzenle sınıfları'ndan DepartmentNamePageModel
türetilir.
Kurs Oluşturma sayfa modelini güncelleştirme
Bölüme bir Kurs atanır. Oluştur ve Düzenle sayfalarının temel sınıfı, bölümü seçmek için bir SelectList
sağlar. öğesini kullanan SelectList
açılan liste yabancı anahtar (FK) özelliğini ayarlar Course.DepartmentID
. EF CoreCourse.DepartmentID
gezinti özelliğini yüklemek için FK kullanırDepartment
.
Aşağıdaki kodla güncelleştirin Pages/Courses/Create.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Courses
{
public class CreateModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public CreateModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
public IActionResult OnGet()
{
PopulateDepartmentsDropDownList(_context);
return Page();
}
[BindProperty]
public Course Course { get; set; }
public async Task<IActionResult> OnPostAsync()
{
var emptyCourse = new Course();
if (await TryUpdateModelAsync<Course>(
emptyCourse,
"course", // Prefix for form value.
s => s.CourseID, s => s.DepartmentID, s => s.Title, s => s.Credits))
{
_context.Courses.Add(emptyCourse);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
// Select DepartmentID if TryUpdateModelAsync fails.
PopulateDepartmentsDropDownList(_context, emptyCourse.DepartmentID);
return Page();
}
}
}
Kod açıklamalarının İngilizce dışındaki dillere çevirisini görmek isterseniz, bunu bu GitHub tartışma konusunda bize bildirin.
Yukarıdaki kod:
- 'den
DepartmentNamePageModel
türetilir. - Fazla göndermeyi önlemek için kullanırTryUpdateModelAsync.
- kaldırır
ViewData["DepartmentID"]
.DepartmentNameSL
SelectList
türü kesin olarak belirlenmiş bir modeldir ve sayfa tarafından Razor kullanılır. Kesin olarak yazılan modeller, zayıf yazılan modellere göre tercih edilir. Daha fazla bilgi için bkz . Zayıf yazılan veriler (ViewData ve ViewBag).
Kurs Oluşturma Razor sayfasını güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Courses/Create.cshtml
:
@page
@model ContosoUniversity.Pages.Courses.CreateModel
@{
ViewData["Title"] = "Create Course";
}
<h2>Create</h2>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<input asp-for="Course.CourseID" class="form-control" />
<span asp-validation-for="Course.CourseID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Yukarıdaki kod aşağıdaki değişiklikleri yapar:
- DepartmentID olan resim yazısını Department olarak değiştirir.
"ViewBag.DepartmentID"
ileDepartmentNameSL
değiştirir (temel sınıftan).- "Bölüm Seç" seçeneğini ekler. Bu değişiklik, ilk departman yerine henüz hiçbir bölüm seçilmediğinde açılan listede "Bölüm Seç" işlemini işler.
- Bölüm seçilmediğinde bir doğrulama iletisi ekler.
Sayfa, Razor Etiket Seç Yardımcısı'nı kullanır:
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>
Oluştur sayfasını test edin. Oluştur sayfası, departman kimliği yerine departman adını görüntüler.
Kurs Düzenleme sayfa modelini güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Courses/Edit.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Courses
{
public class EditModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public EditModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Course Course { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.Include(c => c.Department).FirstOrDefaultAsync(m => m.CourseID == id);
if (Course == null)
{
return NotFound();
}
// Select current DepartmentID.
PopulateDepartmentsDropDownList(_context, Course.DepartmentID);
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
var courseToUpdate = await _context.Courses.FindAsync(id);
if (courseToUpdate == null)
{
return NotFound();
}
if (await TryUpdateModelAsync<Course>(
courseToUpdate,
"course", // Prefix for form value.
c => c.Credits, c => c.DepartmentID, c => c.Title))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
// Select DepartmentID if TryUpdateModelAsync fails.
PopulateDepartmentsDropDownList(_context, courseToUpdate.DepartmentID);
return Page();
}
}
}
Değişiklikler, Sayfa oluşturma modelinde yapılan değişikliklere benzer. Yukarıdaki kodda, PopulateDepartmentsDropDownList
açılan listeden bu bölümü seçen bölüm kimliğini geçirir.
Kurs Düzenleme sayfasını güncelleştirme Razor
Aşağıdaki kodla güncelleştirin Pages/Courses/Edit.cshtml
:
@page
@model ContosoUniversity.Pages.Courses.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Course.CourseID" />
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<div>@Html.DisplayFor(model => model.Course.CourseID)</div>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL"></select>
<span asp-validation-for="Course.DepartmentID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Yukarıdaki kod aşağıdaki değişiklikleri yapar:
- Kurs kimliğini görüntüler. Genellikle bir varlığın Birincil Anahtarı (PK) görüntülenmez. PK'ler genellikle kullanıcılar için anlamsızdır. Bu durumda, KURS numarası PK'dır.
- Department açılan listesinin başlığını DepartmentID'den Department'a değiştirir.
"ViewBag.DepartmentID"
değerini temel sınıftaki ileDepartmentNameSL
değiştirir.
Sayfa, kurs numarası için gizli bir alan (<input type="hidden">
) içerir. ile asp-for="Course.CourseID"
etiket <label>
yardımcısı eklemek, gizli alan gereksinimini ortadan kaldırmaz. <input type="hidden">
, kullanıcı Kaydet'i seçtiğinde kurs numarasının gönderilen verilere dahil edilmesi için gereklidir.
Kurs sayfası modellerini güncelleştirme
AsNoTracking izleme gerekli olmadığında performansı artırabilir.
ve yöntemlerini ekleyerek AsNoTracking
güncelleştirin:OnGetAsync
Pages/Courses/Delete.cshtml.cs
Pages/Courses/Details.cshtml.cs
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);
if (Course == null)
{
return NotFound();
}
return Page();
}
Kurs Razor sayfalarını güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Courses/Delete.cshtml
:
@page
@model ContosoUniversity.Pages.Courses.DeleteModel
@{
ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Course</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.CourseID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.CourseID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Credits)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Credits)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Department)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Department.Name)
</dd>
</dl>
<form method="post">
<input type="hidden" asp-for="Course.CourseID" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>
Ayrıntılar sayfasında da aynı değişiklikleri yapın.
@page
@model ContosoUniversity.Pages.Courses.DetailsModel
@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Course</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.CourseID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.CourseID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Credits)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Credits)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Department)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Department.Name)
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.Course.CourseID">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>
Kurs sayfalarını test edin
Oluşturma, düzenleme, ayrıntılar ve silme sayfalarını test edin.
Eğitmen oluşturma ve düzenleme sayfalarını güncelleştirme
Eğitmenler herhangi bir sayıda ders verebilir. Aşağıdaki görüntüde, bir dizi kurs onay kutusu içeren eğitmen Düzenleme sayfası gösterilmektedir.
Onay kutuları, eğitmenin atandığı kurslarda değişiklik yapmanızı sağlar. Veritabanındaki her kurs için bir onay kutusu görüntülenir. Eğitmenin atandığı kurslar seçilir. Kullanıcı, kurs ödevlerini değiştirmek için onay kutularını seçebilir veya temizleyebilir. Kurs sayısı çok daha fazlaysa farklı bir kullanıcı arabirimi daha iyi çalışabilir. Ancak burada gösterilen çoka çok ilişkiyi yönetme yöntemi değişmez. İlişki oluşturmak veya silmek için birleştirme varlığını işlemeniz gerekir.
Atanan kurs verileri için sınıf oluşturma
Aşağıdaki kodla oluşturun Models/SchoolViewModels/AssignedCourseData.cs
:
namespace ContosoUniversity.Models.SchoolViewModels
{
public class AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}
sınıfı, AssignedCourseData
bir eğitmene atanan kurslar için onay kutularını oluşturmaya yönelik veriler içerir.
Eğitmen sayfa modeli temel sınıfı oluşturma
Pages/Instructors/InstructorCoursesPageModel.cs
Temel sınıfı oluşturun:
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using ContosoUniversity.Models.SchoolViewModels;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Linq;
namespace ContosoUniversity.Pages.Instructors
{
public class InstructorCoursesPageModel : PageModel
{
public List<AssignedCourseData> AssignedCourseDataList;
public void PopulateAssignedCourseData(SchoolContext context,
Instructor instructor)
{
var allCourses = context.Courses;
var instructorCourses = new HashSet<int>(
instructor.Courses.Select(c => c.CourseID));
AssignedCourseDataList = new List<AssignedCourseData>();
foreach (var course in allCourses)
{
AssignedCourseDataList.Add(new AssignedCourseData
{
CourseID = course.CourseID,
Title = course.Title,
Assigned = instructorCourses.Contains(course.CourseID)
});
}
}
}
}
InstructorCoursesPageModel
, Düzenleme ve Oluşturma sayfa modellerinin temel sınıfıdır. PopulateAssignedCourseData
doldurulacak AssignedCourseDataList
tüm Course
varlıkları okur. Her kurs için kod , başlığını ve eğitmenin kursa atanıp atanmayacağını ayarlar CourseID
. Karma Küme, verimli aramalar için kullanılır.
Ofis konumunu işleme
Düzenleme sayfasının işlemesi gereken bir diğer ilişki de Eğitmen varlığının varlıkla OfficeAssignment
olan bire sıfır veya bir ilişkisidir. Eğitmenin kodu düzenlemesinin aşağıdaki senaryoları işlemesi gerekir:
- Kullanıcı ofis atamasını temizlerse varlığı silin
OfficeAssignment
. - Kullanıcı bir ofis ataması girerse ve boşsa yeni
OfficeAssignment
bir varlık oluşturun. - Kullanıcı ofis atamasını değiştirirse varlığı güncelleştirin
OfficeAssignment
.
Eğitmen Düzenleme sayfa modelini güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Instructors/Edit.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Instructors
{
public class EditModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public EditModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (Instructor == null)
{
return NotFound();
}
PopulateAssignedCourseData(_context, Instructor);
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id, string[] selectedCourses)
{
if (id == null)
{
return NotFound();
}
var instructorToUpdate = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses)
.FirstOrDefaultAsync(s => s.ID == id);
if (instructorToUpdate == null)
{
return NotFound();
}
if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(
instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
UpdateInstructorCourses(selectedCourses, instructorToUpdate);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
UpdateInstructorCourses(selectedCourses, instructorToUpdate);
PopulateAssignedCourseData(_context, instructorToUpdate);
return Page();
}
public void UpdateInstructorCourses(string[] selectedCourses,
Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.Courses = new List<Course>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.Courses.Select(c => c.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.Courses.Add(course);
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
var courseToRemove = instructorToUpdate.Courses.Single(
c => c.CourseID == course.CourseID);
instructorToUpdate.Courses.Remove(courseToRemove);
}
}
}
}
}
}
Yukarıdaki kod:
- ve
Courses
gezinti özellikleri için hevesle yüklemeyi kullanarak veritabanındanOfficeAssignment
geçerliInstructor
varlığı alır. - Alınan
Instructor
varlığı model bağlayıcısından alınan değerlerle güncelleştirir. TryUpdateModelAsyncüst paylaşım yapılmasını engeller. - Ofis konumu boşsa null olarak ayarlanır
Instructor.OfficeAssignment
. Null olduğundaInstructor.OfficeAssignment
, tablodakiOfficeAssignment
ilgili satır silinir. - Görünüm modeli sınıfını kullanarak onay kutularıyla ilgili bilgi sağlamak için öğesini
OnGetAsync
AssignedCourseData
çağırırPopulateAssignedCourseData
. OnPostAsync
OnayUpdateInstructorCourses
kutularından düzenlenmekte olan Eğitmen varlığına bilgi uygulamak için çağrısı yapılır.- Başarısız olursa ve
UpdateInstructorCourses
çağrıları.PopulateAssignedCourseData
OnPostAsync
TryUpdateModelAsync Bu yöntem, bir hata iletisiyle yeniden görüntülendiğinde sayfaya girilen atanan kurs verilerini geri yüklemeyi çağırır.
Razor Sayfada Kurs varlıkları koleksiyonu olmadığından model bağlayıcısı gezinti özelliğini otomatik olarak güncelleştiremezCourses
. Gezinti özelliğini güncelleştirmek için model bağlayıcısını Courses
kullanmak yerine, bu işlem yeni UpdateInstructorCourses
yöntemde yapılır. Bu nedenle, özelliğini model bağlamasının Courses
dışında tutmanız gerekir. Bildirilen özelliklerle aşırı yüklemeyi kullandığınızdan ve Courses
ekleme listesinde olmadığından bu, çağıran TryUpdateModelAsync kodda herhangi bir değişiklik gerektirmez.
Hiçbir onay kutusu seçilmediyse içindeki kod UpdateInstructorCourses
boş bir koleksiyonla öğesini başlatır instructorToUpdate.Courses
ve şunu döndürür:
if (selectedCourses == null)
{
instructorToUpdate.Courses = new List<Course>();
return;
}
Kod daha sonra veritabanındaki tüm kurslar arasında döngü oluşturur ve her kursu şu anda eğitmene atanmış olanlarla sayfada seçilenler arasında denetler. Verimli aramaları kolaylaştırmak için, ikinci iki koleksiyon nesnelerde HashSet
depolanır.
Kursun onay kutusu seçiliyse ancak kurs gezinti özelliğinde Instructor.Courses
değilse, kurs gezinti özelliğindeki koleksiyona eklenir.
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.Courses.Add(course);
}
}
Kursun onay kutusu seçili değilse ancak kurs gezinti özelliğindeyseInstructor.Courses
, kurs gezinti özelliğinden kaldırılır.
else
{
if (instructorCourses.Contains(course.CourseID))
{
var courseToRemove = instructorToUpdate.Courses.Single(
c => c.CourseID == course.CourseID);
instructorToUpdate.Courses.Remove(courseToRemove);
}
}
Eğitmen Düzenleme sayfasını güncelleştirme Razor
Aşağıdaki kodla güncelleştirin Pages/Instructors/Edit.cshtml
:
@page
@model ContosoUniversity.Pages.Instructors.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Instructor.ID" />
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="table">
<table>
<tr>
@{
int cnt = 0;
foreach (var course in Model.AssignedCourseDataList)
{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Yukarıdaki kod, üç sütunu olan bir HTML tablosu oluşturur. Her sütunda bir onay kutusu ve kurs numarasını ve başlığını içeren bir resim yazısı vardır. Onay kutularının tümü aynı ada ("selectedCourses") sahiptir. Aynı adın kullanılması, model bağlayıcısını bunları grup olarak ele almak için bilgilendirecektir. Her onay kutusunun değer özniteliği olarak CourseID
ayarlanır. Sayfa deftere nakledildiğinde, model bağlayıcısı yalnızca seçilen onay kutularının değerlerinden CourseID
oluşan bir dizi geçirir.
Onay kutuları başlangıçta işlendiğinde, eğitmene atanan kurslar seçilir.
Not: Eğitmen kurs verilerini düzenlemek için burada uygulanan yaklaşım, sınırlı sayıda kurs olduğunda iyi sonuç verir. Çok daha büyük koleksiyonlar için farklı bir kullanıcı arabirimi ve farklı bir güncelleştirme yöntemi daha kullanılabilir ve verimli olabilir.
Uygulamayı çalıştırın ve güncelleştirilmiş Eğitmenler Düzenleme sayfasını test edin. Bazı kurs ödevlerini değiştirin. Değişiklikler Dizin sayfasına yansıtılır.
Eğitmen Oluşturma sayfasını güncelleştirme
Eğitmen Oluşturma sayfası modelini ve Düzenle sayfasına benzer bir kodla güncelleştirin:
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Instructors
{
public class CreateModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
private readonly ILogger<InstructorCoursesPageModel> _logger;
public CreateModel(SchoolContext context,
ILogger<InstructorCoursesPageModel> logger)
{
_context = context;
_logger = logger;
}
public IActionResult OnGet()
{
var instructor = new Instructor();
instructor.Courses = new List<Course>();
// Provides an empty collection for the foreach loop
// foreach (var course in Model.AssignedCourseDataList)
// in the Create Razor page.
PopulateAssignedCourseData(_context, instructor);
return Page();
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnPostAsync(string[] selectedCourses)
{
var newInstructor = new Instructor();
if (selectedCourses.Length > 0)
{
newInstructor.Courses = new List<Course>();
// Load collection with one DB call.
_context.Courses.Load();
}
// Add selected Courses courses to the new instructor.
foreach (var course in selectedCourses)
{
var foundCourse = await _context.Courses.FindAsync(int.Parse(course));
if (foundCourse != null)
{
newInstructor.Courses.Add(foundCourse);
}
else
{
_logger.LogWarning("Course {course} not found", course);
}
}
try
{
if (await TryUpdateModelAsync<Instructor>(
newInstructor,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
_context.Instructors.Add(newInstructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
return RedirectToPage("./Index");
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
PopulateAssignedCourseData(_context, newInstructor);
return Page();
}
}
}
Yukarıdaki kod:
Uyarı ve hata iletileri için günlüğe kaydetme ekler.
Çağrıları Load, tüm Kursları tek bir veritabanı çağrısında getirir. Küçük koleksiyonlar için bu, kullanılırken FindAsyncbir iyileştirmedir.
FindAsync
, veritabanına istekte bulunmadan izlenen varlığı döndürür.public async Task<IActionResult> OnPostAsync(string[] selectedCourses) { var newInstructor = new Instructor(); if (selectedCourses.Length > 0) { newInstructor.Courses = new List<Course>(); // Load collection with one DB call. _context.Courses.Load(); } // Add selected Courses courses to the new instructor. foreach (var course in selectedCourses) { var foundCourse = await _context.Courses.FindAsync(int.Parse(course)); if (foundCourse != null) { newInstructor.Courses.Add(foundCourse); } else { _logger.LogWarning("Course {course} not found", course); } } try { if (await TryUpdateModelAsync<Instructor>( newInstructor, "Instructor", i => i.FirstMidName, i => i.LastName, i => i.HireDate, i => i.OfficeAssignment)) { _context.Instructors.Add(newInstructor); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); } return RedirectToPage("./Index"); } catch (Exception ex) { _logger.LogError(ex.Message); } PopulateAssignedCourseData(_context, newInstructor); return Page(); }
_context.Instructors.Add(newInstructor)
birleştirme tablosunu açıkça eşlemeden çoka çok ilişkileri kullanarak yeniInstructor
bir oluşturur. EF 5.0'da çoka çok eklendi.
Eğitmen Oluşturma sayfasını test edin.
Eğitmen Oluşturma Razor sayfasını Düzenle sayfasına benzer bir kodla güncelleştirin:
@page
@model ContosoUniversity.Pages.Instructors.CreateModel
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="table">
<table>
<tr>
@{
int cnt = 0;
foreach (var course in Model.AssignedCourseDataList)
{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Eğitmen Silme sayfasını güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Instructors/Delete.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Instructors
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public DeleteModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor = await _context.Instructors.FirstOrDefaultAsync(m => m.ID == id);
if (Instructor == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor instructor = await _context.Instructors
.Include(i => i.Courses)
.SingleAsync(i => i.ID == id);
if (instructor == null)
{
return RedirectToPage("./Index");
}
var departments = await _context.Departments
.Where(d => d.InstructorID == id)
.ToListAsync();
departments.ForEach(d => d.InstructorID = null);
_context.Instructors.Remove(instructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Yukarıdaki kod aşağıdaki değişiklikleri yapar:
Gezinti özelliği için hevesle
Courses
yüklemeyi kullanır.Courses
eklenmelidir veya eğitmen silindiğinde silinmez. Bunları okumak zorunda kalmamak için veritabanında art arda silmeyi yapılandırın.Silinecek eğitmen herhangi bir bölümün yöneticisi olarak atanırsa, bu departmanlardan eğitmen atamasını kaldırır.
Uygulamayı çalıştırın ve Sil sayfasını test edin.
Sonraki adımlar
Bu öğreticide ilgili verilerin nasıl güncelleştirilecekleri gösterilmektedir. Aşağıdaki çizimlerde tamamlanan sayfalardan bazıları gösterilmektedir.
Kurs Oluşturma ve Düzenleme sayfalarını güncelleştirme
Kurs Oluşturma ve Düzenleme sayfalarının yapı iskelesi oluşturulmuş kodunda, Bölüm Kimliğini (tamsayı) gösteren bir Bölüm açılan listesi vardır. Açılan listede Departman adı gösterilmelidir, bu nedenle bu sayfaların her ikisinde de bölüm adları listesi gerekir. Bu listeyi sağlamak için Oluştur ve Düzenle sayfaları için bir temel sınıf kullanın.
Kurs Oluşturma ve Düzenleme için temel sınıf oluşturma
Aşağıdaki kodla bir Pages/Courses/DepartmentNamePageModel.cs
dosya oluşturun:
using ContosoUniversity.Data;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace ContosoUniversity.Pages.Courses
{
public class DepartmentNamePageModel : PageModel
{
public SelectList DepartmentNameSL { get; set; }
public void PopulateDepartmentsDropDownList(SchoolContext _context,
object selectedDepartment = null)
{
var departmentsQuery = from d in _context.Departments
orderby d.Name // Sort by name.
select d;
DepartmentNameSL = new SelectList(departmentsQuery.AsNoTracking(),
"DepartmentID", "Name", selectedDepartment);
}
}
}
Yukarıdaki kod, bölüm adlarının listesini içeren bir SelectList oluşturur. belirtilirse selectedDepartment
, bu bölüm içinde SelectList
seçilir.
Sayfa modeli oluştur ve düzenle sınıfları'ndan DepartmentNamePageModel
türetilir.
Kurs Oluşturma sayfa modelini güncelleştirme
Bölüme bir Kurs atanır. Oluştur ve Düzenle sayfalarının temel sınıfı, bölümü seçmek için bir SelectList
sağlar. öğesini kullanan SelectList
açılan liste yabancı anahtar (FK) özelliğini ayarlar Course.DepartmentID
. EF CoreCourse.DepartmentID
gezinti özelliğini yüklemek için FK kullanırDepartment
.
Aşağıdaki kodla güncelleştirin Pages/Courses/Create.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Courses
{
public class CreateModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public CreateModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
public IActionResult OnGet()
{
PopulateDepartmentsDropDownList(_context);
return Page();
}
[BindProperty]
public Course Course { get; set; }
public async Task<IActionResult> OnPostAsync()
{
var emptyCourse = new Course();
if (await TryUpdateModelAsync<Course>(
emptyCourse,
"course", // Prefix for form value.
s => s.CourseID, s => s.DepartmentID, s => s.Title, s => s.Credits))
{
_context.Courses.Add(emptyCourse);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
// Select DepartmentID if TryUpdateModelAsync fails.
PopulateDepartmentsDropDownList(_context, emptyCourse.DepartmentID);
return Page();
}
}
}
Kod açıklamalarının İngilizce dışındaki dillere çevirisini görmek isterseniz, bunu bu GitHub tartışma konusunda bize bildirin.
Yukarıdaki kod:
- 'den
DepartmentNamePageModel
türetilir. - Fazla göndermeyi önlemek için kullanır
TryUpdateModelAsync
. - kaldırır
ViewData["DepartmentID"]
.DepartmentNameSL
taban sınıfından kesin olarak belirlenmiş bir modeldir ve sayfa tarafından Razor kullanılır. Kesin olarak yazılan modeller, zayıf yazılan modellere göre tercih edilir. Daha fazla bilgi için bkz . Zayıf yazılan veriler (ViewData ve ViewBag).
Kurs Oluşturma Razor sayfasını güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Courses/Create.cshtml
:
@page
@model ContosoUniversity.Pages.Courses.CreateModel
@{
ViewData["Title"] = "Create Course";
}
<h2>Create</h2>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<input asp-for="Course.CourseID" class="form-control" />
<span asp-validation-for="Course.CourseID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Yukarıdaki kod aşağıdaki değişiklikleri yapar:
- DepartmentID olan resim yazısını Department olarak değiştirir.
"ViewBag.DepartmentID"
ileDepartmentNameSL
değiştirir (temel sınıftan).- "Bölüm Seç" seçeneğini ekler. Bu değişiklik, ilk departman yerine henüz hiçbir bölüm seçilmediğinde açılan listede "Bölüm Seç" işlemini işler.
- Bölüm seçilmediğinde bir doğrulama iletisi ekler.
Sayfa, Razor Etiket Seç Yardımcısı'nı kullanır:
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>
Oluştur sayfasını test edin. Oluştur sayfası, departman kimliği yerine departman adını görüntüler.
Kurs Düzenleme sayfa modelini güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Courses/Edit.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Courses
{
public class EditModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public EditModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Course Course { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.Include(c => c.Department).FirstOrDefaultAsync(m => m.CourseID == id);
if (Course == null)
{
return NotFound();
}
// Select current DepartmentID.
PopulateDepartmentsDropDownList(_context, Course.DepartmentID);
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
var courseToUpdate = await _context.Courses.FindAsync(id);
if (courseToUpdate == null)
{
return NotFound();
}
if (await TryUpdateModelAsync<Course>(
courseToUpdate,
"course", // Prefix for form value.
c => c.Credits, c => c.DepartmentID, c => c.Title))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
// Select DepartmentID if TryUpdateModelAsync fails.
PopulateDepartmentsDropDownList(_context, courseToUpdate.DepartmentID);
return Page();
}
}
}
Değişiklikler, Sayfa oluşturma modelinde yapılan değişikliklere benzer. Yukarıdaki kodda, PopulateDepartmentsDropDownList
açılan listeden bu bölümü seçen bölüm kimliğini geçirir.
Kurs Düzenleme sayfasını güncelleştirme Razor
Aşağıdaki kodla güncelleştirin Pages/Courses/Edit.cshtml
:
@page
@model ContosoUniversity.Pages.Courses.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Course.CourseID" />
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<div>@Html.DisplayFor(model => model.Course.CourseID)</div>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL"></select>
<span asp-validation-for="Course.DepartmentID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Yukarıdaki kod aşağıdaki değişiklikleri yapar:
- Kurs kimliğini görüntüler. Genellikle bir varlığın Birincil Anahtarı (PK) görüntülenmez. PK'ler genellikle kullanıcılar için anlamsızdır. Bu durumda, KURS numarası PK'dır.
- Department açılan listesinin başlığını DepartmentID'den Department'a değiştirir.
"ViewBag.DepartmentID"
ileDepartmentNameSL
değiştirir (temel sınıftan).
Sayfa, kurs numarası için gizli bir alan (<input type="hidden">
) içerir. ile asp-for="Course.CourseID"
etiket <label>
yardımcısı eklemek, gizli alan gereksinimini ortadan kaldırmaz. <input type="hidden">
, kullanıcı Kaydet'e tıkladığında kurs numarasının gönderilen verilere dahil edilmesi için gereklidir.
Kurs Ayrıntıları ve Silme sayfalarını güncelleştirme
AsNoTracking izleme gerekli olmadığında performansı artırabilir.
Kurs sayfası modellerini güncelleştirme
eklemek AsNoTracking
için aşağıdaki kodla güncelleştirinPages/Courses/Delete.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Courses
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public DeleteModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Course Course { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);
if (Course == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses.FindAsync(id);
if (Course != null)
{
_context.Courses.Remove(Course);
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
}
}
Dosyada Pages/Courses/Details.cshtml.cs
aynı değişikliği yapın:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Courses
{
public class DetailsModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public DetailsModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
public Course Course { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);
if (Course == null)
{
return NotFound();
}
return Page();
}
}
}
Kurs Razor sayfalarını güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Courses/Delete.cshtml
:
@page
@model ContosoUniversity.Pages.Courses.DeleteModel
@{
ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Course</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.CourseID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.CourseID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Credits)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Credits)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Department)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Department.Name)
</dd>
</dl>
<form method="post">
<input type="hidden" asp-for="Course.CourseID" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>
Ayrıntılar sayfasında da aynı değişiklikleri yapın.
@page
@model ContosoUniversity.Pages.Courses.DetailsModel
@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Course</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.CourseID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.CourseID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Credits)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Credits)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Course.Department)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Course.Department.Name)
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.Course.CourseID">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>
Kurs sayfalarını test edin
Oluşturma, düzenleme, ayrıntılar ve silme sayfalarını test edin.
Eğitmen oluşturma ve düzenleme sayfalarını güncelleştirme
Eğitmenler herhangi bir sayıda ders verebilir. Aşağıdaki görüntüde, bir dizi kurs onay kutusu içeren eğitmen Düzenleme sayfası gösterilmektedir.
Onay kutuları, eğitmenin atandığı kurslarda değişiklik yapmanızı sağlar. Veritabanındaki her kurs için bir onay kutusu görüntülenir. Eğitmenin atandığı kurslar seçilir. Kullanıcı, kurs ödevlerini değiştirmek için onay kutularını seçebilir veya temizleyebilir. Kurs sayısı çok daha fazlaysa farklı bir kullanıcı arabirimi daha iyi çalışabilir. Ancak burada gösterilen çoka çok ilişkiyi yönetme yöntemi değişmez. İlişki oluşturmak veya silmek için birleştirme varlığını işlemeniz gerekir.
Atanan kurs verileri için sınıf oluşturma
Aşağıdaki kodla oluşturun Models/SchoolViewModels/AssignedCourseData.cs
:
namespace ContosoUniversity.Models.SchoolViewModels
{
public class AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}
sınıfı, AssignedCourseData
bir eğitmene atanan kurslar için onay kutularını oluşturmaya yönelik veriler içerir.
Eğitmen sayfa modeli temel sınıfı oluşturma
Pages/Instructors/InstructorCoursesPageModel.cs
Temel sınıfı oluşturun:
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using ContosoUniversity.Models.SchoolViewModels;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Linq;
namespace ContosoUniversity.Pages.Instructors
{
public class InstructorCoursesPageModel : PageModel
{
public List<AssignedCourseData> AssignedCourseDataList;
public void PopulateAssignedCourseData(SchoolContext context,
Instructor instructor)
{
var allCourses = context.Courses;
var instructorCourses = new HashSet<int>(
instructor.CourseAssignments.Select(c => c.CourseID));
AssignedCourseDataList = new List<AssignedCourseData>();
foreach (var course in allCourses)
{
AssignedCourseDataList.Add(new AssignedCourseData
{
CourseID = course.CourseID,
Title = course.Title,
Assigned = instructorCourses.Contains(course.CourseID)
});
}
}
public void UpdateInstructorCourses(SchoolContext context,
string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(
new CourseAssignment
{
InstructorID = instructorToUpdate.ID,
CourseID = course.CourseID
});
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove
= instructorToUpdate
.CourseAssignments
.SingleOrDefault(i => i.CourseID == course.CourseID);
context.Remove(courseToRemove);
}
}
}
}
}
}
InstructorCoursesPageModel
, Düzenle ve Oluştur sayfa modelleri için kullanacağınız temel sınıftır. PopulateAssignedCourseData
doldurulacak AssignedCourseDataList
tüm Course
varlıkları okur. Her kurs için kod , başlığını ve eğitmenin kursa atanıp atanmayacağını ayarlar CourseID
. Karma Küme, verimli aramalar için kullanılır.
Razor Sayfada Kurs varlıkları koleksiyonu olmadığından model bağlayıcısı gezinti özelliğini otomatik olarak güncelleştiremezCourseAssignments
. Gezinti özelliğini güncelleştirmek için model bağlayıcısını CourseAssignments
kullanmak yerine bunu yeni UpdateInstructorCourses
yöntemde yaparsınız. Bu nedenle, özelliğini model bağlamasının CourseAssignments
dışında tutmanız gerekir. Bildirilen özelliklerle aşırı yüklemeyi kullandığınızdan ve CourseAssignments
ekleme listesinde olmadığından bu, çağıran TryUpdateModel
kodda herhangi bir değişiklik gerektirmez.
Onay kutusu seçilmediyse içindeki kod UpdateInstructorCourses
, gezinti özelliğini boş bir koleksiyonla başlatır CourseAssignments
ve şunu döndürür:
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}
Kod daha sonra veritabanındaki tüm kurslar arasında döngü oluşturur ve her kursu şu anda eğitmene atanmış olanlarla sayfada seçilenler arasında denetler. Verimli aramaları kolaylaştırmak için, ikinci iki koleksiyon nesnelerde HashSet
depolanır.
Kursun onay kutusu seçiliyse ancak kurs gezinti özelliğinde Instructor.CourseAssignments
değilse, kurs gezinti özelliğindeki koleksiyona eklenir.
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(
new CourseAssignment
{
InstructorID = instructorToUpdate.ID,
CourseID = course.CourseID
});
}
}
Kursun onay kutusu seçili değilse ancak kurs gezinti özelliğindeyse Instructor.CourseAssignments
, kurs gezinti özelliğinden kaldırılır.
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove
= instructorToUpdate
.CourseAssignments
.SingleOrDefault(i => i.CourseID == course.CourseID);
context.Remove(courseToRemove);
}
}
Ofis konumunu işleme
Düzenleme sayfasının işlemesi gereken bir diğer ilişki de Eğitmen varlığının varlıkla OfficeAssignment
olan bire sıfır veya bir ilişkisidir. Eğitmenin kodu düzenlemesinin aşağıdaki senaryoları işlemesi gerekir:
- Kullanıcı ofis atamasını temizlerse varlığı silin
OfficeAssignment
. - Kullanıcı bir ofis ataması girerse ve boşsa yeni
OfficeAssignment
bir varlık oluşturun. - Kullanıcı ofis atamasını değiştirirse varlığı güncelleştirin
OfficeAssignment
.
Eğitmen Düzenleme sayfa modelini güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Instructors/Edit.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Instructors
{
public class EditModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public EditModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments).ThenInclude(i => i.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (Instructor == null)
{
return NotFound();
}
PopulateAssignedCourseData(_context, Instructor);
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id, string[] selectedCourses)
{
if (id == null)
{
return NotFound();
}
var instructorToUpdate = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.FirstOrDefaultAsync(s => s.ID == id);
if (instructorToUpdate == null)
{
return NotFound();
}
if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(
instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
UpdateInstructorCourses(_context, selectedCourses, instructorToUpdate);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
UpdateInstructorCourses(_context, selectedCourses, instructorToUpdate);
PopulateAssignedCourseData(_context, instructorToUpdate);
return Page();
}
}
}
Yukarıdaki kod:
- ,
CourseAssignment
veCourseAssignment.Course
gezinti özellikleri için istekli yükleme kullanarak veritabanındanOfficeAssignment
geçerliInstructor
varlığı alır. - Alınan
Instructor
varlığı model bağlayıcısından alınan değerlerle güncelleştirir.TryUpdateModel
üst paylaşım yapılmasını engeller. - Ofis konumu boşsa null olarak ayarlanır
Instructor.OfficeAssignment
. Null olduğundaInstructor.OfficeAssignment
, tablodakiOfficeAssignment
ilgili satır silinir. - Görünüm modeli sınıfını kullanarak onay kutularıyla ilgili bilgi sağlamak için öğesini
OnGetAsync
AssignedCourseData
çağırırPopulateAssignedCourseData
. OnPostAsync
OnayUpdateInstructorCourses
kutularından düzenlenmekte olan Eğitmen varlığına bilgi uygulamak için çağrısı yapılır.- Başarısız olursa ve
UpdateInstructorCourses
çağrıları.PopulateAssignedCourseData
OnPostAsync
TryUpdateModel
Bu yöntem, bir hata iletisiyle yeniden görüntülendiğinde sayfaya girilen atanan kurs verilerini geri yüklemeyi çağırır.
Eğitmen Düzenleme sayfasını güncelleştirme Razor
Aşağıdaki kodla güncelleştirin Pages/Instructors/Edit.cshtml
:
@page
@model ContosoUniversity.Pages.Instructors.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Instructor.ID" />
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="table">
<table>
<tr>
@{
int cnt = 0;
foreach (var course in Model.AssignedCourseDataList)
{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Yukarıdaki kod, üç sütunu olan bir HTML tablosu oluşturur. Her sütunda bir onay kutusu ve kurs numarasını ve başlığını içeren bir resim yazısı vardır. Onay kutularının tümü aynı ada ("selectedCourses") sahiptir. Aynı adın kullanılması, model bağlayıcısını bunları grup olarak ele almak için bilgilendirecektir. Her onay kutusunun değer özniteliği olarak CourseID
ayarlanır. Sayfa deftere nakledildiğinde, model bağlayıcısı yalnızca seçilen onay kutularının değerlerinden CourseID
oluşan bir dizi geçirir.
Onay kutuları başlangıçta işlendiğinde, eğitmene atanan kurslar seçilir.
Not: Eğitmen kurs verilerini düzenlemek için burada uygulanan yaklaşım, sınırlı sayıda kurs olduğunda iyi sonuç verir. Çok daha büyük koleksiyonlar için farklı bir kullanıcı arabirimi ve farklı bir güncelleştirme yöntemi daha kullanılabilir ve verimli olabilir.
Uygulamayı çalıştırın ve güncelleştirilmiş Eğitmenler Düzenleme sayfasını test edin. Bazı kurs ödevlerini değiştirin. Değişiklikler Dizin sayfasına yansıtılır.
Eğitmen Oluşturma sayfasını güncelleştirme
Eğitmen Oluşturma sayfası modelini ve Razor sayfasını Düzenle sayfasına benzer bir kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Instructors
{
public class CreateModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public CreateModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
public IActionResult OnGet()
{
var instructor = new Instructor();
instructor.CourseAssignments = new List<CourseAssignment>();
// Provides an empty collection for the foreach loop
// foreach (var course in Model.AssignedCourseDataList)
// in the Create Razor page.
PopulateAssignedCourseData(_context, instructor);
return Page();
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnPostAsync(string[] selectedCourses)
{
var newInstructor = new Instructor();
if (selectedCourses != null)
{
newInstructor.CourseAssignments = new List<CourseAssignment>();
foreach (var course in selectedCourses)
{
var courseToAdd = new CourseAssignment
{
CourseID = int.Parse(course)
};
newInstructor.CourseAssignments.Add(courseToAdd);
}
}
if (await TryUpdateModelAsync<Instructor>(
newInstructor,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
_context.Instructors.Add(newInstructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
PopulateAssignedCourseData(_context, newInstructor);
return Page();
}
}
}
@page
@model ContosoUniversity.Pages.Instructors.CreateModel
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="table">
<table>
<tr>
@{
int cnt = 0;
foreach (var course in Model.AssignedCourseDataList)
{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Eğitmen Oluşturma sayfasını test edin.
Eğitmen Silme sayfasını güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Instructors/Delete.cshtml.cs
:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Instructors
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public DeleteModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor = await _context.Instructors.FirstOrDefaultAsync(m => m.ID == id);
if (Instructor == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor instructor = await _context.Instructors
.Include(i => i.CourseAssignments)
.SingleAsync(i => i.ID == id);
if (instructor == null)
{
return RedirectToPage("./Index");
}
var departments = await _context.Departments
.Where(d => d.InstructorID == id)
.ToListAsync();
departments.ForEach(d => d.InstructorID = null);
_context.Instructors.Remove(instructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Yukarıdaki kod aşağıdaki değişiklikleri yapar:
Gezinti özelliği için hevesle
CourseAssignments
yüklemeyi kullanır.CourseAssignments
eklenmelidir veya eğitmen silindiğinde silinmez. Bunları okumak zorunda kalmamak için veritabanında art arda silmeyi yapılandırın.Silinecek eğitmen herhangi bir bölümün yöneticisi olarak atanırsa, bu departmanlardan eğitmen atamasını kaldırır.
Uygulamayı çalıştırın ve Sil sayfasını test edin.
Sonraki adımlar
Bu öğreticide ilgili verilerin güncelleştirilmesi gösterilmektedir. Çözemediğiniz sorunlarla karşılaşırsanız tamamlanmış uygulamayı indirin veya görüntüleyin. İndirme yönergeleri.
Aşağıdaki çizimlerde tamamlanan sayfalardan bazıları gösterilmektedir.
Kurs oluşturma ve düzenleme sayfalarını inceleyin ve test edin. Yeni bir kurs oluşturun. Bölüm, adıyla değil birincil anahtarıyla (tamsayı) seçilir. Yeni kursu düzenleyin. Testi tamamladığınızda yeni kursu silin.
Ortak kodu paylaşmak için temel sınıf oluşturma
Kurslar/Oluştur ve Kurslar/Düzenle sayfalarının her birinin bir bölüm adı listesi gerekir. Pages/Courses/DepartmentNamePageModel.cshtml.cs
Oluştur ve Düzenle sayfaları için temel sınıfı oluşturun:
using ContosoUniversity.Data;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace ContosoUniversity.Pages.Courses
{
public class DepartmentNamePageModel : PageModel
{
public SelectList DepartmentNameSL { get; set; }
public void PopulateDepartmentsDropDownList(SchoolContext _context,
object selectedDepartment = null)
{
var departmentsQuery = from d in _context.Departments
orderby d.Name // Sort by name.
select d;
DepartmentNameSL = new SelectList(departmentsQuery.AsNoTracking(),
"DepartmentID", "Name", selectedDepartment);
}
}
}
Yukarıdaki kod, bölüm adlarının listesini içeren bir SelectList oluşturur. belirtilirse selectedDepartment
, bu bölüm içinde SelectList
seçilir.
Sayfa modeli oluştur ve düzenle sınıfları'ndan DepartmentNamePageModel
türetilir.
Kurs Sayfalarını Özelleştirme
Yeni bir kurs varlığı oluşturulduğunda, var olan bir bölümle ilişkisi olmalıdır. Kurs oluştururken bölüm eklemek için Oluştur ve Düzenle temel sınıfı, bölümü seçmeye yönelik bir açılan liste içerir. Açılan liste yabancı anahtar (FK) özelliğini ayarlar Course.DepartmentID
. EF CoreCourse.DepartmentID
gezinti özelliğini yüklemek için FK kullanırDepartment
.
Sayfa modeli oluştur'u aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Courses
{
public class CreateModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public CreateModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
public IActionResult OnGet()
{
PopulateDepartmentsDropDownList(_context);
return Page();
}
[BindProperty]
public Course Course { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var emptyCourse = new Course();
if (await TryUpdateModelAsync<Course>(
emptyCourse,
"course", // Prefix for form value.
s => s.CourseID, s => s.DepartmentID, s => s.Title, s => s.Credits))
{
_context.Courses.Add(emptyCourse);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
// Select DepartmentID if TryUpdateModelAsync fails.
PopulateDepartmentsDropDownList(_context, emptyCourse.DepartmentID);
return Page();
}
}
}
Yukarıdaki kod:
- 'den
DepartmentNamePageModel
türetilir. - Fazla göndermeyi önlemek için kullanır
TryUpdateModelAsync
. ViewData["DepartmentID"]
ileDepartmentNameSL
değiştirir (temel sınıftan).
ViewData["DepartmentID"]
, kesin olarak yazılan DepartmentNameSL
ile değiştirilir. Kesin olarak yazılan modeller, zayıf yazılan modellere göre tercih edilir. Daha fazla bilgi için bkz . Zayıf yazılan veriler (ViewData ve ViewBag).
Kurs Oluşturma sayfasını güncelleştirme
Aşağıdaki kodla güncelleştirin Pages/Courses/Create.cshtml
:
@page
@model ContosoUniversity.Pages.Courses.CreateModel
@{
ViewData["Title"] = "Create Course";
}
<h2>Create</h2>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<input asp-for="Course.CourseID" class="form-control" />
<span asp-validation-for="Course.CourseID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Yukarıdaki işaretleme aşağıdaki değişiklikleri yapar:
- DepartmentID olan resim yazısını Department olarak değiştirir.
"ViewBag.DepartmentID"
ileDepartmentNameSL
değiştirir (temel sınıftan).- "Bölüm Seç" seçeneğini ekler. Bu değişiklik, ilk bölüm yerine "Bölüm Seç" işlemini işler.
- Bölüm seçilmediğinde bir doğrulama iletisi ekler.
Sayfa, Razor Etiket Seç Yardımcısı'nı kullanır:
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="Course.DepartmentID" class="text-danger" />
</div>
Oluştur sayfasını test edin. Oluştur sayfası, departman kimliği yerine departman adını görüntüler.
Kursları Düzenle sayfasını güncelleştirin.
Pages/Courses/Edit.cshtml.cs
kodunu şu kodla değiştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Courses
{
public class EditModel : DepartmentNamePageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public EditModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Course Course { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.Include(c => c.Department).FirstOrDefaultAsync(m => m.CourseID == id);
if (Course == null)
{
return NotFound();
}
// Select current DepartmentID.
PopulateDepartmentsDropDownList(_context,Course.DepartmentID);
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (!ModelState.IsValid)
{
return Page();
}
var courseToUpdate = await _context.Courses.FindAsync(id);
if (await TryUpdateModelAsync<Course>(
courseToUpdate,
"course", // Prefix for form value.
c => c.Credits, c => c.DepartmentID, c => c.Title))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
// Select DepartmentID if TryUpdateModelAsync fails.
PopulateDepartmentsDropDownList(_context, courseToUpdate.DepartmentID);
return Page();
}
}
}
Değişiklikler, Sayfa oluşturma modelinde yapılan değişikliklere benzer. Yukarıdaki kodda, PopulateDepartmentsDropDownList
açılan listede belirtilen bölümü seçen departman kimliğini geçirir.
Aşağıdaki işaretlemeyle güncelleştirin Pages/Courses/Edit.cshtml
:
@page
@model ContosoUniversity.Pages.Courses.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Course</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Course.CourseID" />
<div class="form-group">
<label asp-for="Course.CourseID" class="control-label"></label>
<div>@Html.DisplayFor(model => model.Course.CourseID)</div>
</div>
<div class="form-group">
<label asp-for="Course.Title" class="control-label"></label>
<input asp-for="Course.Title" class="form-control" />
<span asp-validation-for="Course.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Credits" class="control-label"></label>
<input asp-for="Course.Credits" class="form-control" />
<span asp-validation-for="Course.Credits" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Course.Department" class="control-label"></label>
<select asp-for="Course.DepartmentID" class="form-control"
asp-items="@Model.DepartmentNameSL"></select>
<span asp-validation-for="Course.DepartmentID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Yukarıdaki işaretleme aşağıdaki değişiklikleri yapar:
- Kurs kimliğini görüntüler. Genellikle bir varlığın Birincil Anahtarı (PK) görüntülenmez. PK'ler genellikle kullanıcılar için anlamsızdır. Bu durumda, KURS numarası PK'dır.
- DepartmentID olan resim yazısını Department olarak değiştirir.
"ViewBag.DepartmentID"
ileDepartmentNameSL
değiştirir (temel sınıftan).
Sayfa, kurs numarası için gizli bir alan (<input type="hidden">
) içerir. ile asp-for="Course.CourseID"
etiket <label>
yardımcısı eklemek, gizli alan gereksinimini ortadan kaldırmaz. <input type="hidden">
, kullanıcı Kaydet'e tıkladığında kurs numarasının gönderilen verilere dahil edilmesi için gereklidir.
Güncelleştirilmiş kodu test edin. Kurs oluşturma, düzenleme ve silme.
Ayrıntılar ve Silme sayfa modellerine AsNoTracking ekleme
AsNoTracking izleme gerekli olmadığında performansı artırabilir. Sil ve Ayrıntılar sayfa modeline ekleyin AsNoTracking
. Aşağıdaki kod güncelleştirilmiş Sayfayı sil modelini gösterir:
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public DeleteModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Course Course { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);
if (Course == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (Course != null)
{
_context.Courses.Remove(Course);
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
}
Dosyasındaki OnGetAsync
yöntemini güncelleştirin Pages/Courses/Details.cshtml.cs
:
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Course = await _context.Courses
.AsNoTracking()
.Include(c => c.Department)
.FirstOrDefaultAsync(m => m.CourseID == id);
if (Course == null)
{
return NotFound();
}
return Page();
}
Silme ve Ayrıntılar sayfalarını değiştirme
Sil Razor sayfasını aşağıdaki işaretlemeyle güncelleştirin:
@page
@model ContosoUniversity.Pages.Courses.DeleteModel
@{
ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Course</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Course.CourseID)
</dt>
<dd>
@Html.DisplayFor(model => model.Course.CourseID)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Course.Title)
</dt>
<dd>
@Html.DisplayFor(model => model.Course.Title)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Course.Credits)
</dt>
<dd>
@Html.DisplayFor(model => model.Course.Credits)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Course.Department)
</dt>
<dd>
@Html.DisplayFor(model => model.Course.Department.DepartmentID)
</dd>
</dl>
<form method="post">
<input type="hidden" asp-for="Course.CourseID" />
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-page="./Index">Back to List</a>
</form>
</div>
Ayrıntılar sayfasında da aynı değişiklikleri yapın.
Kurs sayfalarını test edin
Oluşturma, düzenleme, ayrıntılar ve silmeyi test edin.
Eğitmen sayfalarını güncelleştirme
Aşağıdaki bölümlerde eğitmen sayfaları güncelleştirilmektedir.
Ofis konumu ekleme
Eğitmen kaydını düzenlerken, eğitmenin ofis ödevini güncelleştirmek isteyebilirsiniz. Varlığın Instructor
varlıkla OfficeAssignment
bire sıfır veya bir ilişkisi vardır. Eğitmen kodu aşağıdakileri işlemelidir:
- Kullanıcı ofis atamasını temizlerse varlığı silin
OfficeAssignment
. - Kullanıcı bir ofis ataması girerse ve boşsa yeni
OfficeAssignment
bir varlık oluşturun. - Kullanıcı ofis atamasını değiştirirse varlığı güncelleştirin
OfficeAssignment
.
Eğitmenleri Sayfa modelini düzenle'yi aşağıdaki kodla güncelleştirin:
public class EditModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public EditModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor = await _context.Instructors
.Include(i => i.OfficeAssignment)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (Instructor == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (!ModelState.IsValid)
{
return Page();
}
var instructorToUpdate = await _context.Instructors
.Include(i => i.OfficeAssignment)
.FirstOrDefaultAsync(s => s.ID == id);
if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(
instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
}
Yukarıdaki kod:
- Gezinti özelliği için istekli yükleme kullanarak veritabanından
OfficeAssignment
geçerliInstructor
varlığı alır. - Alınan
Instructor
varlığı model bağlayıcısından alınan değerlerle güncelleştirir.TryUpdateModel
üst paylaşım yapılmasını engeller. - Ofis konumu boşsa null olarak ayarlanır
Instructor.OfficeAssignment
. Null olduğundaInstructor.OfficeAssignment
, tablodakiOfficeAssignment
ilgili satır silinir.
Eğitmen Düzenleme sayfasını güncelleştirme
Office konumuyla güncelleştirin Pages/Instructors/Edit.cshtml
:
@page
@model ContosoUniversity.Pages.Instructors.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Instructor.ID" />
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Eğitmenlerin ofis konumunu değiştirebildiğinizi doğrulayın.
Eğitmen Düzenleme sayfasına Kurs ödevleri ekleme
Eğitmenler herhangi bir sayıda ders verebilir. Bu bölümde, kurs ödevlerini değiştirme özelliğini ekleyebilirsiniz. Aşağıdaki görüntüde güncelleştirilmiş eğitmen Düzenleme sayfası gösterilmektedir:
Course
ve Instructor
çoka çok ilişkisine sahiptir. İlişki eklemek ve kaldırmak için birleştirme varlık kümesine CourseAssignments
varlık ekleyip kaldırabilirsiniz.
onay kutuları, eğitmenin atandığı kurslarda değişiklik yapmanızı sağlar. Veritabanındaki her kurs için bir onay kutusu görüntülenir. Eğitmenin atandığı kurslar kontrol edilir. Kullanıcı, kurs ödevlerini değiştirmek için onay kutularını seçebilir veya temizleyebilir. Ders sayısı çok daha fazlaysa:
- Büyük olasılıkla kursları görüntülemek için farklı bir kullanıcı arabirimi kullanırsınız.
- İlişki oluşturmak veya silmek için birleştirme varlığını düzenleme yöntemi değişmez.
Eğitmen sayfaları oluşturma ve düzenleme desteği için sınıf ekleme
Aşağıdaki kodla oluşturun Models/SchoolViewModels/AssignedCourseData.cs
:
namespace ContosoUniversity.Models.SchoolViewModels
{
public class AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}
sınıfı, AssignedCourseData
eğitmen tarafından atanan derslerin onay kutularını oluşturmaya yönelik veriler içerir.
Pages/Instructors/InstructorCoursesPageModel.cshtml.cs
Temel sınıfı oluşturun:
using ContosoUniversity.Data;
using ContosoUniversity.Models;
using ContosoUniversity.Models.SchoolViewModels;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Linq;
namespace ContosoUniversity.Pages.Instructors
{
public class InstructorCoursesPageModel : PageModel
{
public List<AssignedCourseData> AssignedCourseDataList;
public void PopulateAssignedCourseData(SchoolContext context,
Instructor instructor)
{
var allCourses = context.Courses;
var instructorCourses = new HashSet<int>(
instructor.CourseAssignments.Select(c => c.CourseID));
AssignedCourseDataList = new List<AssignedCourseData>();
foreach (var course in allCourses)
{
AssignedCourseDataList.Add(new AssignedCourseData
{
CourseID = course.CourseID,
Title = course.Title,
Assigned = instructorCourses.Contains(course.CourseID)
});
}
}
public void UpdateInstructorCourses(SchoolContext context,
string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(
new CourseAssignment
{
InstructorID = instructorToUpdate.ID,
CourseID = course.CourseID
});
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove
= instructorToUpdate
.CourseAssignments
.SingleOrDefault(i => i.CourseID == course.CourseID);
context.Remove(courseToRemove);
}
}
}
}
}
}
InstructorCoursesPageModel
, Düzenle ve Oluştur sayfa modelleri için kullanacağınız temel sınıftır. PopulateAssignedCourseData
doldurulacak AssignedCourseDataList
tüm Course
varlıkları okur. Her kurs için kod , başlığını ve eğitmenin kursa atanıp atanmayacağını ayarlar CourseID
. Karma Küme, verimli aramalar oluşturmak için kullanılır.
Eğitmenler Sayfa modelini düzenle
Eğitmen Sayfa modelini düzenle'yi aşağıdaki kodla güncelleştirin:
public class EditModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public EditModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments).ThenInclude(i => i.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (Instructor == null)
{
return NotFound();
}
PopulateAssignedCourseData(_context, Instructor);
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id, string[] selectedCourses)
{
if (!ModelState.IsValid)
{
return Page();
}
var instructorToUpdate = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.FirstOrDefaultAsync(s => s.ID == id);
if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(
instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
UpdateInstructorCourses(_context, selectedCourses, instructorToUpdate);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
UpdateInstructorCourses(_context, selectedCourses, instructorToUpdate);
PopulateAssignedCourseData(_context, instructorToUpdate);
return Page();
}
}
Yukarıdaki kod, office ataması değişikliklerini işler.
Eğitmen Razor Görünümünü güncelleştirin:
@page
@model ContosoUniversity.Pages.Instructors.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Instructor.ID" />
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;
foreach (var course in Model.AssignedCourseDataList)
{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Not
Kodu Visual Studio'ya yapıştırdığınızda satır sonları kodu bozabilecek şekilde değiştirilir. Otomatik biçimlendirmeyi geri almak için Ctrl+Z tuşlarına bir kez basın. Ctrl+Z tuşları satır sonlarını burada gördüğünüz gibi görünecek şekilde düzeltir. Girintinin mükemmel olması gerekmez, ancak @:</tr><tr>
, @:<td>
, @:</td>
ve @:</tr>
satırlarının her birinin gösterildiği gibi tek bir satırda olması gerekir. Yeni kod bloğu seçiliyken, yeni kodu var olan kodla aynı hizaya getirmek için Sekme tuşuna üç kez basın. Bu bağlantıyla bu hatanın durumunu oy verin veya gözden geçirin.
Yukarıdaki kod, üç sütunu olan bir HTML tablosu oluşturur. Her sütunda bir onay kutusu ve kurs numarasını ve başlığını içeren bir resim yazısı vardır. Onay kutularının tümü aynı ada ("selectedCourses") sahiptir. Aynı adın kullanılması, model bağlayıcısını bunları grup olarak ele almak için bilgilendirecektir. Her onay kutusunun değer özniteliği olarak CourseID
ayarlanır. Sayfa deftere nakledildiğinde, model bağlayıcısı yalnızca seçilen onay kutularının değerlerinden CourseID
oluşan bir dizi geçirir.
Onay kutuları başlangıçta işlendiğinde, eğitmene atanan kurslar öznitelikleri denetledi.
Uygulamayı çalıştırın ve güncelleştirilmiş eğitmenler Düzenleme sayfasını test edin. Bazı kurs ödevlerini değiştirin. Değişiklikler Dizin sayfasına yansıtılır.
Not: Eğitmen kurs verilerini düzenlemek için burada uygulanan yaklaşım, sınırlı sayıda kurs olduğunda iyi sonuç verir. Çok daha büyük koleksiyonlar için farklı bir kullanıcı arabirimi ve farklı bir güncelleştirme yöntemi daha kullanılabilir ve verimli olabilir.
Eğitmenler Oluşturma sayfasını güncelleştirme
Eğitmen Oluşturma sayfası modelini aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Instructors
{
public class CreateModel : InstructorCoursesPageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public CreateModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
public IActionResult OnGet()
{
var instructor = new Instructor();
instructor.CourseAssignments = new List<CourseAssignment>();
// Provides an empty collection for the foreach loop
// foreach (var course in Model.AssignedCourseDataList)
// in the Create Razor page.
PopulateAssignedCourseData(_context, instructor);
return Page();
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnPostAsync(string[] selectedCourses)
{
if (!ModelState.IsValid)
{
return Page();
}
var newInstructor = new Instructor();
if (selectedCourses != null)
{
newInstructor.CourseAssignments = new List<CourseAssignment>();
foreach (var course in selectedCourses)
{
var courseToAdd = new CourseAssignment
{
CourseID = int.Parse(course)
};
newInstructor.CourseAssignments.Add(courseToAdd);
}
}
if (await TryUpdateModelAsync<Instructor>(
newInstructor,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
_context.Instructors.Add(newInstructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
PopulateAssignedCourseData(_context, newInstructor);
return Page();
}
}
}
Yukarıdaki kod, koda Pages/Instructors/Edit.cshtml.cs
benzer.
Eğitmen Oluşturma Razor sayfasını aşağıdaki işaretlemeyle güncelleştirin:
@page
@model ContosoUniversity.Pages.Instructors.CreateModel
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<h4>Instructor</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;
foreach (var course in Model.AssignedCourseDataList)
{
if (cnt++ % 3 == 0)
{
@:</tr><tr>
}
@:<td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@:</tr>
}
</table>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Eğitmen Oluşturma sayfasını test edin.
Sil sayfasını güncelleştirme
Sayfayı sil modelini aşağıdaki kodla güncelleştirin:
using ContosoUniversity.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;
namespace ContosoUniversity.Pages.Instructors
{
public class DeleteModel : PageModel
{
private readonly ContosoUniversity.Data.SchoolContext _context;
public DeleteModel(ContosoUniversity.Data.SchoolContext context)
{
_context = context;
}
[BindProperty]
public Instructor Instructor { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Instructor = await _context.Instructors.SingleAsync(m => m.ID == id);
if (Instructor == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int id)
{
Instructor instructor = await _context.Instructors
.Include(i => i.CourseAssignments)
.SingleAsync(i => i.ID == id);
var departments = await _context.Departments
.Where(d => d.InstructorID == id)
.ToListAsync();
departments.ForEach(d => d.InstructorID = null);
_context.Instructors.Remove(instructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Yukarıdaki kod aşağıdaki değişiklikleri yapar:
Gezinti özelliği için hevesle
CourseAssignments
yüklemeyi kullanır.CourseAssignments
eklenmelidir veya eğitmen silindiğinde silinmez. Bunları okumak zorunda kalmamak için veritabanında art arda silmeyi yapılandırın.Silinecek eğitmen herhangi bir bölümün yöneticisi olarak atanırsa, bu departmanlardan eğitmen atamasını kaldırır.
Ek kaynaklar
ASP.NET Core