在 ASP.NET Core 應(yīng)用中更新生成的頁面
構(gòu)架的電影應(yīng)用有個(gè)不錯(cuò)的開始,但是展示效果還不夠理想梯浪。 ReleaseDate 應(yīng)是 Release Date (兩個(gè)詞)捌年。
更新生成的代碼
打開 Models/Movie.cs 文件,并添加以下代碼中突出顯示的行 :
C#復(fù)制
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
}
[Column(TypeName = "decimal(18, 2)")]
數(shù)據(jù)注釋使 Entity Framework Core 可以將 Price
正確映射到數(shù)據(jù)庫中的貨幣挂洛。 有關(guān)詳細(xì)信息礼预,請(qǐng)參閱數(shù)據(jù)類型。
DataAnnotations 未包括在下一個(gè)教程中抹锄。 Display 特性指定要顯示的字段名稱的內(nèi)容(本例中應(yīng)為“Release Date”逆瑞,而不是“ReleaseDate”)。 DataType 屬性指定數(shù)據(jù)的類型(日期)伙单,使字段中存儲(chǔ)的時(shí)間信息不會(huì)顯示。
瀏覽到 Pages/Movies哈肖,并將鼠標(biāo)懸停在“編輯”鏈接上以查看目標(biāo) URL 吻育。
“編輯”淤井、“詳細(xì)信息”和“刪除”鏈接是在 Pages/Movies/Index.cshtml 文件中由定位標(biāo)記幫助程序生成的 布疼。
CSHTML復(fù)制
@foreach (var item in Model.Movie) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
標(biāo)記幫助程序使服務(wù)器端代碼可以在 Razor 文件中參與創(chuàng)建和呈現(xiàn) HTML 元素摊趾。 在前面的代碼中,AnchorTagHelper
從 Razor 頁面(路由是相對(duì)的)宛乃、asp-page
和路由 ID (asp-route-id
) 動(dòng)態(tài)生成 HTML href
特性值骇陈。 有關(guān)詳細(xì)信息枢贿,請(qǐng)參閱頁面的 URL 生成。
在最喜歡的瀏覽器中使用“查看源”來檢查生成的標(biāo)記 肛炮。 生成的 HTML 的一部分如下所示:
HTML復(fù)制
<td>
<a href="/Movies/Edit?id=1">Edit</a> |
<a href="/Movies/Details?id=1">Details</a> |
<a href="/Movies/Delete?id=1">Delete</a>
</td>
動(dòng)態(tài)生成的鏈接通過查詢字符串傳遞電影 ID(例如,https://localhost:5001/Movies/Details?id=1
中的 ?id=1
)宝踪。
更新“編輯”侨糟、“詳細(xì)信息”和“刪除”Razor 頁面以使用“{id:int?}”路由模板。 將上述每個(gè)頁面的頁面指令從 @page
更改為 @page "{id:int}"
瘩燥。 運(yùn)行應(yīng)用秕重,然后查看源。 生成的 HTML 會(huì)將 ID 添加到 URL 的路徑部分:
HTML復(fù)制
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
如果對(duì)具有“{id: int}” 路由模板的頁面進(jìn)行的請(qǐng)求中不包含整數(shù)厉膀,則將返回 HTTP 404(未找到)錯(cuò)誤溶耘。 例如,http://localhost:5000/Movies/Details
將返回 404 錯(cuò)誤服鹅。 若要使 ID 可選汰具,請(qǐng)將 ?
追加到路由約束:
CSHTML復(fù)制
@page "{id:int?}"
若要測試 @page "{id:int?}"
的行為:
- 在 Pages/Movies/Details.cshtml 中將 page 指令設(shè)置為
@page "{id:int?}"
。 - 在
public async Task<IActionResult> OnGetAsync(int? id)
中(位于 Pages/Movies/Details.cshtml.cs 中)設(shè)置斷點(diǎn)菱魔。 - 導(dǎo)航到
https://localhost:5001/Movies/Details/
留荔。
使用 @page "{id:int}"
指令時(shí),永遠(yuǎn)不會(huì)命中斷點(diǎn)澜倦。 路由引擎返回 HTTP 404聚蝶。 使用 @page "{id:int?}"
時(shí),OnGetAsync
方法返回 NotFound
(HTTP 404)藻治。
查看并發(fā)異常處理
查看 Pages/Movies/Edit.cshtml.cs 文件中的 OnPostAsync
方法 :
C#復(fù)制
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Movie).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool MovieExists(int id)
{
return _context.Movie.Any(e => e.ID == id);
}
當(dāng)一個(gè)客戶端刪除電影并且另一個(gè)客戶端對(duì)電影發(fā)布更改時(shí)碘勉,前面的代碼會(huì)檢測并發(fā)異常。
測試 catch
塊:
- 在
catch (DbUpdateConcurrencyException)
上設(shè)置斷點(diǎn) - 對(duì)電影選擇“編輯” 桩卵,進(jìn)行更改验靡,但不要輸入“保存” 。
- 在其他瀏覽器窗口中雏节,選擇同一電影的“刪除”鏈接胜嗓,然后刪除此電影。
- 在之前的瀏覽器窗口中钩乍,將更改發(fā)布到電影辞州。
生產(chǎn)代碼可能要檢測并發(fā)沖突。 有關(guān)詳細(xì)信息寥粹,請(qǐng)參閱處理并發(fā)沖突变过。
發(fā)布和綁定審閱
檢查 Pages/Movies/Edit.cshtml.cs 文件 :
C#復(fù)制
public class EditModel : PageModel
{
private readonly RazorPagesMovieContext _context;
public EditModel(RazorPagesMovieContext context)
{
_context = context;
}
[BindProperty]
public Movie Movie { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);
if (Movie == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Movie).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!_context.Movie.Any(e => e.ID == Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
}
當(dāng)對(duì) Movies/Edit 頁面進(jìn)行 HTTP GET 請(qǐng)求時(shí)(例如 http://localhost:5000/Movies/Edit/2
):
-
OnGetAsync
方法從數(shù)據(jù)庫提取電影并返回Page
方法埃元。 -
Page
方法呈現(xiàn)“Pages/Movies/Edit.cshtml”Razor 頁面。 Pages/Movies/Edit.cshtml 文件包含模型指令 (@model RazorPagesMovie.Pages.Movies.EditModel
)媚狰,這使電影模型在頁面上可用岛杀。 - “編輯”表單中會(huì)顯示電影的值。
當(dāng)發(fā)布 Movies/Edit 頁面時(shí):
-
此頁面上的表單值將綁定到
Movie
屬性崭孤。[BindProperty]
特性會(huì)啟用模型綁定类嗤。C#復(fù)制
[BindProperty] public Movie Movie { get; set; }
如果模型狀態(tài)中存在錯(cuò)誤(例如,
ReleaseDate
無法被轉(zhuǎn)換為日期)裳瘪,則會(huì)使用已提交的值顯示表單土浸。如果沒有模型錯(cuò)誤,則電影已保存彭羹。
“索引”黄伊、“創(chuàng)建”和“刪除”Razor 頁面中的 HTTP GET 方法遵循一個(gè)類似的模式。 “創(chuàng)建”Razor 頁面中的 HTTP POST OnPostAsync
方法遵循的模式類似于“編輯”Razor 頁面中的 OnPostAsync
方法所遵循的模式派殷。
在下一教程中將添加搜索还最。