Sdílet prostřednictvím


Část 5– aktualizace vygenerovaných stránek v aplikaci ASP.NET Core

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Vygenerovaná filmová aplikace má dobrý začátek, ale prezentace není ideální. Datum vydání by mělo být dvě slova– Datum vydání.

Otevřená filmová aplikace v Chromu

Aktualizace modelu

Aktualizujte Models/Movie.cs následujícím zvýrazněným kódem:

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; }
}

V předchozím kódu:

  • Datová [Column(TypeName = "decimal(18, 2)")] poznámka umožňuje entity Framework Core správně mapovat Price na měnu v databázi. Další informace naleznete v tématu Datové typy.
  • Atribut [Display] určuje zobrazovaný název pole. V předchozím kódu místo Release DateReleaseDate.
  • Atribut [DataType] určuje typ dat (Date). Informace o čase uložené v poli se nezobrazují.

DataAnnotations najdete v dalším kurzu.

Přejděte na Stránky nebo filmy a najeďte myší na odkaz Upravit a zobrazte cílovou adresu URL.

Okno prohlížeče s myší na odkaz Upravit a zobrazená adresa URL https://localhost:1234/Movies/Edit/5 odkazu

Odkazy Upravit, Podrobnosti a Odstranit jsou generovány pomocným pomocníkem značky ukotvení v Pages/Movies/Index.cshtml souboru.

@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>

Pomocné rutiny značek umožňují, aby se kód na straně serveru v souborech Razor podílel na vytváření a vykreslování elementů HTML.

V předchozím kódu pomocník značky ukotvení dynamicky generuje hodnotu atributu HTML href ze Razor stránky (trasa je relativní), identifikátor asp-pagetrasyasp-route-id (). Další informace najdete v tématu Generování adres URL pro stránky.

K prozkoumání vygenerované značky použijte zdroj zobrazení z prohlížeče. Část vygenerovaného kódu HTML je znázorněná níže:

<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>

Dynamicky generované odkazy předávají ID videa s řetězcem dotazu. Například in ?id=1https://localhost:5001/Movies/Details?id=1.

Přidání šablony trasy

Aktualizujte stránky Upravit, Podrobnosti a Odstranit Razor tak, aby používaly {id:int} šablonu trasy. Změňte direktivu stránky pro každou z těchto stránek na @page@page "{id:int}". Spusťte aplikaci a pak zobrazte zdroj.

Vygenerovaný kód HTML přidá ID do části cesty adresy URL:

<td>
  <a href="/Movies/Edit/1">Edit</a> |
  <a href="/Movies/Details/1">Details</a> |
  <a href="/Movies/Delete/1">Delete</a>
</td>

Požadavek na stránku se šablonou {id:int} trasy, která neobsahuje celé číslo, vrátí chybu HTTP 404 (nenalezena). Například https://localhost:5001/Movies/Details vrátí chybu 404. Pokud chcete nastavit ID jako volitelné, připojte k omezení trasy symbol ?:

@page "{id:int?}"

Otestujte chování @page "{id:int?}":

  1. Nastavte direktivu Pages/Movies/Details.cshtml stránky na @page "{id:int?}"hodnotu .
  2. Nastavte zarážku v public async Task<IActionResult> OnGetAsync(int? id), v Pages/Movies/Details.cshtml.cs.
  3. Přejděte na https://localhost:5001/Movies/Details/.

S direktivou @page "{id:int}" se zarážka nikdy nedostane. Směrovací modul vrátí http 404. Using @page "{id:int?}", OnGetAsync metoda vrátí NotFound (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();
}

Kontrola zpracování výjimek souběžnosti

Zkontrolujte metodu OnPostAsyncPages/Movies/Edit.cshtml.cs v souboru:

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);
}

Předchozí kód zjistí výjimky souběžnosti, když jeden klient odstraní video a ostatní klienty publikují změny videa.

Postup otestování catch bloku:

  1. Nastavte zarážku na catch (DbUpdateConcurrencyException).
  2. Vyberte Upravit pro film, proveďte změny, ale nezadávejte uložit.
  3. V jiném okně prohlížeče vyberte odkaz Odstranit pro stejný film a pak video odstraňte.
  4. V předchozím okně prohlížeče publikujte změny videa.

