Megosztás a következőn keresztül:


5. rész: A létrehozott lapok frissítése egy ASP.NET Core-alkalmazásban

Megjegyzés:

Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.

Figyelmeztetés

A ASP.NET Core ezen verziója már nem támogatott. További információt a .NET és a .NET Core támogatási szabályzatában talál. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.

Az állványozott filmalkalmazás jól indul, de a bemutató nem ideális. A ReleaseDate-nek két szónak kell lennie: Kiadás dátuma.

A filmalkalmazás meg van nyitva a Chrome-ban

A modell frissítése

Frissítse Models/Movie.cs a következő kiemelt kóddal:

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

Az előző kódban:

  • Az [Column(TypeName = "decimal(18, 2)")] adatjegyzet lehetővé teszi, hogy az Entity Framework Core megfelelően megfeleltetsen Price az adatbázis pénznemére. További információ: adattípusok.
  • A [Megjelenítés] attribútum egy mező megjelenítendő nevét adja meg. Az előző kódban ahelyett, Release Date hogy ReleaseDate.
  • A [DataType] attribútum adja meg az adatok típusát (Date). A mezőben tárolt időadatok nem jelennek meg.

A DataAnnotationst a következő oktatóanyag ismerteti.

Tallózással keresse meg a Lapok/Filmek lapot, és mutasson a Szerkesztés hivatkozásra a cél URL-cím megtekintéséhez.

Böngészőablak a Szerkesztés hivatkozásra mutató egérrel, és megjelenik egy hivatkozás URL-címe https://localhost:1234/Movies/Edit/5

A szerkesztési, részletes és törlési hivatkozásokat a fájl horgonycímke-segédjePages/Movies/Index.cshtml hozza létre.

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

A címkesegédek lehetővé teszik, hogy a kiszolgálóoldali kód részt vegyen a HTML-elemek Razor fájlokban történő létrehozásában és megjelenítésében.

Az előző kódban a Horgonycímke segéd dinamikusan generálja a HTML-attribútum href értékét a Razor lapról (az útvonal relatív), a asp-page, és az útvonalazonosítóból (asp-route-id). További információt a Pages URL-címének generálása című témakörben talál.

A létrehozott korrektúra vizsgálatához használja a Forrás megtekintése böngészőből parancsot. A létrehozott HTML egy része az alábbiakban látható:

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

A dinamikusan létrehozott hivatkozások egy lekérdezési sztringgel adják át a filmazonosítót. Például a ?id=1 be https://localhost:5001/Movies/Details?id=1.

Útvonalsablon hozzáadása

Frissítse a Lapok szerkesztése, részletei és törlése Razor elemet az {id:int} útvonalsablon használatához. Módosítsa az egyes lapok oldalirányelvét a következőre @page@page "{id:int}": . Futtassa az alkalmazást, majd tekintse meg a forrást.

A létrehozott HTML hozzáadja az azonosítót az URL elérési útjának részéhez:

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

Az egész számot {id:int} tartalmazó útvonalsablonnal rendelkező lapra irányuló kérés HTTP 404-es (nem található) hibát ad vissza. Például https://localhost:5001/Movies/Details 404-et ad vissza. Ha az azonosítót nem kötelező megadni, fűzze hozzá ? az útvonalkorlátozáshoz:

@page "{id:int?}"

A következő viselkedésének tesztelése @page "{id:int?}":

  1. Állítsa be az oldalirányelmét a következőre Pages/Movies/Details.cshtml@page "{id:int?}": .
  2. Töréspont beállítása a következőben public async Task<IActionResult> OnGetAsync(int? id): Pages/Movies/Details.cshtml.cs.
  3. Navigáljon ide: https://localhost:5001/Movies/Details/.

@page "{id:int}" Az irányelv, a töréspont soha nem éri el. Az útválasztási motor a HTTP 404-et adja vissza. A használatával @page "{id:int?}"a OnGetAsync metódus visszatér 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();
}

