Bölüm 5, bir ASP.NET Core uygulamasında oluşturulan sayfaları güncelleştirme

Gönderen Rick Anderson

İskeleli film uygulamasının iyi bir başlangıcı vardır, ancak sunu ideal değildir. ReleaseDate iki sözcük olmalıdır: Yayın Tarihi.

Movie application open in Chrome

Oluşturulan kodu güncelleştirme

Aşağıdaki vurgulanmış kodla güncelleştirin Models/Movie.cs :

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

Önceki kodda:

  • Veri [Column(TypeName = "decimal(18, 2)")] ek açıklaması, Entity Framework Core'un veritabanındaki para birimiyle doğru şekilde eşlenebilen Price olmasını sağlar. Daha fazla bilgi için bkz. Veri Türleri.
  • [Display] özniteliği bir alanın görünen adını belirtir. Yukarıdaki kodda ,"ReleaseDate" yerine "Release Date" (Yayın Tarihi).
  • [DataType] özniteliği verilerin türünü belirtir (Date). Alanda depolanan zaman bilgileri görüntülenmez.

DataAnnotations , sonraki öğreticide ele alınmıştır.

Sayfalar/Filmler'e gidin ve hedef URL'yi görmek için Düzenle bağlantısının üzerine gelin.

Browser window with mouse over the Edit link and a link Url of https://localhost:1234/Movies/Edit/5 is shown

Düzenle, Ayrıntılar ve Sil bağlantıları, dosyadaki Pages/Movies/Index.cshtmlYer Işareti Yardımcısı tarafından oluşturulur.

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

Etiket Yardımcıları , sunucu tarafı kodunun dosyalarda HTML öğeleri Razor oluşturma ve işlemeye katılmasını sağlar.

Yukarıdaki kodda Yer Işareti Etiketi Yardımcısı, Html öznitelik değerini Sayfadan href (yol görelidir), asp-pageve yol tanımlayıcısından Razor (asp-route-id ) dinamik olarak oluşturur. Daha fazla bilgi için bkz. Sayfalar için URL oluşturma.

Oluşturulan işaretlemeyi incelemek için tarayıcıdan Kaynağı Görüntüle'yi kullanın. Oluşturulan HTML'nin bir bölümü aşağıda gösterilmiştir:

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

Dinamik olarak oluşturulan bağlantılar, film kimliğini bir sorgu dizesiyle geçirir. Örneğin, içindeki ?id=1https://localhost:5001/Movies/Details?id=1.

Yol şablonu ekleme

Rota şablonunu kullanmak için Sayfaları Düzenle, Ayrıntılar ve Sil'i Razor güncelleştirin {id:int} . Bu sayfaların her biri için sayfa yönergesini olarak @page@page "{id:int}"değiştirin. Uygulamayı çalıştırın ve ardından kaynağı görüntüleyin.

Oluşturulan HTML, kimliği URL'nin yol bölümüne ekler:

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

Tamsayıyı içermeyen yol şablonunu içeren sayfaya {id:int} yönelik bir istek HTTP 404 (bulunamadı) hatası döndürür. Örneğin, https://localhost:5001/Movies/Details 404 hatası döndürür. Kimliği isteğe bağlı hale getirmek için yol kısıtlamasına ekleyin ? :

@page "{id:int?}"

davranışını @page "{id:int?}"test edin:

  1. içindeki Pages/Movies/Details.cshtml sayfa yönergesini olarak @page "{id:int?}"ayarlayın.
  2. içinde içinde public async Task<IActionResult> OnGetAsync(int? id)Pages/Movies/Details.cshtml.csbir kesme noktası ayarlayın.
  3. https://localhost:5001/Movies/Details/ sayfasına gidin.

yönergesi @page "{id:int}" ile kesme noktasına hiçbir zaman isabet etmez. Yönlendirme altyapısı HTTP 404 döndürür. @page "{id:int?}"yöntemi kullanılarak OnGetAsync (HTTP 404) döndürülüyor NotFound :

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

Eşzamanlılık özel durum işlemesini gözden geçirme

Dosyasındaki OnPostAsync yöntemini Pages/Movies/Edit.cshtml.cs gözden geçirin:

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

Önceki kod, bir istemci filmi sildiğinde ve diğer istemci filme değişiklik gönderdiğinde eşzamanlılık özel durumlarını algılar.