Produkční kód může chtít zjistit konflikty souběžnosti. Další informace najdete v tématu Zpracování konfliktů souběžnosti.

Publikování a kontrola vazby

Pages/Movies/Edit.cshtml.cs Prozkoumejte soubor:

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);
    }

Při provedení požadavku HTTP GET na stránku Filmy/Úpravy, například https://localhost:5001/Movies/Edit/3:

  • Metoda OnGetAsync načte film z databáze a vrátí metodu Page .
  • Metoda Page vykreslí Pages/Movies/Edit.cshtmlRazor Stránku. Soubor Pages/Movies/Edit.cshtml obsahuje direktivu @model RazorPagesMovie.Pages.Movies.EditModelmodelu, která zpřístupňuje filmový model na stránce.
  • Formulář Upravit se zobrazí s hodnotami z filmu.

Když se publikuje stránka Movies/Edit:

  • Hodnoty formuláře na stránce jsou vázány na Movie vlastnost. Atribut [BindProperty] umožňuje vazbu modelu.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Pokud jsou ve stavu modelu chyby, ReleaseDate například nelze převést na datum, formulář se znovu zobrazí s odeslanými hodnotami.

  • Pokud neexistují žádné chyby modelu, film se uloží.

Metody HTTP GET na stránkách Index, Create a Delete Razor se řídí podobným vzorem. Metoda HTTP POST OnPostAsync na create Razor page se řídí podobným vzorem OnPostAsync jako metoda v Edit Razor Page.

Další kroky

Vygenerovaná filmová aplikace má dobrý začátek, ale prezentace není ideální. Datum vydání by mělo být dvě slova– Datum vydání.

Otevřená filmová aplikace v Chromu

Aktualizace modelu

Aktualizujte Models/Movie.cs následujícím zvýrazněným kódem:

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; }
}

V předchozím kódu:

  • Datová [Column(TypeName = "decimal(18, 2)")] poznámka umožňuje entity Framework Core správně mapovat Price na měnu v databázi. Další informace naleznete v tématu Datové typy.
  • Atribut [Display] určuje zobrazovaný název pole. V předchozím kódu místo Release DateReleaseDate.
  • Atribut [DataType] určuje typ dat (Date). Informace o čase uložené v poli se nezobrazují.

DataAnnotations najdete v dalším kurzu.

Přejděte na Stránky nebo filmy a najeďte myší na odkaz Upravit a zobrazte cílovou adresu URL.

Okno prohlížeče s myší na odkaz Upravit a zobrazená adresa URL https://localhost:1234/Movies/Edit/5 odkazu

Odkazy Upravit, Podrobnosti a Odstranit jsou generovány pomocným pomocníkem značky ukotvení v Pages/Movies/Index.cshtml souboru.

@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>

Pomocné rutiny značek umožňují, aby se kód na straně serveru v souborech Razor podílel na vytváření a vykreslování elementů HTML.

V předchozím kódu pomocník značky ukotvení dynamicky generuje hodnotu atributu HTML href ze Razor stránky (trasa je relativní), identifikátor asp-pagetrasyasp-route-id (). Další informace najdete v tématu Generování adres URL pro stránky.

K prozkoumání vygenerované značky použijte zdroj zobrazení z prohlížeče. Část vygenerovaného kódu HTML je znázorněná níže:

<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>

Dynamicky generované odkazy předávají ID videa s řetězcem dotazu. Například in ?id=1https://localhost:5001/Movies/Details?id=1.

Přidání šablony trasy

Aktualizujte stránky Upravit, Podrobnosti a Odstranit Razor tak, aby používaly {id:int} šablonu trasy. Změňte direktivu stránky pro každou z těchto stránek na @page@page "{id:int}". Spusťte aplikaci a pak zobrazte zdroj.

Vygenerovaný kód HTML přidá ID do části cesty adresy URL:

<td>
  <a href="/Movies/Edit/1">Edit</a> |
  <a href="/Movies/Details/1">Details</a> |
  <a href="/Movies/Delete/1">Delete</a>