Egyidejűségi kivételkezelés áttekintése

Tekintse át a OnPostAsync fájlban található metódust Pages/Movies/Edit.cshtml.cs :

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

Az előző kód egyidejűségi kivételeket észlel, ha az egyik ügyfél törli a filmet, a másik ügyfél pedig módosítja a filmet.

A blokk tesztelése catch :

  1. Töréspont beállítása a következőre catch (DbUpdateConcurrencyException): .
  2. Válassza a Film szerkesztése lehetőséget, végezze el a módosításokat, de ne írja be a Mentés gombot.
  3. Egy másik böngészőablakban válassza ki ugyanahhoz a filmhez a Törlés hivatkozást, majd törölje a filmet.
  4. Az előző böngészőablakban tegye közzé a film módosításait.

Előfordulhat, hogy az éles kód egyidejűségi ütközéseket szeretne észlelni. További információt az egyidejűségi ütközések kezelése című témakörben talál.

Közzétételi és kötési felülvizsgálat

Vizsgálja meg a Pages/Movies/Edit.cshtml.cs fájlt:

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

Ha HTTP GET kérést küld a Filmek/Szerkesztés lapra, például https://localhost:5001/Movies/Edit/3:

  • A OnGetAsync metódus lekéri a filmet az adatbázisból, és visszaadja a metódust Page .
  • A Page metódus megjeleníti a Pages/Movies/Edit.cshtmlRazor lapot. A Pages/Movies/Edit.cshtml fájl tartalmazza a modell irányelvét @model RazorPagesMovie.Pages.Movies.EditModel, amely elérhetővé teszi a filmmodellt az oldalon.
  • A Szerkesztés űrlap a film értékeivel együtt jelenik meg.

A Filmek/Szerkesztés lap közzétételekor:

  • A lapon lévő űrlapértékek a Movie tulajdonsághoz vannak kötve. Az [BindProperty] attribútum engedélyezi a modellkötést.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Ha például a modell állapota hibás, ReleaseDate például nem konvertálható dátummá, az űrlap újra megjelenik a beküldött értékekkel.

  • Ha nincsenek modellhibák, a rendszer menti a filmet.

Az indexelési, létrehozási és törlési Razor lapok HTTP GET metódusai hasonló mintát követnek. A Http POST OnPostAsync metódus a Lap létrehozása Razor lapon a szerkesztési OnPostAsync lap metódusához Razor hasonló mintát követ.

Következő lépések

Az állványozott filmalkalmazás jól indul, de a bemutató nem ideális. A ReleaseDate-nek két szónak kell lennie: Kiadás dátuma.

A filmalkalmazás meg van nyitva a Chrome-ban

A modell frissítése

Frissítse Models/Movie.cs a következő kiemelt kóddal:

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

Az előző kódban:

  • Az [Column(TypeName = "decimal(18, 2)")] adatjegyzet lehetővé teszi, hogy az Entity Framework Core megfelelően megfeleltetsen Price az adatbázis pénznemére. További információ: adattípusok.
  • A [Megjelenítés] attribútum egy mező megjelenítendő nevét adja meg. Az előző kódban ahelyett, Release Date hogy ReleaseDate.
  • A [DataType] attribútum adja meg az adatok típusát (Date). A mezőben tárolt időadatok nem jelennek meg.

A DataAnnotationst a következő oktatóanyag ismerteti.

Tallózással keresse meg a Lapok/Filmek lapot, és mutasson a Szerkesztés hivatkozásra a cél URL-cím megtekintéséhez.

Böngészőablak a Szerkesztés hivatkozásra mutató egérrel, és megjelenik egy hivatkozás URL-címe https://localhost:1234/Movies/Edit/5

A szerkesztési, részletes és törlési hivatkozásokat a fájl horgonycímke-segédjePages/Movies/Index.cshtml hozza létre.

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

