13 KiB
title | author | description | manager | ms.author | ms.date | ms.prod | ms.technology | ms.topic | uid |
---|---|---|---|---|---|---|---|---|---|
Razor Pages with EF Core in ASP.NET Core - Update Related Data - 7 of 8 | rick-anderson | In this tutorial you'll update related data by updating foreign key fields and navigation properties. | wpickett | riande | 11/15/2017 | asp.net-core | aspnet | get-started-article | data/ef-rp/update-related-data |
Razor Pages with EF Core in ASP.NET Core - Update Related Data - 7 of 8
By Tom Dykstra, and Rick Anderson
[!INCLUDEabout the series]
This tutorial demonstrates updating related data. If you run into problems you can't solve, download the completed app for this stage.
The following illustrations shows some of the completed pages.
Examine and test the Create and Edit course pages. Create a new course. The department is selected by its primary key (an integer), not its name. Edit the new course. When you have finished testing, delete the new course.
Create a base class to share common code
The Courses/Create and Courses/Edit pages each need a list of department names. Create the Pages/Courses/DepartmentNamePageModel.cshtml.cs base class for the Create and Edit pages:
The preceding code creates a SelectList to contain the list of department names. If selectedDepartment
is specified, that department is selected in the SelectList
.
The Create and Edit page model classes will derive from DepartmentNamePageModel
.
Customize the Courses Pages
When a new course entity is created, it must have a relationship to an existing department. To add a department while creating a course, the base class for Create and Edit contains a drop-down list for selecting the department. The drop-down list sets the Course.DepartmentID
foreign key (FK) property. EF Core uses the Course.DepartmentID
FK to load the Department
navigation property.
Update the Create page model with the following code:
The preceding code:
- Derives from
DepartmentNamePageModel
. - Uses
TryUpdateModelAsync
to prevent overposting. - Replaces
ViewData["DepartmentID"]
withDepartmentNameSL
(from the base class).
ViewData["DepartmentID"]
is replaced with the strongly typed DepartmentNameSL
. Strongly typed models are preferred over weakly typed. For more information, see Weakly typed data (ViewData and ViewBag).
Update the Courses Create page
Update Pages/Courses/Create.cshtml with the following markup:
The preceding markup makes the following changes:
- Changes the caption from DepartmentID to Department.
- Replaces
"ViewBag.DepartmentID"
withDepartmentNameSL
(from the base class). - Adds the "Select Department" option. This change renders "Select Department" rather than the first department.
- Adds a validation message when the department isn't selected.
The Razor Page uses the Select Tag Helper:
Test the Create page. The Create page displays the department name rather than the department ID.
Update the Courses Edit page.
Update the edit page model with the following code:
The changes are similar to those made in the Create page model. In the preceding code, PopulateDepartmentsDropDownList
passes in the department ID, which select the department specified in the drop-down list.
Update Pages/Courses/Edit.cshtml with the following markup:
The preceding markup makes the following changes:
- Displays the course ID. Generally the Primary Key (PK) of an entity isn't displayed. PKs are usually meaningless to users. In this case, the PK is the course number.
- Changes the caption from DepartmentID to Department.
- Replaces
"ViewBag.DepartmentID"
withDepartmentNameSL
(from the base class). - Adds the "Select Department" option. This change renders "Select Department" rather than the first department.
- Adds a validation message when the department isn't selected.
The page contains a hidden field (<input type="hidden">
) for the course number. Adding a <label>
tag helper with asp-for="Course.CourseID"
doesn't eliminate the need for the hidden field. <input type="hidden">
is required for the course number to be included in the posted data when the user clicks Save.
Test the updated code. Create, edit, and delete a course.
Add AsNoTracking to the Details and Delete page models
AsNoTracking can improve performance when tracking isn't required. Add AsNoTracking
to the Delete and Details page model. The following code shows the updated Delete page model:
Update the OnGetAsync
method in the Pages/Courses/Details.cshtml.cs file:
Modify the Delete and Details pages
Update the Delete Razor page with the following markup:
Make the same changes to the Details page.
Test the Course pages
Test create, edit, details, and delete.
Update the instructor pages
The following sections update the instructor pages.
Add office location
When editing an instructor record, you may want to update the instructor's office assignment. The Instructor
entity has a one-to-zero-or-one relationship with the OfficeAssignment
entity. The instructor code must handle:
- If the user clears the office assignment, delete the
OfficeAssignment
entity. - If the user enters an office assignment and it was empty, create a new
OfficeAssignment
entity. - If the user changes the office assignment, update the
OfficeAssignment
entity.
Update the instructors Edit page model with the following code:
The preceding code:
- Gets the current
Instructor
entity from the database using eager loading for theOfficeAssignment
navigation property. - Updates the retrieved
Instructor
entity with values from the model binder.TryUpdateModel
prevents overposting. - If the office location is blank, sets
Instructor.OfficeAssignment
to null. WhenInstructor.OfficeAssignment
is null, the related row in theOfficeAssignment
table is deleted.
Update the instructor Edit page
Update Pages/Instructors/Edit.cshtml with the office location:
Verify you can change an instructors office location.
Add Course assignments to the instructor Edit page
Instructors may teach any number of courses. In this section, you add the ability to change course assignments. The following image shows the updated instructor Edit page:
Course
and Instructor
has a many-to-many relationship. To add and remove relationships, you add and remove entities from the CourseAssignments
join entity set.
Check boxes enable changes to courses an instructor is assigned to. A check box is displayed for every course in the database. Courses that the instructor is assigned to are checked. The user can select or clear check boxes to change course assignments. If the number of courses were much greater:
- You'd probably use a different user interface to display the courses.
- The method of manipulating a join entity to create or delete relationships wouldn't change.
Add classes to support Create and Edit instructor pages
Create SchoolViewModels/AssignedCourseData.cs with the following code:
The AssignedCourseData
class contains data to create the check boxes for assigned courses by an instructor.
Create the Pages/Instructors/InstructorCoursesPageModel.cshtml.cs base class:
The InstructorCoursesPageModel
is the base class you will use for the Edit and Create page models. PopulateAssignedCourseData
reads all Course
entities to populate AssignedCourseDataList
. For each course, the code sets the CourseID
, title, and whether or not the instructor is assigned to the course. A HashSet is used to create efficient lookups.
Instructors Edit page model
Update the instructor Edit page model with the following code:
The preceding code handles office assignment changes.
Update the instructor Razor View:
[!NOTE] When you paste the code in Visual Studio, line breaks are changed in a way that breaks the code. Press Ctrl+Z one time to undo the automatic formatting. Ctrl+Z fixes the line breaks so that they look like what you see here. The indentation doesn't have to be perfect, but the
@</tr><tr>
,@:<td>
,@:</td>
, and@:</tr>
lines must each be on a single line as shown. With the block of new code selected, press Tab three times to line up the new code with the existing code. Vote on or review the status of this bug with this link.
The preceding code creates an HTML table that has three columns. Each column has a check box and a caption containing the course number and title. The check boxes all have the same name ("selectedCourses"). Using the same name informs the model binder to treat them as a group. The value attribute of each check box is set to CourseID
. When the page is posted, the model binder passes an array that consists of the CourseID
values for only the check boxes that are selected.
When the check boxes are initially rendered, courses assigned to the instructor have checked attributes.
Run the app and test the updated instructors Edit page. Change some course assignments. The changes are reflected on the Index page.
Note: The approach taken here to edit instructor course data works well when there's a limited number of courses. For collections that are much larger, a different UI and a different updating method would be more useable and efficient.
Update the instructors Create page
Update the instructor Create page model with the following code:
The preceding code is similar to the Pages/Instructors/Edit.cshtml.cs code.
Update the instructor Create Razor page with the following markup:
Test the instructor Create page.
Update the Delete page
Update the Delete page model with the following code:
The preceding code makes the following changes:
-
Uses eager loading for the
CourseAssignments
navigation property.CourseAssignments
must be included or they aren't deleted when the instructor is deleted. To avoid needing to read them, configure cascade delete in the database. -
If the instructor to be deleted is assigned as administrator of any departments, removes the instructor assignment from those departments.