Bloğu test etmek catch için:

  1. üzerinde catch (DbUpdateConcurrencyException)bir kesme noktası ayarlayın.
  2. Film için Düzenle'yi seçin, değişiklikler yapın, ancak Kaydet'e girmeyin.
  3. Başka bir tarayıcı penceresinde, aynı film için Sil bağlantısını seçin ve ardından filmi silin.
  4. Önceki tarayıcı penceresinde, değişiklikleri filme gönderin.

Üretim kodu eşzamanlılık çakışmalarını algılamak isteyebilir. Daha fazla bilgi için bkz. Eşzamanlılık çakışmalarını işleme .

Gönderme ve bağlama gözden geçirmesi

Pages/Movies/Edit.cshtml.cs Dosyayı inceleyin:

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

Filmler/Düzenleme sayfasına bir HTTP GET isteği yapıldığında, örneğin: https://localhost:5001/Movies/Edit/3

  • OnGetAsync yöntemi, filmi veritabanından getirir ve yöntemini döndürürPage.
  • Page yöntemi Page'i Pages/Movies/Edit.cshtmlRazor işler. dosyası Pages/Movies/Edit.cshtml , film modelini sayfada kullanılabilir hale getiren model yönergesini @model RazorPagesMovie.Pages.Movies.EditModeliçerir.
  • Düzenle formu filmdeki değerlerle birlikte görüntülenir.

Filmler/Düzenle sayfası gönderildiğinde:

  • Sayfadaki form değerleri özelliğine Movie bağlıdır. [BindProperty] özniteliği Model bağlamayı etkinleştirir.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Örneğin ReleaseDate , model durumunda bir tarihe dönüştürülemeyen hatalar varsa, form gönderilen değerlerle yeniden görüntülenir.

  • Model hatası yoksa film kaydedilir.

, Oluştur ve Sil Razor sayfalarındaki IndexHTTP GET yöntemleri de benzer bir desen izler. Oluşturma Razor Sayfasındaki HTTP POST OnPostAsync yöntemi, Sayfayı Düzenle'deki Razor yönteme OnPostAsync benzer bir desen izler.

Ek kaynaklar

İskeleli film uygulamasının iyi bir başlangıcı vardır, ancak sunu ideal değildir. ReleaseDate iki sözcük olmalıdır: Yayın Tarihi.

Movie application open in Chrome

Oluşturulan kodu güncelleştirme

Models/Movie.cs Dosyayı açın ve aşağıdaki kodda gösterilen vurgulanan satırları ekleyin:

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

Önceki kodda:

  • Veri [Column(TypeName = "decimal(18, 2)")] ek açıklaması, Entity Framework Core'un veritabanındaki para birimiyle doğru şekilde eşlenebilen Price olmasını sağlar. Daha fazla bilgi için bkz. Veri Türleri.
  • [Display] özniteliği bir alanın görünen adını belirtir. Yukarıdaki kodda ,"ReleaseDate" yerine "Release Date" (Yayın Tarihi).
  • [DataType] özniteliği verilerin türünü belirtir (Date). Alanda depolanan zaman bilgileri görüntülenmez.

DataAnnotations , sonraki öğreticide ele alınmıştır.

Sayfalar/Filmler'e gidin ve hedef URL'yi görmek için Düzenle bağlantısının üzerine gelin.

Browser window with mouse over the Edit link and a link Url of https://localhost:1234/Movies/Edit/5 is shown

Düzenle, Ayrıntılar ve Sil bağlantıları, dosyadaki Pages/Movies/Index.cshtmlYer Işareti Yardımcısı tarafından oluşturulur.

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

Etiket Yardımcıları , sunucu tarafı kodunun dosyalarda HTML öğeleri Razor oluşturma ve işlemeye katılmasını sağlar.

Yukarıdaki kodda Yer Işareti Etiketi Yardımcısı, Html öznitelik değerini Sayfadan href (yol görelidir), asp-pageve yol tanımlayıcısından Razor (asp-route-id ) dinamik olarak oluşturur. Daha fazla bilgi için bkz. Sayfalar için URL oluşturma.

Oluşturulan işaretlemeyi incelemek için tarayıcıdan Kaynağı Görüntüle'yi kullanın. Oluşturulan HTML'nin bir bölümü aşağıda gösterilmiştir:

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