A címkesegédek lehetővé teszik, hogy a kiszolgálóoldali kód részt vegyen a HTML-elemek Razor fájlokban történő létrehozásában és megjelenítésében.

Az előző kódban a Horgonycímke segéd dinamikusan generálja a HTML-attribútum href értékét a Razor lapról (az útvonal relatív), a asp-page, és az útvonalazonosítóból (asp-route-id). További információt a Pages URL-címének generálása című témakörben talál.

A létrehozott korrektúra vizsgálatához használja a Forrás megtekintése böngészőből parancsot. A létrehozott HTML egy része az alábbiakban látható:

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

A dinamikusan létrehozott hivatkozások egy lekérdezési sztringgel adják át a filmazonosítót. Például a ?id=1 be https://localhost:5001/Movies/Details?id=1.

Útvonalsablon hozzáadása

Frissítse a Lapok szerkesztése, részletei és törlése Razor elemet az {id:int} útvonalsablon használatához. Módosítsa az egyes lapok oldalirányelvét a következőre @page@page "{id:int}": . Futtassa az alkalmazást, majd tekintse meg a forrást.

A létrehozott HTML hozzáadja az azonosítót az URL elérési útjának részéhez:

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

Az egész számot {id:int} tartalmazó útvonalsablonnal rendelkező lapra irányuló kérés HTTP 404-es (nem található) hibát ad vissza. Például https://localhost:5001/Movies/Details 404-et ad vissza. Ha az azonosítót nem kötelező megadni, fűzze hozzá ? az útvonalkorlátozáshoz:

@page "{id:int?}"

A következő viselkedésének tesztelése @page "{id:int?}":

  1. Állítsa be az oldalirányelmét a következőre Pages/Movies/Details.cshtml@page "{id:int?}": .
  2. Töréspont beállítása a következőben public async Task<IActionResult> OnGetAsync(int? id): Pages/Movies/Details.cshtml.cs.
  3. Navigáljon ide: https://localhost:5001/Movies/Details/.

@page "{id:int}" Az irányelv, a töréspont soha nem éri el. Az útválasztási motor a HTTP 404-et adja vissza. A használatával @page "{id:int?}"a OnGetAsync metódus visszatér 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();
}

Egyidejűségi kivételkezelés áttekintése

Tekintse át a OnPostAsync fájlban található metódust Pages/Movies/Edit.cshtml.cs :

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

Az előző kód egyidejűségi kivételeket észlel, ha az egyik ügyfél törli a filmet, a másik ügyfél pedig módosítja a filmet.

A blokk tesztelése catch :

  1. Töréspont beállítása a következőre catch (DbUpdateConcurrencyException): .
  2. Válassza a Film szerkesztése lehetőséget, végezze el a módosításokat, de ne írja be a Mentés gombot.
  3. Egy másik böngészőablakban válassza ki ugyanahhoz a filmhez a Törlés hivatkozást, majd törölje a filmet.
  4. Az előző böngészőablakban tegye közzé a film módosításait.

Előfordulhat, hogy az éles kód egyidejűségi ütközéseket szeretne észlelni. További információt az egyidejűségi ütközések kezelése című témakörben talál.

Közzétételi és kötési felülvizsgálat

Vizsgálja meg a Pages/Movies/Edit.cshtml.cs fájlt:

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

Ha HTTP GET kérést küld a Filmek/Szerkesztés lapra, például https://localhost:5001/Movies/Edit/3:

  • A OnGetAsync metódus lekéri a filmet az adatbázisból, és visszaadja a metódust Page .
  • A Page metódus megjeleníti a Pages/Movies/Edit.cshtmlRazor lapot. A Pages/Movies/Edit.cshtml fájl tartalmazza a modell irányelvét @model RazorPagesMovie.Pages.Movies.EditModel, amely elérhetővé teszi a filmmodellt az oldalon.
  • A Szerkesztés űrlap a film értékeivel együtt jelenik meg.