</td>

Požadavek na stránku se šablonou {id:int} trasy, která neobsahuje celé číslo, vrátí chybu HTTP 404 (nenalezena). Například https://localhost:5001/Movies/Details vrátí chybu 404. Pokud chcete nastavit ID jako volitelné, připojte k omezení trasy symbol ?:

@page "{id:int?}"

Otestujte chování @page "{id:int?}":

  1. Nastavte direktivu Pages/Movies/Details.cshtml stránky na @page "{id:int?}"hodnotu .
  2. Nastavte zarážku v public async Task<IActionResult> OnGetAsync(int? id), v Pages/Movies/Details.cshtml.cs.
  3. Přejděte na https://localhost:5001/Movies/Details/.

S direktivou @page "{id:int}" se zarážka nikdy nedostane. Směrovací modul vrátí http 404. Using @page "{id:int?}", OnGetAsync metoda vrátí NotFound (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();
}

Kontrola zpracování výjimek souběžnosti

Zkontrolujte metodu OnPostAsyncPages/Movies/Edit.cshtml.cs v souboru:

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);
}

Předchozí kód zjistí výjimky souběžnosti, když jeden klient odstraní video a ostatní klienty publikují změny videa.

Postup otestování catch bloku:

  1. Nastavte zarážku na catch (DbUpdateConcurrencyException).
  2. Vyberte Upravit pro film, proveďte změny, ale nezadávejte uložit.
  3. V jiném okně prohlížeče vyberte odkaz Odstranit pro stejný film a pak video odstraňte.
  4. V předchozím okně prohlížeče publikujte změny videa.

Produkční kód může chtít zjistit konflikty souběžnosti. Další informace najdete v tématu Zpracování konfliktů souběžnosti.

Publikování a kontrola vazby

Pages/Movies/Edit.cshtml.cs Prozkoumejte soubor:

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);
    }

Při provedení požadavku HTTP GET na stránku Filmy/Úpravy, například https://localhost:5001/Movies/Edit/3:

  • Metoda OnGetAsync načte film z databáze a vrátí metodu Page .
  • Metoda Page vykreslí Pages/Movies/Edit.cshtmlRazor Stránku. Soubor Pages/Movies/Edit.cshtml obsahuje direktivu @model RazorPagesMovie.Pages.Movies.EditModelmodelu, která zpřístupňuje filmový model na stránce.
  • Formulář Upravit se zobrazí s hodnotami z filmu.

Když se publikuje stránka Movies/Edit:

  • Hodnoty formuláře na stránce jsou vázány na Movie vlastnost. Atribut [BindProperty] umožňuje vazbu modelu.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Pokud jsou ve stavu modelu chyby, ReleaseDate například nelze převést na datum, formulář se znovu zobrazí s odeslanými hodnotami.

  • Pokud neexistují žádné chyby modelu, film se uloží.

Metody HTTP GET na stránkách Index, Create a Delete Razor se řídí podobným vzorem. Metoda HTTP POST OnPostAsync na create Razor page se řídí podobným vzorem OnPostAsync jako metoda v Edit Razor Page.

Další kroky

Vygenerovaná filmová aplikace má dobrý začátek, ale prezentace není ideální. Datum vydání by mělo být dvě slova– Datum vydání.

Otevřená filmová aplikace v Chromu

Aktualizace modelu

Aktualizujte Models/Movie.cs následujícím zvýrazněným kódem:

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; }
}

V předchozím kódu:

  • Datová [Column(TypeName = "decimal(18, 2)")] poznámka umožňuje entity Framework Core správně mapovat Price na měnu v databázi. Další informace naleznete v tématu Datové typy.
  • Atribut [Display] určuje zobrazovaný název pole. V předchozím kódu místo Release DateReleaseDate.
  • Atribut [DataType] určuje typ dat (Date). Informace o čase uložené v poli se nezobrazují.

DataAnnotations najdete v dalším kurzu.

Přejděte na Stránky nebo filmy a najeďte myší na odkaz Upravit a zobrazte cílovou adresu URL.