Dinamik olarak oluşturulan bağlantılar, film kimliğini bir sorgu dizesiyle geçirir. Örneğin, içindeki ?id=1https://localhost:5001/Movies/Details?id=1.

Yol şablonu ekleme

Rota şablonunu kullanmak için Sayfaları Düzenle, Ayrıntılar ve Sil'i Razor güncelleştirin {id:int} . Bu sayfaların her biri için sayfa yönergesini olarak @page@page "{id:int}"değiştirin. Uygulamayı çalıştırın ve ardından kaynağı görüntüleyin.

Oluşturulan HTML, kimliği URL'nin yol bölümüne ekler:

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

Tamsayıyı içermeyen yol şablonunu içeren sayfaya {id:int} yönelik bir istek HTTP 404 (bulunamadı) hatası döndürür. Örneğin, https://localhost:5001/Movies/Details 404 hatası döndürür. Kimliği isteğe bağlı hale getirmek için yol kısıtlamasına ekleyin ? :

@page "{id:int?}"

davranışını @page "{id:int?}"test edin:

  1. içindeki Pages/Movies/Details.cshtml page yönergesini olarak @page "{id:int?}"ayarlayın.
  2. içinde içinde public async Task<IActionResult> OnGetAsync(int? id)Pages/Movies/Details.cshtml.csbir kesme noktası ayarlayın.
  3. https://localhost:5001/Movies/Details/ sayfasına gidin.

yönergesi @page "{id:int}" ile kesme noktasına hiçbir zaman isabet olmaz. Yönlendirme altyapısı HTTP 404 döndürür. @page "{id:int?}"OnGetAsync yöntemi kullanılarak döndürülüyor 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();
}

Eşzamanlılık özel durum işlemesini gözden geçirme

Dosyasındaki OnPostAsync yöntemini Pages/Movies/Edit.cshtml.cs gözden geçirin:

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

Önceki kod, bir istemci filmi sildiğinde ve diğer istemci de değişiklikleri filme gönderdiğinde eşzamanlılık özel durumlarını algılar.

Bloğu test etmek catch için:

  1. üzerinde catch (DbUpdateConcurrencyException)bir kesme noktası ayarlayın.
  2. Film için Düzenle'yi seçin, değişiklik yapın, ancak Kaydet'e girmeyin.
  3. Başka bir tarayıcı penceresinde, aynı film için Sil bağlantısını seçin ve ardından filmi silin.
  4. Önceki tarayıcı penceresinde, değişiklikleri filme gönderin.

Üretim kodu eşzamanlılık çakışmalarını algılamak isteyebilir. Daha fazla bilgi için bkz. Eşzamanlılık çakışmalarını işleme .

Gönderme ve bağlama gözden geçirmesi

Pages/Movies/Edit.cshtml.cs Dosyayı inceleyin:

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

Filmler/Düzenle sayfasına bir HTTP GET isteği yapıldığında, örneğin: https://localhost:5001/Movies/Edit/3

  • OnGetAsync yöntemi, filmi veritabanından getirir ve yöntemini döndürürPage.
  • Page yöntemi Page'i Pages/Movies/Edit.cshtmlRazor işler. Pages/Movies/Edit.cshtml dosyası, film modelini sayfada kullanılabilir hale getiren model yönergesini @model RazorPagesMovie.Pages.Movies.EditModeliçerir.
  • Düzenle formu filmdeki değerlerle birlikte görüntülenir.

Filmler/Düzenle sayfası gönderildiğinde:

  • Sayfadaki form değerleri özelliğine Movie bağlıdır. [BindProperty] özniteliği Model bağlamayı etkinleştirir.

    [BindProperty]
    public Movie Movie { get; set; }
    
  • Örneğin model durumunda hatalar varsa, ReleaseDate tarihe dönüştürülemiyorsa form gönderilen değerlerle yeniden görüntülenir.

  • Model hatası yoksa film kaydedilir.

, Create ve Delete Razor sayfalarındaki IndexHTTP GET yöntemleri de benzer bir desen izler. Oluşturma Razor Sayfasındaki HTTP POST OnPostAsync yöntemi, Düzenleme Razor Sayfası'ndaki yönteme OnPostAsync benzer bir desen izler.

Ek kaynaklar