A Filmek/Szerkesztés lap közzétételekor:

  • A lapon lévő űrlapértékek a Movie tulajdonsághoz vannak kötve. Az [BindProperty] attribútum engedélyezi a modellkötést.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Ha például a modell állapota hibás, ReleaseDate például nem konvertálható dátummá, az űrlap újra megjelenik a beküldött értékekkel.

  • Ha nincsenek modellhibák, a rendszer menti a filmet.

Az indexelési, létrehozási és törlési Razor lapok HTTP GET metódusai hasonló mintát követnek. A Http POST OnPostAsync metódus a Lap létrehozása Razor lapon a szerkesztési OnPostAsync lap metódusához Razor hasonló mintát követ.

Következő lépések

Az állványozott filmalkalmazás jól indul, de a bemutató nem ideális. A ReleaseDate-nek két szónak kell lennie: Kiadás dátuma.

A filmalkalmazás meg van nyitva a Chrome-ban

A modell frissítése

Frissítse Models/Movie.cs a következő kiemelt kóddal:

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

Az előző kódban:

  • Az [Column(TypeName = "decimal(18, 2)")] adatjegyzet lehetővé teszi, hogy az Entity Framework Core megfelelően megfeleltetsen Price az adatbázis pénznemére. További információ: adattípusok.
  • A [Megjelenítés] attribútum egy mező megjelenítendő nevét adja meg. Az előző kódban ahelyett, Release Date hogy ReleaseDate.
  • A [DataType] attribútum adja meg az adatok típusát (Date). A mezőben tárolt időadatok nem jelennek meg.

A DataAnnotationst a következő oktatóanyag ismerteti.

Tallózással keresse meg a Lapok/Filmek lapot, és mutasson a Szerkesztés hivatkozásra a cél URL-cím megtekintéséhez.

Böngészőablak a Szerkesztés hivatkozásra mutató egérrel, és megjelenik egy hivatkozás URL-címe https://localhost:1234/Movies/Edit/5

A szerkesztési, részletes és törlési hivatkozásokat a fájl horgonycímke-segédjePages/Movies/Index.cshtml hozza létre.

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

A címkesegédek lehetővé teszik, hogy a kiszolgálóoldali kód részt vegyen a HTML-elemek Razor fájlokban történő létrehozásában és megjelenítésében.

Az előző kódban a Horgonycímke segéd dinamikusan generálja a HTML-attribútum href értékét a Razor lapról (az útvonal relatív), a asp-page, és az útvonalazonosítóból (asp-route-id). További információt a Pages URL-címének generálása című témakörben talál.

A létrehozott korrektúra vizsgálatához használja a Forrás megtekintése böngészőből parancsot. A létrehozott HTML egy része az alábbiakban látható:

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

A dinamikusan létrehozott hivatkozások egy lekérdezési sztringgel adják át a filmazonosítót. Például a ?id=1 be https://localhost:5001/Movies/Details?id=1.

Útvonalsablon hozzáadása

Frissítse a Lapok szerkesztése, részletei és törlése Razor elemet az {id:int} útvonalsablon használatához. Módosítsa az egyes lapok oldalirányelvét a következőre @page@page "{id:int}": . Futtassa az alkalmazást, majd tekintse meg a forrást.

A létrehozott HTML hozzáadja az azonosítót az URL elérési útjának részéhez:

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

Az egész számot {id:int} tartalmazó útvonalsablonnal rendelkező lapra irányuló kérés HTTP 404-es (nem található) hibát ad vissza. Például https://localhost:5001/Movies/Details 404-et ad vissza. Ha az azonosítót nem kötelező megadni, fűzze hozzá ? az útvonalkorlátozáshoz:

@page "{id:int?}"