Okno prohlížeče s myší na odkaz Upravit a zobrazená adresa URL https://localhost:1234/Movies/Edit/5 odkazu

Odkazy Upravit, Podrobnosti a Odstranit jsou generovány pomocným pomocníkem značky ukotvení v Pages/Movies/Index.cshtml souboru.

@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>

Pomocné rutiny značek umožňují, aby se kód na straně serveru v souborech Razor podílel na vytváření a vykreslování elementů HTML.

V předchozím kódu pomocník značky ukotvení dynamicky generuje hodnotu atributu HTML href ze Razor stránky (trasa je relativní), identifikátor asp-pagetrasyasp-route-id (). Další informace najdete v tématu Generování adres URL pro stránky.

K prozkoumání vygenerované značky použijte zdroj zobrazení z prohlížeče. Část vygenerovaného kódu HTML je znázorněná níže:

<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>

Dynamicky generované odkazy předávají ID videa s řetězcem dotazu. Například in ?id=1https://localhost:5001/Movies/Details?id=1.

Přidání šablony trasy

Aktualizujte stránky Upravit, Podrobnosti a Odstranit Razor tak, aby používaly {id:int} šablonu trasy. Změňte direktivu stránky pro každou z těchto stránek na @page@page "{id:int}". Spusťte aplikaci a pak zobrazte zdroj.

Vygenerovaný kód HTML přidá ID do části cesty adresy URL:

<td>
  <a href="/Movies/Edit/1">Edit</a> |
  <a href="/Movies/Details/1">Details</a> |
  <a href="/Movies/Delete/1">Delete</a>
</td>

Požadavek na stránku se šablonou {id:int} trasy, která neobsahuje celé číslo, vrátí chybu HTTP 404 (nenalezena). Například https://localhost:5001/Movies/Details vrátí chybu 404. Pokud chcete nastavit ID jako volitelné, připojte k omezení trasy symbol ?:

@page "{id:int?}"

Otestujte chování @page "{id:int?}":

  1. Nastavte direktivu Pages/Movies/Details.cshtml stránky na @page "{id:int?}"hodnotu .
  2. Nastavte zarážku v public async Task<IActionResult> OnGetAsync(int? id), v Pages/Movies/Details.cshtml.cs.
  3. Přejděte na https://localhost:5001/Movies/Details/.

S direktivou @page "{id:int}" se zarážka nikdy nedostane. Směrovací modul vrátí http 404. Using @page "{id:int?}", OnGetAsync metoda vrátí NotFound (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();
}

Kontrola zpracování výjimek souběžnosti

Zkontrolujte metodu OnPostAsyncPages/Movies/Edit.cshtml.cs v souboru:

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);
}

Předchozí kód zjistí výjimky souběžnosti, když jeden klient odstraní video a ostatní klienty publikují změny videa.

Postup otestování catch bloku:

  1. Nastavte zarážku na catch (DbUpdateConcurrencyException).
  2. Vyberte Upravit pro film, proveďte změny, ale nezadávejte uložit.
  3. V jiném okně prohlížeče vyberte odkaz Odstranit pro stejný film a pak video odstraňte.
  4. V předchozím okně prohlížeče publikujte změny videa.

Produkční kód může chtít zjistit konflikty souběžnosti. Další informace najdete v tématu Zpracování konfliktů souběžnosti.

Publikování a kontrola vazby

Pages/Movies/Edit.cshtml.cs Prozkoumejte soubor:

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);
    }

Při provedení požadavku HTTP GET na stránku Filmy/Úpravy, například https://localhost:5001/Movies/Edit/3:

  • Metoda OnGetAsync načte film z databáze a vrátí metodu Page .
  • Metoda Page vykreslí Pages/Movies/Edit.cshtmlRazor Stránku. Soubor Pages/Movies/Edit.cshtml obsahuje direktivu @model RazorPagesMovie.Pages.Movies.EditModelmodelu, která zpřístupňuje filmový model na stránce.
  • Formulář Upravit se zobrazí s hodnotami z filmu.

