Čá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 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

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