A következő viselkedésének tesztelése @page "{id:int?}":

  1. Állítsa be az oldalirányelmét a következőre Pages/Movies/Details.cshtml@page "{id:int?}": .
  2. Töréspont beállítása a következőben public async Task<IActionResult> OnGetAsync(int? id): Pages/Movies/Details.cshtml.cs.
  3. Navigáljon ide: https://localhost:5001/Movies/Details/.

@page "{id:int}" Az irányelv, a töréspont soha nem éri el. Az útválasztási motor a HTTP 404-et adja vissza. A használatával @page "{id:int?}"a OnGetAsync metódus visszatér 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();
}

Egyidejűségi kivételkezelés áttekintése

Tekintse át a OnPostAsync fájlban található metódust Pages/Movies/Edit.cshtml.cs :

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

Az előző kód egyidejűségi kivételeket észlel, ha az egyik ügyfél törli a filmet, a másik ügyfél pedig módosítja a filmet.

A blokk tesztelése catch :

  1. Töréspont beállítása a következőre catch (DbUpdateConcurrencyException): .
  2. Válassza a Film szerkesztése lehetőséget, végezze el a módosításokat, de ne írja be a Mentés gombot.
  3. Egy másik böngészőablakban válassza ki ugyanahhoz a filmhez a Törlés hivatkozást, majd törölje a filmet.
  4. Az előző böngészőablakban tegye közzé a film módosításait.

Előfordulhat, hogy az éles kód egyidejűségi ütközéseket szeretne észlelni. További információt az egyidejűségi ütközések kezelése című témakörben talál.

Közzétételi és kötési felülvizsgálat

Vizsgálja meg a Pages/Movies/Edit.cshtml.cs fájlt:

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

Ha HTTP GET kérést küld a Filmek/Szerkesztés lapra, például https://localhost:5001/Movies/Edit/3:

  • A OnGetAsync metódus lekéri a filmet az adatbázisból, és visszaadja a metódust Page .
  • A Page metódus megjeleníti a Pages/Movies/Edit.cshtmlRazor lapot. A Pages/Movies/Edit.cshtml fájl tartalmazza a modell irányelvét @model RazorPagesMovie.Pages.Movies.EditModel, amely elérhetővé teszi a filmmodellt az oldalon.
  • A Szerkesztés űrlap a film értékeivel együtt jelenik meg.

A Filmek/Szerkesztés lap közzétételekor:

  • A lapon lévő űrlapértékek a Movie tulajdonsághoz vannak kötve. Az [BindProperty] attribútum engedélyezi a modellkötést.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Ha például a modell állapota hibás, ReleaseDate például nem konvertálható dátummá, az űrlap újra megjelenik a beküldött értékekkel.

  • Ha nincsenek modellhibák, a rendszer menti a filmet.

Az indexelési, létrehozási és törlési Razor lapok HTTP GET metódusai hasonló mintát követnek. A Http POST OnPostAsync metódus a Lap létrehozása Razor lapon a szerkesztési OnPostAsync lap metódusához Razor hasonló mintát követ.

Következő lépések

Az állványozott filmalkalmazás jól indul, de a bemutató nem ideális. A ReleaseDate-nek két szónak kell lennie: Kiadás dátuma.

A filmalkalmazás meg van nyitva a Chrome-ban

A létrehozott kód frissítése

Frissítse Models/Movie.cs a következő kiemelt kóddal:

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

Az előző kódban:

  • Az [Column(TypeName = "decimal(18, 2)")] adatjegyzet lehetővé teszi, hogy az Entity Framework Core megfelelően megfeleltetsen Price az adatbázis pénznemére. További információ: adattípusok.
  • A [Megjelenítés] attribútum egy mező megjelenítendő nevét adja meg. Az előző kódban a "ReleaseDate" helyett a "ReleaseDate" helyett a "Kiadás dátuma" szerepel.
  • A [DataType] attribútum adja meg az adatok típusát (Date). A mezőben tárolt időadatok nem jelennek meg.

A DataAnnotationst a következő oktatóanyag ismerteti.