Když se publikuje stránka Movies/Edit:

  • Hodnoty formuláře na stránce jsou vázány na Movie vlastnost. Atribut [BindProperty] umožňuje vazbu modelu.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Pokud jsou ve stavu modelu chyby, ReleaseDate například nelze převést na datum, formulář se znovu zobrazí s odeslanými hodnotami.

  • Pokud neexistují žádné chyby modelu, film se uloží.

Metody HTTP GET na stránkách Index, Create a Delete Razor se řídí podobným vzorem. Metoda HTTP POST OnPostAsync na create Razor page se řídí podobným vzorem OnPostAsync jako metoda v Edit Razor Page.

Další kroky

Vygenerovaná filmová aplikace má dobrý začátek, ale prezentace není ideální. Datum vydání by mělo být dvě slova– Datum vydání.

Otevřená filmová aplikace v Chromu

Aktualizace vygenerovaného kódu

Aktualizujte Models/Movie.cs následujícím zvýrazněným kódem:

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; }
    }
}

V předchozím kódu:

  • Datová [Column(TypeName = "decimal(18, 2)")] poznámka umožňuje entity Framework Core správně mapovat Price na měnu v databázi. Další informace naleznete v tématu Datové typy.
  • Atribut [Display] určuje zobrazovaný název pole. V předchozím kódu místo releaseDate zadejte datum vydání.
  • Atribut [DataType] určuje typ dat (Date). Informace o čase uložené v poli se nezobrazují.

DataAnnotations najdete v dalším kurzu.

Přejděte na Stránky nebo filmy a najeďte myší na odkaz Upravit a zobrazte cílovou adresu URL.

Okno prohlížeče s myší na odkaz Upravit a zobrazená adresa URL https://localhost:1234/Movies/Edit/5 odkazu

Odkazy Upravit, Podrobnosti a Odstranit jsou generovány pomocným pomocníkem značky ukotvení v Pages/Movies/Index.cshtml souboru.

@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>

Pomocné rutiny značek umožňují, aby se kód na straně serveru v souborech Razor podílel na vytváření a vykreslování elementů HTML.

V předchozím kódu pomocník značky ukotvení dynamicky generuje hodnotu atributu HTML href ze Razor stránky (trasa je relativní), identifikátor asp-pagetrasyasp-route-id (). Další informace najdete v tématu Generování adres URL pro stránky.

K prozkoumání vygenerované značky použijte zdroj zobrazení z prohlížeče. Část vygenerovaného kódu HTML je znázorněná níže:

<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>

Dynamicky generované odkazy předávají ID videa s řetězcem dotazu. Například in ?id=1https://localhost:5001/Movies/Details?id=1.

Přidání šablony trasy

Aktualizujte stránky Upravit, Podrobnosti a Odstranit Razor tak, aby používaly {id:int} šablonu trasy. Změňte direktivu stránky pro každou z těchto stránek na @page@page "{id:int}". Spusťte aplikaci a pak zobrazte zdroj.

Vygenerovaný kód HTML přidá ID do části cesty adresy URL:

<td>
  <a href="/Movies/Edit/1">Edit</a> |
  <a href="/Movies/Details/1">Details</a> |
  <a href="/Movies/Delete/1">Delete</a>
</td>

Požadavek na stránku se šablonou {id:int} trasy, která neobsahuje celé číslo, vrátí chybu HTTP 404 (nenalezena). Například https://localhost:5001/Movies/Details vrátí chybu 404. Pokud chcete nastavit ID jako volitelné, připojte k omezení trasy symbol ?:

@page "{id:int?}"

Otestujte chování @page "{id:int?}":

  1. Nastavte direktivu Pages/Movies/Details.cshtml stránky na @page "{id:int?}"hodnotu .
  2. Nastavte zarážku v public async Task<IActionResult> OnGetAsync(int? id), v Pages/Movies/Details.cshtml.cs.
  3. Přejděte na https://localhost:5001/Movies/Details/.

S direktivou @page "{id:int}" se zarážka nikdy nedostane. Směrovací modul vrátí http 404. Using @page "{id:int?}", OnGetAsync metoda vrátí NotFound (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();
}

Kontrola zpracování výjimek souběžnosti

