Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Anmärkning
Det här är inte den senaste versionen av den här artikeln. Den aktuella versionen finns i .NET 10-versionen av den här artikeln.
Varning
Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i supportpolicyn för .NET och .NET Core. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Den scaffolded filmappen har en bra start, men presentationen är inte idealisk. ReleaseDate ska vara två ord, Utgivningsdatum.
Uppdatera modellen
Uppdatera Models/Movie.cs med följande markerade kod:
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; } = string.Empty;
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; } = string.Empty;
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
I föregående kod:
- Med
[Column(TypeName = "decimal(18, 2)")]dataanteckningen kan Entity Framework Core mappaPricetill valuta i databasen på rätt sätt. Mer information finns i Datatyper. - Attributet [Display] anger visningsnamnet för ett fält. I den föregående koden,
Release Datei stället förReleaseDate. - Attributet [DataType] anger typen av data (
Date). Tidsinformationen som lagras i fältet visas inte.
DataAnnotationer beskrivs i nästa handledning.
Bläddra till Sidor/Filmer och hovra över en Redigera-länk för att se mål-URL:en.
Länkarna Redigera, Information och Ta bort genereras av fästpunktstagghjälpenPages/Movies/Index.cshtml i filen.
@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>
Tagghjälpare gör det möjligt för kod på serversidan att delta i skapandet och återgivningen av HTML-element i Razor filer.
I föregående kod genererar hjälpverktyget för fästpunkt dynamiskt HTML-attributvärdet href från Razor sidan (vägen är relativ), asp-page, och vägidentifieraren (asp-route-id). Mer information finns i URL-generering för sidor.
Använd Visa källa från en webbläsare för att undersöka den genererade markeringen. En del av den genererade HTML-koden visas nedan:
<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>
De dynamiskt genererade länkarna skickar film-ID:t med en frågesträng. Till exempel ?id=1 i https://localhost:5001/Movies/Details?id=1.
Lägg till routningsmall
Uppdatera redigera, information och ta bort Razor sidor för att använda routningsmallen {id:int} . Ändra siddirektivet för var och en av dessa sidor från @page till @page "{id:int}". Kör appen och visa sedan källan.
Den genererade HTML-koden lägger till ID:t i sökvägsdelen av URL:en:
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
En begäran till sidan med {id:int} routemallen som inte innehåller heltal returnerar ett HTTP 404-fel (sidan kunde inte hittas). Returnerar https://localhost:5001/Movies/Details till exempel ett 404-fel. Om du vill göra ID:t valfritt lägger du till i routningsbegränsningen ? :
@page "{id:int?}"
Testa beteendet av @page "{id:int?}":
- Ange siddirektivet i
Pages/Movies/Details.cshtmltill@page "{id:int?}". - Ange en brytpunkt i
public async Task<IActionResult> OnGetAsync(int? id)iPages/Movies/Details.cshtml.cs. - Gå till
https://localhost:5001/Movies/Details/.
Med direktivet @page "{id:int}" uppnås aldrig brytpunkten. Routningsmotorn returnerar HTTP 404. Metoden OnGetAsync returnerar NotFound med @page "{id:int?}" (HTTP 404):
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
else
{
Movie = movie;
}
return Page();
}
Granska hantering av samtidighetsfel
OnPostAsync Granska metoden i Pages/Movies/Edit.cshtml.cs filen:
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);
}
Den tidigare koden identifierar samtidighetsfel när en klient tar bort filmen och den andra klienten publicerar ändringar i filmen.
Så här testar du catch blocket:
- Ange en brytpunkt på
catch (DbUpdateConcurrencyException). - Välj Redigera för en film, gör ändringar, men ange inte Spara.
- I ett annat webbläsarfönster väljer du länken Ta bort för samma film och tar sedan bort filmen.
- I föregående webbläsarfönster publicerar du ändringar i filmen.
Produktionskoden kanske vill identifiera samtidighetskonflikter. Mer information finns i Hantera samtidighetskonflikter .
Granskning av publicering och koppling
Pages/Movies/Edit.cshtml.cs Granska filen:
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public EditModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
[BindProperty]
public Movie Movie { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
Movie = movie;
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see https://aka.ms/RazorPagesCRUD.
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);
}
När en HTTP GET-begäran görs till sidan Filmer/Redigera, https://localhost:5001/Movies/Edit/3till exempel :
- Metoden
OnGetAsynchämtar filmen från databasen och returnerarPagemetoden. - Metoden
PagerenderarPages/Movies/Edit.cshtmlRazor sidan. FilenPages/Movies/Edit.cshtmlinnehåller modelldirektivet@model RazorPagesMovie.Pages.Movies.EditModel, vilket gör filmmodellen tillgänglig på sidan. - Formuläret Redigera visas med värdena från filmen.
När sidan Filmer/Redigera publiceras:
Formulärvärdena på sidan är bundna till egenskapen
Movie. Attributet[BindProperty]aktiverar modellbindning.[BindProperty] public Movie Movie { get; set; }Om det finns fel i modelltillståndet, till exempel om
ReleaseDateinte kan konverteras till ett datum, visas formuläret igen med de skickade värdena.Om det inte finns några modellfel sparas filmen.
HTTP GET-metoderna i sidorna Index, Skapa och Ta bort Razor följer ett liknande mönster. HTTP POST-metoden OnPostAsync i skapa-sidan Razor följer ett liknande mönster som OnPostAsync metoden i Redigera Razor sida.
Nästa steg
Den scaffolded filmappen har en bra start, men presentationen är inte idealisk. ReleaseDate ska vara två ord, Utgivningsdatum.
Uppdatera modellen
Uppdatera Models/Movie.cs med följande markerade kod:
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; } = string.Empty;
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; } = string.Empty;
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
I föregående kod:
- Med
[Column(TypeName = "decimal(18, 2)")]dataanteckningen kan Entity Framework Core mappaPricetill valuta i databasen på rätt sätt. Mer information finns i Datatyper. - Attributet [Display] anger visningsnamnet för ett fält. I den föregående koden,
Release Datei stället förReleaseDate. - Attributet [DataType] anger typen av data (
Date). Tidsinformationen som lagras i fältet visas inte.
DataAnnotationer beskrivs i nästa handledning.
Bläddra till Sidor/Filmer och hovra över en Redigera-länk för att se mål-URL:en.
Länkarna Redigera, Information och Ta bort genereras av fästpunktstagghjälpenPages/Movies/Index.cshtml i filen.
@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>
Tagghjälpare gör det möjligt för kod på serversidan att delta i skapandet och återgivningen av HTML-element i Razor filer.
I föregående kod genererar hjälpverktyget för fästpunkt dynamiskt HTML-attributvärdet href från Razor sidan (vägen är relativ), asp-page, och vägidentifieraren (asp-route-id). Mer information finns i URL-generering för sidor.
Använd Visa källa från en webbläsare för att undersöka den genererade markeringen. En del av den genererade HTML-koden visas nedan:
<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>
De dynamiskt genererade länkarna skickar film-ID:t med en frågesträng. Till exempel ?id=1 i https://localhost:5001/Movies/Details?id=1.
Lägg till routningsmall
Uppdatera redigera, information och ta bort Razor sidor för att använda routningsmallen {id:int} . Ändra siddirektivet för var och en av dessa sidor från @page till @page "{id:int}". Kör appen och visa sedan källan.
Den genererade HTML-koden lägger till ID:t i sökvägsdelen av URL:en:
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
En begäran till sidan med {id:int} routemallen som inte innehåller heltal returnerar ett HTTP 404-fel (sidan kunde inte hittas). Returnerar https://localhost:5001/Movies/Details till exempel ett 404-fel. Om du vill göra ID:t valfritt lägger du till i routningsbegränsningen ? :
@page "{id:int?}"
Testa beteendet av @page "{id:int?}":
- Ange siddirektivet i
Pages/Movies/Details.cshtmltill@page "{id:int?}". - Ange en brytpunkt i
public async Task<IActionResult> OnGetAsync(int? id)iPages/Movies/Details.cshtml.cs. - Gå till
https://localhost:5001/Movies/Details/.
Med direktivet @page "{id:int}" uppnås aldrig brytpunkten. Routningsmotorn returnerar HTTP 404. Metoden OnGetAsync returnerar NotFound med @page "{id:int?}" (HTTP 404):
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);
if (Movie == null)
{
return NotFound();
}
return Page();
}
Granska hantering av samtidighetsfel
OnPostAsync Granska metoden i Pages/Movies/Edit.cshtml.cs filen:
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);
}
Den tidigare koden identifierar samtidighetsfel när en klient tar bort filmen och den andra klienten publicerar ändringar i filmen.
Så här testar du catch blocket:
- Ange en brytpunkt på
catch (DbUpdateConcurrencyException). - Välj Redigera för en film, gör ändringar, men ange inte Spara.
- I ett annat webbläsarfönster väljer du länken Ta bort för samma film och tar sedan bort filmen.
- I föregående webbläsarfönster publicerar du ändringar i filmen.
Produktionskoden kanske vill identifiera samtidighetskonflikter. Mer information finns i Hantera samtidighetskonflikter .
Granskning av publicering och koppling
Pages/Movies/Edit.cshtml.cs Granska filen:
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public EditModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
[BindProperty]
public Movie Movie { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null || _context.Movie == null)
{
return NotFound();
}
var movie = await _context.Movie.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
Movie = movie;
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see https://aka.ms/RazorPagesCRUD.
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);
}
När en HTTP GET-begäran görs till sidan Filmer/Redigera, https://localhost:5001/Movies/Edit/3till exempel :
- Metoden
OnGetAsynchämtar filmen från databasen och returnerarPagemetoden. - Metoden
PagerenderarPages/Movies/Edit.cshtmlRazor sidan. FilenPages/Movies/Edit.cshtmlinnehåller modelldirektivet@model RazorPagesMovie.Pages.Movies.EditModel, vilket gör filmmodellen tillgänglig på sidan. - Formuläret Redigera visas med värdena från filmen.
När sidan Filmer/Redigera publiceras:
Formulärvärdena på sidan är bundna till egenskapen
Movie. Attributet[BindProperty]aktiverar modellbindning.[BindProperty] public Movie Movie { get; set; }Om det finns fel i modelltillståndet, till exempel om
ReleaseDateinte kan konverteras till ett datum, visas formuläret igen med de skickade värdena.Om det inte finns några modellfel sparas filmen.
HTTP GET-metoderna i sidorna Index, Skapa och Ta bort Razor följer ett liknande mönster. HTTP POST-metoden OnPostAsync i skapa-sidan Razor följer ett liknande mönster som OnPostAsync metoden i Redigera Razor sida.
Nästa steg
Den scaffolded filmappen har en bra start, men presentationen är inte idealisk. ReleaseDate ska vara två ord, Utgivningsdatum.
Uppdatera modellen
Uppdatera Models/Movie.cs med följande markerade kod:
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; } = string.Empty;
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; } = string.Empty;
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
I föregående kod:
- Med
[Column(TypeName = "decimal(18, 2)")]dataanteckningen kan Entity Framework Core mappaPricetill valuta i databasen på rätt sätt. Mer information finns i Datatyper. - Attributet [Display] anger visningsnamnet för ett fält. I den föregående koden,
Release Datei stället förReleaseDate. - Attributet [DataType] anger typen av data (
Date). Tidsinformationen som lagras i fältet visas inte.
DataAnnotationer beskrivs i nästa handledning.
Bläddra till Sidor/Filmer och hovra över en Redigera-länk för att se mål-URL:en.
Länkarna Redigera, Information och Ta bort genereras av fästpunktstagghjälpenPages/Movies/Index.cshtml i filen.
@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>
Tagghjälpare gör det möjligt för kod på serversidan att delta i skapandet och återgivningen av HTML-element i Razor filer.
I föregående kod genererar hjälpverktyget för fästpunkt dynamiskt HTML-attributvärdet href från Razor sidan (vägen är relativ), asp-page, och vägidentifieraren (asp-route-id). Mer information finns i URL-generering för sidor.
Använd Visa källa från en webbläsare för att undersöka den genererade markeringen. En del av den genererade HTML-koden visas nedan:
<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>
De dynamiskt genererade länkarna skickar film-ID:t med en frågesträng. Till exempel ?id=1 i https://localhost:5001/Movies/Details?id=1.
Lägg till routningsmall
Uppdatera redigera, information och ta bort Razor sidor för att använda routningsmallen {id:int} . Ändra siddirektivet för var och en av dessa sidor från @page till @page "{id:int}". Kör appen och visa sedan källan.
Den genererade HTML-koden lägger till ID:t i sökvägsdelen av URL:en:
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
En begäran till sidan med {id:int} routemallen som inte innehåller heltal returnerar ett HTTP 404-fel (sidan kunde inte hittas). Returnerar https://localhost:5001/Movies/Details till exempel ett 404-fel. Om du vill göra ID:t valfritt lägger du till i routningsbegränsningen ? :
@page "{id:int?}"
Testa beteendet av @page "{id:int?}":
- Ange siddirektivet i
Pages/Movies/Details.cshtmltill@page "{id:int?}". - Ange en brytpunkt i
public async Task<IActionResult> OnGetAsync(int? id)iPages/Movies/Details.cshtml.cs. - Gå till
https://localhost:5001/Movies/Details/.
Med direktivet @page "{id:int}" uppnås aldrig brytpunkten. Routningsmotorn returnerar HTTP 404. Metoden OnGetAsync returnerar NotFound med @page "{id:int?}" (HTTP 404):
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);
if (Movie == null)
{
return NotFound();
}
return Page();
}
Granska hantering av samtidighetsfel
OnPostAsync Granska metoden i Pages/Movies/Edit.cshtml.cs filen:
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);
}
Den tidigare koden identifierar samtidighetsfel när en klient tar bort filmen och den andra klienten publicerar ändringar i filmen.
Så här testar du catch blocket:
- Ange en brytpunkt på
catch (DbUpdateConcurrencyException). - Välj Redigera för en film, gör ändringar, men ange inte Spara.
- I ett annat webbläsarfönster väljer du länken Ta bort för samma film och tar sedan bort filmen.
- I föregående webbläsarfönster publicerar du ändringar i filmen.
Produktionskoden kanske vill identifiera samtidighetskonflikter. Mer information finns i Hantera samtidighetskonflikter .
Granskning av publicering och koppling
Pages/Movies/Edit.cshtml.cs Granska filen:
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public EditModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
[BindProperty]
public Movie Movie { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null || _context.Movie == null)
{
return NotFound();
}
var movie = await _context.Movie.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
Movie = movie;
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see https://aka.ms/RazorPagesCRUD.
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);
}
När en HTTP GET-begäran görs till sidan Filmer/Redigera, https://localhost:5001/Movies/Edit/3till exempel :
- Metoden
OnGetAsynchämtar filmen från databasen och returnerarPagemetoden. - Metoden
PagerenderarPages/Movies/Edit.cshtmlRazor sidan. FilenPages/Movies/Edit.cshtmlinnehåller modelldirektivet@model RazorPagesMovie.Pages.Movies.EditModel, vilket gör filmmodellen tillgänglig på sidan. - Formuläret Redigera visas med värdena från filmen.
När sidan Filmer/Redigera publiceras:
Formulärvärdena på sidan är bundna till egenskapen
Movie. Attributet[BindProperty]aktiverar modellbindning.[BindProperty] public Movie Movie { get; set; }Om det finns fel i modelltillståndet, till exempel om
ReleaseDateinte kan konverteras till ett datum, visas formuläret igen med de skickade värdena.Om det inte finns några modellfel sparas filmen.
HTTP GET-metoderna i sidorna Index, Skapa och Ta bort Razor följer ett liknande mönster. HTTP POST-metoden OnPostAsync i skapa-sidan Razor följer ett liknande mönster som OnPostAsync metoden i Redigera Razor sida.
Nästa steg
Den scaffolded filmappen har en bra start, men presentationen är inte idealisk. ReleaseDate ska vara två ord, Utgivningsdatum.
Uppdatera den genererade koden
Uppdatera Models/Movie.cs med följande markerade kod:
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; } = string.Empty;
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; } = string.Empty;
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
}
I föregående kod:
- Med
[Column(TypeName = "decimal(18, 2)")]dataanteckningen kan Entity Framework Core mappaPricetill valuta i databasen på rätt sätt. Mer information finns i Datatyper. - Attributet [Display] anger visningsnamnet för ett fält. I föregående kod, "Utgivningsdatum" i stället för "ReleaseDate".
- Attributet [DataType] anger typen av data (
Date). Tidsinformationen som lagras i fältet visas inte.
DataAnnotationer beskrivs i nästa handledning.
Bläddra till Sidor/Filmer och hovra över en Redigera-länk för att se mål-URL:en.
Länkarna Redigera, Information och Ta bort genereras av fästpunktstagghjälpenPages/Movies/Index.cshtml i filen.
@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>
Tagghjälpare gör det möjligt för kod på serversidan att delta i skapandet och återgivningen av HTML-element i Razor filer.
I föregående kod genererar hjälpverktyget för fästpunkt dynamiskt HTML-attributvärdet href från Razor sidan (vägen är relativ), asp-page, och vägidentifieraren (asp-route-id). Mer information finns i URL-generering för sidor.
Använd Visa källa från en webbläsare för att undersöka den genererade markeringen. En del av den genererade HTML-koden visas nedan:
<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>
De dynamiskt genererade länkarna skickar film-ID:t med en frågesträng. Till exempel ?id=1 i https://localhost:5001/Movies/Details?id=1.
Lägg till routningsmall
Uppdatera redigera, information och ta bort Razor sidor för att använda routningsmallen {id:int} . Ändra siddirektivet för var och en av dessa sidor från @page till @page "{id:int}". Kör appen och visa sedan källan.
Den genererade HTML-koden lägger till ID:t i sökvägsdelen av URL:en:
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
En begäran till sidan med {id:int} routningsmallen som inte innehåller heltalet returnerar ett HTTP 404-fel (hittades inte). Till exempel https://localhost:5001/Movies/Details returnerar ett 404-fel. Om du vill göra ID:t valfritt lägger du till i routningsbegränsningen ? :
@page "{id:int?}"
Testa beteendet av @page "{id:int?}":
- Ange siddirektivet i
Pages/Movies/Details.cshtmltill@page "{id:int?}". - Ange en brytpunkt i
public async Task<IActionResult> OnGetAsync(int? id)iPages/Movies/Details.cshtml.cs. - Gå till
https://localhost:5001/Movies/Details/.
Med direktivet @page "{id:int}" uppnås aldrig brytpunkten. Routningsmotorn returnerar HTTP 404. Med @page "{id:int?}"-metoden returnerar OnGetAsyncNotFound (HTTP 404):
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);
if (Movie == null)
{
return NotFound();
}
return Page();
}
Granska hantering av samtidighetsfel
OnPostAsync Granska metoden i Pages/Movies/Edit.cshtml.cs filen:
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)).GetValueOrDefault();
}
Den tidigare koden identifierar samtidighetsfel när en klient tar bort filmen och den andra klienten publicerar ändringar i filmen. Den tidigare koden identifierar inte konflikter som uppstår på grund av att två eller flera klienter redigerar samma film samtidigt. I det här fallet tillämpas redigeringar av flera klienter i den ordning som SaveChanges anropas och redigeringar som tillämpas senare kan skriva över tidigare redigeringar med inaktuella värden.
Så här testar du catch blocket:
- Ange en brytpunkt på
catch (DbUpdateConcurrencyException). - Välj Redigera för en film, gör ändringar, men ange inte Spara.
- I ett annat webbläsarfönster väljer du länken Ta bort för samma film och tar sedan bort filmen.
- I föregående webbläsarfönster publicerar du ändringar i filmen.
Produktionskoden kanske vill identifiera ytterligare samtidighetskonflikter, till exempel flera klienter som redigerar en entitet samtidigt. Mer information finns i Hantera samtidighetskonflikter .
Granskning av publicering och sammanbindning
Pages/Movies/Edit.cshtml.cs Granska filen:
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public EditModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
{
_context = context;
}
[BindProperty]
public Movie Movie { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null || _context.Movie == null)
{
return NotFound();
}
var movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);
if (movie == null)
{
return NotFound();
}
Movie = movie;
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see https://aka.ms/RazorPagesCRUD.
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)).GetValueOrDefault();
}
När en HTTP GET-begäran görs till sidan Filmer/Redigera, https://localhost:5001/Movies/Edit/3till exempel :
- Metoden
OnGetAsynchämtar filmen från databasen och returnerarPagemetoden. - Metoden
PagerenderarPages/Movies/Edit.cshtmlRazor sidan. FilenPages/Movies/Edit.cshtmlinnehåller modelldirektivet@model RazorPagesMovie.Pages.Movies.EditModel, vilket gör filmmodellen tillgänglig på sidan. - Formuläret Redigera visas med värdena från filmen.
När sidan Filmer/Redigera publiceras:
Formulärvärdena på sidan är bundna till egenskapen
Movie. Attributet[BindProperty]aktiverar modellbindning.[BindProperty] public Movie Movie { get; set; }Om det finns fel i modelltillståndet, till exempel om
ReleaseDateinte kan konverteras till ett datum, visas formuläret igen med de skickade värdena.Om det inte finns några modellfel sparas filmen.
HTTP GET-metoderna i sidorna Index, Skapa och Ta bort Razor följer ett liknande mönster. HTTP POST-metoden OnPostAsync i skapa-sidan Razor följer ett liknande mönster som OnPostAsync metoden i Redigera Razor sida.
Nästa steg
Den ramverkbaserade filmapplikationen har en bra start, men presentationen är inte optimal. ReleaseDate ska vara två ord, Utgivningsdatum.
Uppdatera den genererade koden
Models/Movie.cs Öppna filen och lägg till de markerade raderna som visas i följande kod:
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; }
}
}
I föregående kod:
- Med
[Column(TypeName = "decimal(18, 2)")]dataanteckningen kan Entity Framework Core mappaPricetill valuta i databasen på rätt sätt. Mer information finns i Datatyper. - Attributet [Display] anger visningsnamnet för ett fält. I föregående kod, "Utgivningsdatum" i stället för "ReleaseDate".
- Attributet [DataType] anger typen av data (
Date). Tidsinformationen som lagras i fältet visas inte.
Dataanalyser behandlas i nästa handledning.
Bläddra till Sidor/Filmer och hovra över en Redigera-länk för att se mål-URL:en.
Länkarna Redigera, Information och Ta bort genereras av fästpunktstagghjälpenPages/Movies/Index.cshtml i filen.
@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>
Tagghjälpare gör det möjligt för kod på serversidan att delta i skapandet och återgivningen av HTML-element i Razor filer.
I föregående kod genererar hjälpverktyget för fästpunkt dynamiskt HTML-attributvärdet href från Razor sidan (vägen är relativ), asp-page, och vägidentifieraren (asp-route-id). Mer information finns i URL-generering för sidor.
Använd Visa källa från en webbläsare för att undersöka den genererade markeringen. En del av den genererade HTML-koden visas nedan:
<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>
De dynamiskt genererade länkarna skickar film-ID:t med en frågesträng. Till exempel ?id=1 i https://localhost:5001/Movies/Details?id=1.
Lägg till routningsmall
Uppdatera redigera, information och ta bort Razor sidor för att använda routningsmallen {id:int} . Ändra siddirektivet för var och en av dessa sidor från @page till @page "{id:int}". Kör appen och visa sedan källan.
Den genererade HTML-koden lägger till ID:t i sökvägsdelen av URL:en:
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
En begäran till sidan med {id:int} routningsmallen som inte innehåller heltalet returnerar ett HTTP 404-fel (hittades inte). Till exempel https://localhost:5001/Movies/Details returnerar ett 404-fel. Om du vill göra ID:t valfritt lägger du till i routningsbegränsningen ? :
@page "{id:int?}"
Testa beteendet för @page "{id:int?}":
- Ange siddirektivet i
Pages/Movies/Details.cshtmltill@page "{id:int?}". - Ange en brytpunkt i
public async Task<IActionResult> OnGetAsync(int? id)iPages/Movies/Details.cshtml.cs. - Gå till
https://localhost:5001/Movies/Details/.
Med direktivet @page "{id:int}" uppnås aldrig brytpunkten. Routningsmotorn returnerar HTTP 404. Metoden OnGetAsync returnerar NotFound med @page "{id:int?}" (HTTP 404):
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);
if (Movie == null)
{
return NotFound();
}
return Page();
}
Granska hantering av samtidighetsfel
OnPostAsync Granska metoden i Pages/Movies/Edit.cshtml.cs filen:
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);
}
Den tidigare koden identifierar samtidighetsfel när en klient tar bort filmen och den andra klienten publicerar ändringar i filmen.
Så här testar du catch blocket:
- Ange en brytpunkt på
catch (DbUpdateConcurrencyException). - Välj Redigera för en film, gör ändringar, men ange inte Spara.
- I ett annat webbläsarfönster väljer du länken Ta bort för samma film och tar sedan bort filmen.
- I föregående webbläsarfönster publicerar du ändringar i filmen.
Produktionskoden kanske vill identifiera samtidighetskonflikter. Mer information finns i Hantera samtidighetskonflikter .
Granskning av publicering och koppling
Pages/Movies/Edit.cshtml.cs Granska filen:
public class EditModel : PageModel
{
private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;
public EditModel(RazorPagesMovie.Data.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.FirstOrDefaultAsync(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 (!MovieExists(Movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
private bool MovieExists(int id)
{
return _context.Movie.Any(e => e.ID == id);
}
När en HTTP GET-begäran görs till sidan Filmer/Redigera, https://localhost:5001/Movies/Edit/3till exempel :
- Metoden
OnGetAsynchämtar filmen från databasen och returnerarPagemetoden. - Metoden
PagerenderarPages/Movies/Edit.cshtmlRazor sidan. FilenPages/Movies/Edit.cshtmlinnehåller modelldirektivet@model RazorPagesMovie.Pages.Movies.EditModel, vilket gör filmmodellen tillgänglig på sidan. - Formuläret Redigera visas med värdena från filmen.
När sidan Filmer/Redigera publiceras:
Formulärvärdena på sidan är bundna till egenskapen
Movie. Attributet[BindProperty]aktiverar modellbindning.[BindProperty] public Movie Movie { get; set; }Om det finns fel i modelltillståndet, till exempel,
ReleaseDateinte kan konverteras till ett datum, visas formuläret igen med de skickade värdena.Om det inte finns några modellfel sparas filmen.
HTTP GET-metoderna i sidorna Index, Skapa och Ta bort Razor följer ett liknande mönster. HTTP POST-metoden OnPostAsync i skapa-sidan Razor följer ett liknande mönster som OnPostAsync metoden i Redigera Razor sida.
Nästa steg
ASP.NET Core