Tallózással keresse meg a Lapok/Filmek lapot, és mutasson a Szerkesztés hivatkozásra a cél URL-cím megtekintéséhez.

Böngészőablak a Szerkesztés hivatkozásra mutató egérrel, és megjelenik egy hivatkozás URL-címe https://localhost:1234/Movies/Edit/5

A szerkesztési, részletes és törlési hivatkozásokat a fájl horgonycímke-segédjePages/Movies/Index.cshtml hozza létre.

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

A címkesegédek lehetővé teszik, hogy a kiszolgálóoldali kód részt vegyen a HTML-elemek Razor fájlokban történő létrehozásában és megjelenítésében.

Az előző kódban a Horgonycímke segéd dinamikusan generálja a HTML-attribútum href értékét a Razor lapról (az útvonal relatív), a asp-page, és az útvonalazonosítóból (asp-route-id). További információt a Pages URL-címének generálása című témakörben talál.

A létrehozott korrektúra vizsgálatához használja a Forrás megtekintése böngészőből parancsot. A létrehozott HTML egy része az alábbiakban látható:

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

A dinamikusan létrehozott hivatkozások egy lekérdezési sztringgel adják át a filmazonosítót. Például a ?id=1 be https://localhost:5001/Movies/Details?id=1.

Útvonalsablon hozzáadása

Frissítse a Lapok szerkesztése, részletei és törlése Razor elemet az {id:int} útvonalsablon használatához. Módosítsa az egyes lapok oldalirányelvét a következőre @page@page "{id:int}": . Futtassa az alkalmazást, majd tekintse meg a forrást.

A létrehozott HTML hozzáadja az azonosítót az URL elérési útjának részéhez:

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

Az egész számot {id:int} tartalmazó útvonalsablont tartalmazó lapra irányuló kérés HTTP 404-es (nem található) hibát ad vissza. Például https://localhost:5001/Movies/Details 404-et ad vissza. Ha az azonosítót nem kötelező megadni, fűzze hozzá ? az útvonalkorlátozáshoz:

@page "{id:int?}"

A következő viselkedésének tesztelése @page "{id:int?}":

  1. Állítsa be az oldalirányelmét a következőre Pages/Movies/Details.cshtml@page "{id:int?}": .
  2. Töréspont beállítása a következőben public async Task<IActionResult> OnGetAsync(int? id): Pages/Movies/Details.cshtml.cs.
  3. Navigáljon ide: https://localhost:5001/Movies/Details/.

@page "{id:int}" Az irányelv, a töréspont soha nem éri el. Az útválasztási motor a HTTP 404-et adja vissza. A használatával @page "{id:int?}"a OnGetAsync metódus visszatér 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();
}

Egyidejűségi kivételkezelés áttekintése

Tekintse át a OnPostAsync fájlban található metódust Pages/Movies/Edit.cshtml.cs :

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

Az előző kód egyidejűségi kivételeket észlel, ha az egyik ügyfél törli a filmet, a másik ügyfél pedig módosítja a filmet. Az előző kód nem észleli azokat az ütközéseket, amelyek azért fordulnak elő, mert két vagy több ügyfél egyszerre szerkeszti ugyanazt a filmet. Ebben az esetben a rendszer több ügyfél szerkesztését alkalmazza a meghívott sorrendben SaveChanges , és a később alkalmazott módosítások felülírhatják a korábbi módosításokat elavult értékekkel.

A blokk tesztelése catch :

  1. Töréspont beállítása a következőre catch (DbUpdateConcurrencyException): .
  2. Válassza a Film szerkesztése lehetőséget, végezze el a módosításokat, de ne írja be a Mentés gombot.
  3. Egy másik böngészőablakban válassza ki ugyanahhoz a filmhez a Törlés hivatkozást, majd törölje a filmet.
  4. Az előző böngészőablakban tegye közzé a film módosításait.