Zkontrolujte metodu OnPostAsyncPages/Movies/Edit.cshtml.cs v souboru:

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();
}

Předchozí kód zjistí výjimky souběžnosti, když jeden klient odstraní video a ostatní klienty publikují změny videa. Předchozí kód nezjistí konflikty, ke kterým dochází kvůli dvěma nebo více klientům, kteří současně upravují stejný film. V tomto případě se úpravy více klientů použijí v pořadí, v jakém SaveChanges se volají, a úpravy, které se použijí později, mohou přepsat dřívější úpravy zastaralými hodnotami.

Postup otestování catch bloku:

  1. Nastavte zarážku na catch (DbUpdateConcurrencyException).
  2. Vyberte Upravit pro film, proveďte změny, ale nezadávejte uložit.
  3. V jiném okně prohlížeče vyberte odkaz Odstranit pro stejný film a pak video odstraňte.
  4. V předchozím okně prohlížeče publikujte změny videa.

Produkční kód může chtít zjistit další konflikty souběžnosti, jako je například několik klientů, kteří upravují entitu najednou. Další informace najdete v tématu Zpracování konfliktů souběžnosti.

Publikování a kontrola vazby

Pages/Movies/Edit.cshtml.cs Prozkoumejte soubor:

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();
    }

Při provedení požadavku HTTP GET na stránku Filmy/Úpravy, například https://localhost:5001/Movies/Edit/3:

  • Metoda OnGetAsync načte film z databáze a vrátí metodu Page .
  • Metoda Page vykreslí Pages/Movies/Edit.cshtmlRazor Stránku. Soubor Pages/Movies/Edit.cshtml obsahuje direktivu @model RazorPagesMovie.Pages.Movies.EditModelmodelu, která zpřístupňuje filmový model na stránce.
  • Formulář Upravit se zobrazí s hodnotami z filmu.

Když se publikuje stránka Movies/Edit:

  • Hodnoty formuláře na stránce jsou vázány na Movie vlastnost. Atribut [BindProperty] umožňuje vazbu modelu.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Pokud jsou ve stavu modelu chyby, ReleaseDate například nelze převést na datum, formulář se znovu zobrazí s odeslanými hodnotami.

  • Pokud neexistují žádné chyby modelu, film se uloží.

Metody HTTP GET na stránkách Index, Create a Delete Razor se řídí podobným vzorem. Metoda HTTP POST OnPostAsync na create Razor page se řídí podobným vzorem OnPostAsync jako metoda v Edit Razor Page.

Další kroky

Vygenerovaná filmová aplikace má dobrý začátek, ale prezentace není ideální. Datum vydání by mělo být dvě slova– Datum vydání.

Otevřená filmová aplikace v Chromu

Aktualizace vygenerovaného kódu

Models/Movie.cs Otevřete soubor a přidejte zvýrazněné řádky uvedené v následujícím kódu:

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; }
    }
}

V předchozím kódu:

  • Datová [Column(TypeName = "decimal(18, 2)")] poznámka umožňuje entity Framework Core správně mapovat Price na měnu v databázi. Další informace naleznete v tématu Datové typy.
  • Atribut [Display] určuje zobrazovaný název pole. V předchozím kódu místo releaseDate zadejte datum vydání.
  • Atribut [DataType] určuje typ dat (Date). Informace o čase uložené v poli se nezobrazují.

DataAnnotations najdete v dalším kurzu.

Přejděte na Stránky nebo filmy a najeďte myší na odkaz Upravit a zobrazte cílovou adresu URL.

Okno prohlížeče s myší na odkaz Upravit a zobrazená adresa URL https://localhost:1234/Movies/Edit/5 odkazu

Odkazy Upravit, Podrobnosti a Odstranit jsou generovány pomocným pomocníkem značky ukotvení v Pages/Movies/Index.cshtml souboru.

@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>

Pomocné rutiny značek umožňují, aby se kód na straně serveru v souborech Razor podílel na vytváření a vykreslování elementů HTML.

