replace viewData with strong types (#4924)
* replace viewData with strong types * work * workpull/4925/head
parent
b155aeda42
commit
152469f1ce
|
@ -198,7 +198,9 @@ In a web app, the `DbContext` that reads an entity and displays the data is disp
|
|||
|
||||
## Update the Delete page
|
||||
|
||||
In this section, code is added to implement a custom error message when the call to `SaveChanges` fails.
|
||||
In this section, code is added to implement a custom error message when the call to `SaveChanges` fails. Add a string to contain possile error messages:
|
||||
|
||||
[!code-csharp[Main](intro/samples/cu/Pages/Students/Delete.cshtml.cs?name=snippet1&highlight=12)]
|
||||
|
||||
Replace the `OnGetAsync` method with the following code:
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<form sp-page="./Index" method="get">
|
||||
<div class="form-actions no-color">
|
||||
<p>
|
||||
Find by name: <input type="text" name="SearchString" value="@ViewData["currentFilter"]" />
|
||||
Find by name: <input type="text" name="SearchString" value="@Model.CurrentFilter" />
|
||||
<input type="submit" value="Search" class="btn btn-default" /> |
|
||||
<a asp-page="./Index">Back to full List</a>
|
||||
</p>
|
||||
|
@ -25,8 +25,8 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a asp-page="./Index" asp-route-sortOrder="@ViewData["NameSort"]"
|
||||
asp-route-currentFilter="@ViewData["CurrentFilter"]">
|
||||
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"
|
||||
asp-route-currentFilter="@Model.CurrentFilter">
|
||||
@Html.DisplayNameFor(model => model.Student[0].LastName)
|
||||
</a>
|
||||
</th>
|
||||
|
@ -34,8 +34,8 @@
|
|||
@Html.DisplayNameFor(model => model.Student[0].FirstMidName)
|
||||
</th>
|
||||
<th>
|
||||
<a asp-page="./Index" asp-route-sortOrder="@ViewData["DateSort"]"
|
||||
asp-route-currentFilter="@ViewData["CurrentFilter"]">
|
||||
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort"
|
||||
asp-route-currentFilter="@Model.CurrentFilter">
|
||||
@Html.DisplayNameFor(model => model.Student[0].EnrollmentDate)
|
||||
</a>
|
||||
</th>
|
||||
|
@ -71,16 +71,16 @@
|
|||
}
|
||||
|
||||
<a asp-page="./Index"
|
||||
asp-route-sortOrder="@ViewData["CurrentSort"]"
|
||||
asp-route-sortOrder="@Model.CurrentSort"
|
||||
asp-route-pageIndex="@(Model.Student.PageIndex - 1)"
|
||||
asp-route-currentFilter="@ViewData["CurrentFilter"]"
|
||||
asp-route-currentFilter="@Model.CurrentFilter"
|
||||
class="btn btn-default @prevDisabled">
|
||||
Previous
|
||||
</a>
|
||||
<a asp-page="./Index"
|
||||
asp-route-sortOrder="@ViewData["CurrentSort"]"
|
||||
asp-route-sortOrder="@Model.CurrentSort"
|
||||
asp-route-pageIndex="@(Model.Student.PageIndex + 1)"
|
||||
asp-route-currentFilter="@ViewData["CurrentFilter"]"
|
||||
asp-route-currentFilter="@Model.CurrentFilter"
|
||||
class="btn btn-default @nextDisabled">
|
||||
Next
|
||||
</a>
|
|
@ -1,12 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ContosoUniversity.Models;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ContosoUniversity.Data;
|
||||
using ContosoUniversity.Models;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ContosoUniversity.Pages.Students
|
||||
{
|
||||
|
@ -20,13 +17,17 @@ namespace ContosoUniversity.Pages.Students
|
|||
}
|
||||
|
||||
public PaginatedList<Student> Student { get; set; }
|
||||
public string NameSort { get; set; }
|
||||
public string DateSort { get; set; }
|
||||
public string CurrentFilter { get; set; }
|
||||
public string CurrentSort { get; set; }
|
||||
|
||||
public async Task OnGetAsync(string sortOrder,
|
||||
string currentFilter, string searchString, int? pageIndex)
|
||||
{
|
||||
ViewData["CurrentSort"] = sortOrder;
|
||||
ViewData["NameSort"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
|
||||
ViewData["DateSort"] = sortOrder == "Date" ? "date_desc" : "Date";
|
||||
CurrentSort = sortOrder;
|
||||
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
|
||||
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
|
||||
if (searchString != null)
|
||||
{
|
||||
pageIndex = 1;
|
||||
|
@ -36,7 +37,7 @@ namespace ContosoUniversity.Pages.Students
|
|||
searchString = currentFilter;
|
||||
}
|
||||
|
||||
ViewData["CurrentFilter"] = searchString;
|
||||
CurrentFilter = searchString;
|
||||
|
||||
IQueryable<Student> studentIQ = from s in _context.Students
|
||||
select s;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<h2>Delete</h2>
|
||||
|
||||
<p class="text-danger">@ViewData["ErrorMessage"]</p>
|
||||
<p class="text-danger">@Model.ErrorMessage</p>
|
||||
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
<div>
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace ContosoUniversity.Pages.Students
|
||||
{
|
||||
#region snippet1
|
||||
public class DeleteModel : PageModel
|
||||
{
|
||||
private readonly ContosoUniversity.Data.SchoolContext _context;
|
||||
|
@ -17,6 +18,8 @@ namespace ContosoUniversity.Pages.Students
|
|||
|
||||
[BindProperty]
|
||||
public Student Student { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
#endregion
|
||||
|
||||
#region snippet_OnGetAsync
|
||||
public async Task<IActionResult> OnGetAsync(int? id, bool? saveChangesError = false)
|
||||
|
@ -28,7 +31,7 @@ namespace ContosoUniversity.Pages.Students
|
|||
|
||||
Student = await _context.Students
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync (m => m.ID == id);
|
||||
.FirstOrDefaultAsync(m => m.ID == id);
|
||||
|
||||
if (Student == null)
|
||||
{
|
||||
|
@ -37,7 +40,7 @@ namespace ContosoUniversity.Pages.Students
|
|||
|
||||
if (saveChangesError.GetValueOrDefault())
|
||||
{
|
||||
ViewData["ErrorMessage"] = "Delete failed. Try again";
|
||||
ErrorMessage = "Delete failed. Try again";
|
||||
}
|
||||
|
||||
return Page();
|
||||
|
@ -54,7 +57,7 @@ namespace ContosoUniversity.Pages.Students
|
|||
|
||||
var student = await _context.Students
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync (m => m.ID == id);
|
||||
.FirstOrDefaultAsync(m => m.ID == id);
|
||||
|
||||
if (student == null)
|
||||
{
|
||||
|
@ -70,7 +73,7 @@ namespace ContosoUniversity.Pages.Students
|
|||
catch (DbUpdateException /* ex */)
|
||||
{
|
||||
//Log the error (uncomment ex variable name and write a log.)
|
||||
return RedirectToAction("./Delete",
|
||||
return RedirectToAction("./Delete",
|
||||
new { id = id, saveChangesError = true });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<form sp-page="./Index" method="get">
|
||||
<div class="form-actions no-color">
|
||||
<p>
|
||||
Find by name: <input type="text" name="SearchString" value="@ViewData["currentFilter"]" />
|
||||
Find by name: <input type="text" name="SearchString" value="@Model.CurrentFilter" />
|
||||
<input type="submit" value="Search" class="btn btn-default" /> |
|
||||
<a asp-page="./Index">Back to full List</a>
|
||||
</p>
|
||||
|
@ -25,8 +25,8 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a asp-page="./Index" asp-route-sortOrder="@ViewData["NameSort"]"
|
||||
asp-route-currentFilter="@ViewData["CurrentFilter"]">
|
||||
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort"
|
||||
asp-route-currentFilter="@Model.CurrentFilter">
|
||||
@Html.DisplayNameFor(model => model.Student[0].LastName)
|
||||
</a>
|
||||
</th>
|
||||
|
@ -34,8 +34,8 @@
|
|||
@Html.DisplayNameFor(model => model.Student[0].FirstMidName)
|
||||
</th>
|
||||
<th>
|
||||
<a asp-page="./Index" asp-route-sortOrder="@ViewData["DateSort"]"
|
||||
asp-route-currentFilter="@ViewData["CurrentFilter"]">
|
||||
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort"
|
||||
asp-route-currentFilter="@Model.CurrentFilter">
|
||||
@Html.DisplayNameFor(model => model.Student[0].EnrollmentDate)
|
||||
</a>
|
||||
</th>
|
||||
|
@ -70,16 +70,16 @@
|
|||
}
|
||||
|
||||
<a asp-page="./Index"
|
||||
asp-route-sortOrder="@ViewData["CurrentSort"]"
|
||||
asp-route-sortOrder="@Model.CurrentSort"
|
||||
asp-route-pageIndex="@(Model.Student.PageIndex - 1)"
|
||||
asp-route-currentFilter="@ViewData["CurrentFilter"]"
|
||||
asp-route-currentFilter="@Model.CurrentFilter"
|
||||
class="btn btn-default @prevDisabled">
|
||||
Previous
|
||||
</a>
|
||||
<a asp-page="./Index"
|
||||
asp-route-sortOrder="@ViewData["CurrentSort"]"
|
||||
asp-route-sortOrder="@Model.CurrentSort"
|
||||
asp-route-pageIndex="@(Model.Student.PageIndex + 1)"
|
||||
asp-route-currentFilter="@ViewData["CurrentFilter"]"
|
||||
asp-route-currentFilter="@Model.CurrentFilter"
|
||||
class="btn btn-default @nextDisabled">
|
||||
Next
|
||||
</a>
|
|
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace ContosoUniversity.Pages.Students
|
||||
{
|
||||
#region snippet1
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly ContosoUniversity.Data.SchoolContext _context;
|
||||
|
@ -19,6 +20,12 @@ namespace ContosoUniversity.Pages.Students
|
|||
_context = context;
|
||||
}
|
||||
|
||||
public string NameSort { get; set; }
|
||||
public string DateSort { get; set; }
|
||||
public string CurrentFilter { get; set; }
|
||||
public string CurrentSort { get; set; }
|
||||
#endregion
|
||||
|
||||
#if SortFilterPage
|
||||
#region snippet_SortFilterPageType
|
||||
public PaginatedList<Student> Student { get; set; }
|
||||
|
@ -41,8 +48,8 @@ namespace ContosoUniversity.Pages.Students
|
|||
public async Task OnGetAsync(string sortOrder)
|
||||
{
|
||||
#region snippet_Ternary
|
||||
ViewData["NameSort"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
|
||||
ViewData["DateSort"] = sortOrder == "Date" ? "date_desc" : "Date";
|
||||
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
|
||||
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
|
||||
#endregion
|
||||
|
||||
IQueryable<Student> studentIQ = from s in _context.Students
|
||||
|
@ -74,9 +81,9 @@ namespace ContosoUniversity.Pages.Students
|
|||
#region snippet_SortFilter
|
||||
public async Task OnGetAsync(string sortOrder, string searchString)
|
||||
{
|
||||
ViewData["NameSort"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
|
||||
ViewData["DateSort"] = sortOrder == "Date" ? "date_desc" : "Date";
|
||||
ViewData["CurrentFilter"] = searchString;
|
||||
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
|
||||
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
|
||||
CurrentFilter = searchString;
|
||||
|
||||
IQueryable<Student> studentIQ = from s in _context.Students
|
||||
select s;
|
||||
|
@ -113,9 +120,9 @@ namespace ContosoUniversity.Pages.Students
|
|||
string currentFilter, string searchString, int? pageIndex)
|
||||
#endregion
|
||||
{
|
||||
ViewData["CurrentSort"] = sortOrder;
|
||||
ViewData["NameSort"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
|
||||
ViewData["DateSort"] = sortOrder == "Date" ? "date_desc" : "Date";
|
||||
CurrentSort = sortOrder;
|
||||
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
|
||||
DateSort = sortOrder == "Date" ? "date_desc" : "Date";
|
||||
#region snippet_SortFilterPage3
|
||||
if (searchString != null)
|
||||
{
|
||||
|
@ -127,7 +134,7 @@ namespace ContosoUniversity.Pages.Students
|
|||
}
|
||||
#endregion
|
||||
|
||||
ViewData["CurrentFilter"] = searchString;
|
||||
CurrentFilter = searchString;
|
||||
|
||||
IQueryable<Student> studentIQ = from s in _context.Students
|
||||
select s;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a asp-page="./Index" asp-route-sortOrder="@ViewData["NameSort"]">
|
||||
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
|
||||
@Html.DisplayNameFor(model => model.Student[0].LastName)
|
||||
</a>
|
||||
</th>
|
||||
|
@ -22,7 +22,7 @@
|
|||
@Html.DisplayNameFor(model => model.Student[0].FirstMidName)
|
||||
</th>
|
||||
<th>
|
||||
<a asp-page="./Index" asp-route-sortOrder="@ViewData["DateSort"]">
|
||||
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort">
|
||||
@Html.DisplayNameFor(model => model.Student[0].EnrollmentDate)
|
||||
</a>
|
||||
</th>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<div class="form-actions no-color">
|
||||
<p>
|
||||
Find by name:
|
||||
<input type="text" name="SearchString" value="@ViewData["currentFilter"]" />
|
||||
<input type="text" name="SearchString" value="@Model.CurrentFilter" />
|
||||
<input type="submit" value="Search" class="btn btn-default" /> |
|
||||
<a asp-page="./Index">Back to full List</a>
|
||||
</p>
|
||||
|
@ -26,7 +26,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a asp-page="./Index" asp-route-sortOrder="@ViewData["NameSort"]">
|
||||
<a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
|
||||
@Html.DisplayNameFor(model => model.Student[0].LastName)
|
||||
</a>
|
||||
</th>
|
||||
|
@ -34,7 +34,7 @@
|
|||
@Html.DisplayNameFor(model => model.Student[0].FirstMidName)
|
||||
</th>
|
||||
<th>
|
||||
<a asp-page="./Index" asp-route-sortOrder="@ViewData["DateSort"]">
|
||||
<a asp-page="./Index" asp-route-sortOrder="@Model.DateSort">
|
||||
@Html.DisplayNameFor(model => model.Student[0].EnrollmentDate)
|
||||
</a>
|
||||
</th>
|
||||
|
|
|
@ -27,6 +27,11 @@ If you run into problems you can't solve, download the [completed app for this s
|
|||
|
||||
## Add sorting to the Index page
|
||||
|
||||
Add strings to the *Students/Index.cshtml.cs* `PageModel` to contain the sorting paramaters:
|
||||
|
||||
[!code-csharp[Main](intro/samples/cu/Pages/Students/Index.cshtml.cs?name=snippet1&highlight=10-13)]
|
||||
|
||||
|
||||
Update the *Students/Index.cshtml.cs* `OnGetAsync` with the following code:
|
||||
|
||||
[!code-csharp[Main](intro/samples/cu/Pages/Students/Index.cshtml.cs?name=snippet_SortOnly)]
|
||||
|
@ -38,17 +43,15 @@ The `sortOrder` parameter is either "Name" or "Date." The `sortOrder` parameter
|
|||
|
||||
When the Index page is requested from the **Students** link, there's no query string. The students are displayed in ascending order by last name. Ascending order by last name is the default (fall-through case) in the `switch` statement. When the user clicks a column heading link, the appropriate `sortOrder` value is provided in the query string value.
|
||||
|
||||
The two `ViewData` elements (`NameSort` and `DateSort`) are used by the Razor Page to configure the column heading hyperlinks with the appropriate query string values:
|
||||
`NameSort` and `DateSort` are used by the Razor Page to configure the column heading hyperlinks with the appropriate query string values:
|
||||
|
||||
[!code-csharp[Main](intro/samples/cu/Pages/Students/Index.cshtml.cs?name=snippet_SortOnly&highlight=3-4)]
|
||||
|
||||
`ViewData` is a [ViewDataDictionary](/aspnet/core/api/microsoft.aspnetcore.mvc.viewfeatures.viewdatadictionary) object accessed through `string` keys. `ViewData` provides a convenient way to pass data from a Razor Page to a code-behind file, and from a code-behind file to a Razor Page. For more information, see [Weakly typed data (ViewData and ViewBag)](xref:mvc/views/overview#VD_VB) and [ViewData](xref:mvc/views/overview#VD).
|
||||
|
||||
The following code contains the C# [?: operator](https://docs.microsoft.com/dotnet/csharp/language-reference/operators/conditional-operator):
|
||||
|
||||
[!code-csharp[Main](intro/samples/cu/Pages/Students/Index.cshtml.cs?name=snippet_Ternary)]
|
||||
|
||||
The first line specifies that when `sortOrder` is null or empty, `NameSort` is set to "name_desc." If `sortOrder` is **not** null or empty, `NameSort` is set to an empty string.
|
||||
The first line specifies that when `sortOrder` is null or empty, `NameSort` is set to "name_desc." If `sortOrder` is **not** null or empty, `NameSort` is set to an empty string.
|
||||
|
||||
The `?: operator` is also known as the ternary operator.
|
||||
|
||||
|
@ -80,7 +83,7 @@ Replace the code in *Students/Index.cshtml*, with the following highlighted code
|
|||
The preceding code:
|
||||
|
||||
* Adds hyperlinks to the `LastName` and `EnrollmentDate` column headings.
|
||||
* Uses the information in `ViewData` dictionary to set up hyperlinks with the current sort order values.
|
||||
* Uses the information in `NameSort` and `DateSort` to set up hyperlinks with the current sort order values.
|
||||
|
||||
To verify that sorting works:
|
||||
|
||||
|
@ -91,7 +94,7 @@ To verify that sorting works:
|
|||
To get a better understanding of the code:
|
||||
|
||||
* In *Student/Index.cshtml.cs*, set a breakpoint on `switch (sortOrder)`.
|
||||
* Add a watch for `ViewData["NameSort"]` and `ViewData["DateSort"]`.
|
||||
* Add a watch for `NameSort` and `DateSort`.
|
||||
* In *Student/Index.cshtml*, set a breakpoint on `@Html.DisplayNameFor(model => model.Student[0].LastName)`.
|
||||
|
||||
Step through the debugger.
|
||||
|
@ -185,9 +188,9 @@ All the parameters are null when:
|
|||
|
||||
When a paging link is clicked, the page index variable contains the page number to display.
|
||||
|
||||
`ViewData["CurrentSort"]` provides the Razor Page with the current sort order. The current sort order must be included in the paging links to keep the sort order while paging.
|
||||
`CurrentSort` provides the Razor Page with the current sort order. The current sort order must be included in the paging links to keep the sort order while paging.
|
||||
|
||||
`ViewData["CurrentFilter"]` provides the Razor Page with the current filter string. The `ViewData["CurrentFilter"]` value:
|
||||
`CurrentFilter` provides the Razor Page with the current filter string. The `CurrentFilter` value:
|
||||
|
||||
* Must be included in the paging links in order to maintain the filter settings during paging.
|
||||
* Must be restored to the text box when the page is redisplayed.
|
||||
|
@ -229,7 +232,7 @@ Run the app and navigate to the students page.
|
|||
To get a better understanding of the code:
|
||||
|
||||
* In *Student/Index.cshtml.cs*, set a breakpoint on `switch (sortOrder)`.
|
||||
* Add a watch for `ViewData["NameSort"]`, `ViewData["DateSort"]`, ViewData["CurrentSort"], and `Model.Student.PageIndex`.
|
||||
* Add a watch for `NameSort`, `DateSort`, `CurrentSort`, and `Model.Student.PageIndex`.
|
||||
* In *Student/Index.cshtml*, set a breakpoint on `@Html.DisplayNameFor(model => model.Student[0].LastName)`.
|
||||
|
||||
Step through the debugger.
|
||||
|
|
Loading…
Reference in New Issue