Előfordulhat, hogy az éles kód további egyidejűségi ütközéseket szeretne észlelni, például egy entitást egyszerre több ügyfél szerkeszt. További információt az egyidejűségi ütközések kezelése című témakörben talál.

Közzétételi és kötési felülvizsgálat

Vizsgálja meg a Pages/Movies/Edit.cshtml.cs fájlt:

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

Ha HTTP GET kérést küld a Filmek/Szerkesztés lapra, például https://localhost:5001/Movies/Edit/3:

  • A OnGetAsync metódus lekéri a filmet az adatbázisból, és visszaadja a metódust Page .
  • A Page metódus megjeleníti a Pages/Movies/Edit.cshtmlRazor lapot. A Pages/Movies/Edit.cshtml fájl tartalmazza a modell irányelvét @model RazorPagesMovie.Pages.Movies.EditModel, amely elérhetővé teszi a filmmodellt az oldalon.
  • A Szerkesztés űrlap a film értékeivel együtt jelenik meg.

A Filmek/Szerkesztés lap közzétételekor:

  • A lapon lévő űrlapértékek a Movie tulajdonsághoz vannak kötve. Az [BindProperty] attribútum engedélyezi a modellkötést.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Ha például a modell állapota hibás, ReleaseDate például nem konvertálható dátummá, az űrlap újra megjelenik a beküldött értékekkel.

  • Ha nincsenek modellhibák, a rendszer menti a filmet.

Az indexelési, létrehozási és törlési Razor lapok HTTP GET metódusai hasonló mintát követnek. A Http POST OnPostAsync metódus a Lap létrehozása Razor lapon a szerkesztési OnPostAsync lap metódusához Razor hasonló mintát követ.

Következő lépések

Az állványozott filmalkalmazás jól indul, de a bemutató nem ideális. A ReleaseDate-nek két szónak kell lennie: Kiadás dátuma.

A filmalkalmazás meg van nyitva a Chrome-ban

A létrehozott kód frissítése

Nyissa meg a Models/Movie.cs fájlt, és adja hozzá a következő kódban látható kiemelt sorokat:

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

Az előző kódban:

  • Az [Column(TypeName = "decimal(18, 2)")] adatjegyzet lehetővé teszi, hogy az Entity Framework Core megfelelően megfeleltetsen Price az adatbázis pénznemére. További információ: adattípusok.
  • A [Megjelenítés] attribútum egy mező megjelenítendő nevét adja meg. Az előző kódban a "ReleaseDate" helyett a "ReleaseDate" helyett a "Kiadás dátuma" szerepel.
  • A [DataType] attribútum adja meg az adatok típusát (Date). A mezőben tárolt időadatok nem jelennek meg.

A DataAnnotationst a következő oktatóanyag ismerteti.

Tallózással keresse meg a Lapok/Filmek lapot, és mutasson a Szerkesztés hivatkozásra a cél URL-cím megtekintéséhez.

Böngészőablak a Szerkesztés hivatkozásra mutató egérrel, és megjelenik egy hivatkozás URL-címe https://localhost:1234/Movies/Edit/5

A szerkesztési, részletes és törlési hivatkozásokat a fájl horgonycímke-segédjePages/Movies/Index.cshtml hozza létre.

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

A címkesegédek lehetővé teszik, hogy a kiszolgálóoldali kód részt vegyen a HTML-elemek Razor fájlokban történő létrehozásában és megjelenítésében.

Az előző kódban a Horgonycímke segéd dinamikusan generálja a HTML-attribútum href értékét a Razor lapról (az útvonal relatív), a asp-page, és az útvonalazonosítóból (asp-route-id). További információt a Pages URL-címének generálása című témakörben talál.

A létrehozott korrektúra vizsgálatához használja a Forrás megtekintése böngészőből parancsot. A létrehozott HTML egy része az alábbiakban látható:

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

A dinamikusan létrehozott hivatkozások egy lekérdezési sztringgel adják át a filmazonosítót. Például a ?id=1 be https://localhost:5001/Movies/Details?id=1.