V předchozím kódu pomocník značky ukotvení dynamicky generuje hodnotu atributu HTML href ze Razor stránky (trasa je relativní), identifikátor asp-pagetrasyasp-route-id (). Další informace najdete v tématu Generování adres URL pro stránky.

K prozkoumání vygenerované značky použijte zdroj zobrazení z prohlížeče. Část vygenerovaného kódu HTML je znázorněná níže:

<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>

Dynamicky generované odkazy předávají ID videa s řetězcem dotazu. Například in ?id=1https://localhost:5001/Movies/Details?id=1.

Přidání šablony trasy

Aktualizujte stránky Upravit, Podrobnosti a Odstranit Razor tak, aby používaly {id:int} šablonu trasy. Změňte direktivu stránky pro každou z těchto stránek na @page@page "{id:int}". Spusťte aplikaci a pak zobrazte zdroj.

Vygenerovaný kód HTML přidá ID do části cesty adresy URL:

<td>
  <a href="/Movies/Edit/1">Edit</a> |
  <a href="/Movies/Details/1">Details</a> |
  <a href="/Movies/Delete/1">Delete</a>
</td>

Požadavek na stránku se šablonou {id:int} trasy, která neobsahuje celé číslo, vrátí chybu HTTP 404 (nenalezena). Například https://localhost:5001/Movies/Details vrátí chybu 404. Pokud chcete nastavit ID jako volitelné, připojte k omezení trasy symbol ?:

@page "{id:int?}"

Otestujte chování @page "{id:int?}":

  1. Nastavte direktivu Pages/Movies/Details.cshtml stránky na @page "{id:int?}"hodnotu .
  2. Nastavte zarážku v public async Task<IActionResult> OnGetAsync(int? id), v Pages/Movies/Details.cshtml.cs.
  3. Přejděte na https://localhost:5001/Movies/Details/.

S direktivou @page "{id:int}" se zarážka nikdy nedostane. Směrovací modul vrátí http 404. Using @page "{id:int?}", OnGetAsync metoda vrátí NotFound (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();
}

Kontrola zpracování výjimek souběžnosti

Zkontrolujte metodu OnPostAsyncPages/Movies/Edit.cshtml.cs v souboru:

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);
}

Předchozí kód zjistí výjimky souběžnosti, když jeden klient odstraní video a ostatní klienty publikují změny videa.

Postup otestování catch bloku:

  1. Nastavte zarážku na catch (DbUpdateConcurrencyException).
  2. Vyberte Upravit pro film, proveďte změny, ale nezadávejte uložit.
  3. V jiném okně prohlížeče vyberte odkaz Odstranit pro stejný film a pak video odstraňte.
  4. V předchozím okně prohlížeče publikujte změny videa.

Produkční kód může chtít zjistit konflikty souběžnosti. Další informace najdete v tématu Zpracování konfliktů souběžnosti.

Publikování a kontrola vazby

Pages/Movies/Edit.cshtml.cs Prozkoumejte soubor:

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);
    }

Při provedení požadavku HTTP GET na stránku Filmy/Úpravy, například https://localhost:5001/Movies/Edit/3:

  • Metoda OnGetAsync načte film z databáze a vrátí metodu Page .
  • Metoda Page vykreslí Pages/Movies/Edit.cshtmlRazor Stránku. Soubor Pages/Movies/Edit.cshtml obsahuje direktivu @model RazorPagesMovie.Pages.Movies.EditModelmodelu, která zpřístupňuje filmový model na stránce.
  • Formulář Upravit se zobrazí s hodnotami z filmu.

Když se publikuje stránka Movies/Edit:

  • Hodnoty formuláře na stránce jsou vázány na Movie vlastnost. Atribut [BindProperty] umožňuje vazbu modelu.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Pokud jsou ve stavu modelu chyby, ReleaseDate například nelze převést na datum, formulář se znovu zobrazí s odeslanými hodnotami.

  • Pokud neexistují žádné chyby modelu, film se uloží.

Metody HTTP GET na stránkách Index, Create a Delete Razor se řídí podobným vzorem. Metoda HTTP POST OnPostAsync na create Razor page se řídí podobným vzorem OnPostAsync jako metoda v Edit Razor Page.

Další kroky