Útvonalsablon hozzáadása

Frissítse a Lapok szerkesztése, részletei és törlése Razor elemet az {id:int} útvonalsablon használatához. Módosítsa az egyes lapok oldalirányelvét a következőre @page@page "{id:int}": . Futtassa az alkalmazást, majd tekintse meg a forrást.

A létrehozott HTML hozzáadja az azonosítót az URL elérési útjának részéhez:

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

Az egész számot {id:int} tartalmazó útvonalsablont tartalmazó lapra irányuló kérés HTTP 404-es (nem található) hibát ad vissza. Például https://localhost:5001/Movies/Details 404-et ad vissza. Ha az azonosítót nem kötelező megadni, fűzze hozzá ? az útvonalkorlátozáshoz:

@page "{id:int?}"

A következő viselkedésének tesztelése @page "{id:int?}":

  1. Állítsa be az oldalirányelmét a következőre Pages/Movies/Details.cshtml@page "{id:int?}": .
  2. Töréspont beállítása a következőben public async Task<IActionResult> OnGetAsync(int? id): Pages/Movies/Details.cshtml.cs.
  3. Navigáljon ide: https://localhost:5001/Movies/Details/.

@page "{id:int}" Az irányelv, a töréspont soha nem éri el. Az útválasztási motor a HTTP 404-et adja vissza. A használatával @page "{id:int?}"a OnGetAsync metódus visszatér 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();
}

Egyidejűségi kivételkezelés áttekintése

Tekintse át a OnPostAsync fájlban található metódust Pages/Movies/Edit.cshtml.cs :

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

Az előző kód egyidejűségi kivételeket észlel, ha az egyik ügyfél törli a filmet, a másik ügyfél pedig módosítja a filmet.

A blokk tesztelése catch :

  1. Töréspont beállítása a következőre catch (DbUpdateConcurrencyException): .
  2. Válassza a Film szerkesztése lehetőséget, végezze el a módosításokat, de ne írja be a Mentés gombot.
  3. Egy másik böngészőablakban válassza ki ugyanahhoz a filmhez a Törlés hivatkozást, majd törölje a filmet.
  4. Az előző böngészőablakban tegye közzé a film módosításait.

Előfordulhat, hogy az éles kód egyidejűségi ütközéseket szeretne észlelni. További információt az egyidejűségi ütközések kezelése című témakörben talál.

Közzétételi és kötési felülvizsgálat

Vizsgálja meg a Pages/Movies/Edit.cshtml.cs fájlt:

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

Ha HTTP GET kérést küld a Filmek/Szerkesztés lapra, például https://localhost:5001/Movies/Edit/3:

  • A OnGetAsync metódus lekéri a filmet az adatbázisból, és visszaadja a metódust Page .
  • A Page metódus megjeleníti a Pages/Movies/Edit.cshtmlRazor lapot. A Pages/Movies/Edit.cshtml fájl tartalmazza a modell irányelvét @model RazorPagesMovie.Pages.Movies.EditModel, amely elérhetővé teszi a filmmodellt az oldalon.
  • A Szerkesztés űrlap a film értékeivel együtt jelenik meg.

A Filmek/Szerkesztés lap közzétételekor:

  • A lapon lévő űrlapértékek a Movie tulajdonsághoz vannak kötve. Az [BindProperty] attribútum engedélyezi a modellkötést.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Ha például a modell állapota hibás, ReleaseDate például nem konvertálható dátummá, az űrlap újra megjelenik a beküldött értékekkel.

  • Ha nincsenek modellhibák, a rendszer menti a filmet.

Az indexelési, létrehozási és törlési Razor lapok HTTP GET metódusai hasonló mintát követnek. A Http POST OnPostAsync metódus a Lap létrehozása Razor lapon a szerkesztési OnPostAsync lap metódusához Razor hasonló mintát követ.

Következő lépések