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

Gönderen Rick Anderson

Yapı iskelesi film uygulamasının iyi bir başlangıcı vardır ancak sunum ideal değildir. ReleaseDate iki sözcük, Yayın tarihi olmalıdır.

Chrome 'da açık film uygulaması

Oluşturulan kodu Güncelleştir

Modelleri/filmi. cs 'yi aşağıdaki vurgulanmış kodla güncelleştirin:

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:

  • [Column(TypeName = "decimal(18, 2)")]Veri ek açıklaması, Entity Framework Core veritabanındaki para birimiyle doğru şekilde eşlenmesine olanak sağlar Price . 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 "Yayın tarihi".
  • [DataType] özniteliği, veri türünü belirtir ( Date ). Alanda depolanan zaman bilgileri gösterilmez.

Veri açıklamaları sonraki öğreticide ele alınmıştır.

Hedef URL 'yi görmek için sayfalara/filmlere gidin ve bir düzenleme bağlantısının üzerine gelin.

Düzenleme bağlantısı üzerinde fare ile tarayıcı penceresi ve bağlantı URL 'Si https://localhost:1234/Movies/Edit/5 gösteriliyor

Düzenle, Ayrıntılar ve Sil bağlantıları, Sayfalar/filmler/ Index . cshtml dosyasındaki tutturucu etiketi 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ı kodun dosyalarda HTML öğeleri oluşturma ve işlemeye katılmasını sağlar Razor .

Yukarıdaki kodda, tutturucu etiketi Yardımcısı , sayfada HTML öznitelik değerini dinamik olarak oluşturur href Razor (yol göreli olur),, asp-page ve yol tanımlayıcısı ( asp-route-id ). Daha fazla bilgi için bkz. Sayfalar Için URL oluşturma.

Oluşturulan biçimlendirmeyi incelemek için bir tarayıcıdan Görünüm kaynağı ' nı 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 iletir. Örneğin, ?id=1 içinde https://localhost:5001/Movies/Details?id=1 .

Rota şablonu Ekle

RazorYol şablonunu kullanmak Için düzenleme, Ayrıntılar ve silme sayfalarını güncelleştirin {id:int} . Bu sayfaların her biri için Page yönergesini ' den ' @page e değiştirin @page "{id:int}" . Uygulamayı çalıştırın ve kaynağı görüntüleyin.

Oluşturulan HTML, URL 'nin yol bölümüne KIMLIĞI 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ı içermeyen yol şablonuna sahip sayfaya yönelik bir istek, {id:int} HTTP 404 (bulunamadı) hatası döndürür. Örneğin, https://localhost:5001/Movies/Details bir 404 hatası döndürür. KIMLIĞI isteğe bağlı yapmak için ? yol kısıtlamasına ekleyin:

@page "{id:int?}"

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

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

@page "{id:int}"Yönergeyle, kesme noktası hiçbir şekilde vurılmaz. Yönlendirme Altyapısı HTTP 404 döndürür. Kullanarak @page "{id:int?}" , OnGetAsync yöntemi döndürü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();
}

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

OnPostAsync Pages/filmler/Edit. cshtml. cs dosyasındaki yöntemi 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 filmle değişiklik yaptığı zaman eşzamanlılık özel durumlarını algılar.

Bloğu test etmek için catch :

  1. Üzerinde bir kesme noktası ayarlayın catch (DbUpdateConcurrencyException) .
  2. Film için Düzenle ' yi seçin, değişiklikler yapın, ancak Kaydet' i girmeyin.
  3. Başka bir tarayıcı penceresinde, aynı filmin Sil bağlantısını seçin ve ardından filmi silin.
  4. Önceki tarayıcı penceresinde filmdeki değişiklikleri 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 incelemesi

Pages/filmler/Edit. cshtml. cs dosyasını 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 HTTP GET isteği yapıldığında, örneğin https://localhost:5001/Movies/Edit/3 :

  • OnGetAsyncYöntemi, filmi veritabanından getirir ve Page yöntemi döndürür.
  • PageYöntemi Sayfalar/filmler/Edit. cshtml Razor sayfasını işler. Pages/filmler/Edit. cshtml dosyası model yönergesini içerir @model RazorPagesMovie.Pages.Movies.EditModel , bu da film modelini sayfada kullanılabilir hale getirir.
  • Düzenleme formu filmdeki değerlerle birlikte görüntülenir.

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

  • Sayfadaki form değerleri Movie özelliğine bağlıdır. [BindProperty]Öznitelik, model bağlamayımümkün bir şekilde sunar.

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

  • Model hatası yoksa, film kaydedilir.

IndexSayfalarında, oluşturma ve silme gıbı http get yöntemleri Razor benzer bir düzene sahiptir. OnPostAsyncOluşturma SAYFASıNDAKI http post yöntemi, Razor OnPostAsync düzenleme sayfasındaki yöntemine benzer bir düzen izler Razor .

Ek kaynaklar

Yapı iskelesi film uygulamasının iyi bir başlangıcı vardır ancak sunum ideal değildir. ReleaseDate iki sözcük, Yayın tarihi olmalıdır.

Chrome 'da açık film uygulaması

Oluşturulan kodu Güncelleştir

Modeller/film. cs dosyasını açın ve aşağıdaki kodda gösterilen vurgulanmış 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:

  • [Column(TypeName = "decimal(18, 2)")]Veri ek açıklaması, Entity Framework Core veritabanındaki para birimiyle doğru şekilde eşlenmesine olanak sağlar Price . 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 "Yayın tarihi".
  • [DataType] özniteliği, veri türünü belirtir ( Date ). Alanda depolanan zaman bilgileri gösterilmez.

Veri açıklamaları sonraki öğreticide ele alınmıştır.

Hedef URL 'yi görmek için sayfalara/filmlere gidin ve bir düzenleme bağlantısının üzerine gelin.

Düzenleme bağlantısı üzerinde fare ile tarayıcı penceresi ve bağlantı URL 'Si https://localhost:1234/Movies/Edit/5 gösteriliyor

Düzenle, Ayrıntılar ve Sil bağlantıları, Sayfalar/filmler/ Index . cshtml dosyasındaki tutturucu etiketi 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ı kodun dosyalarda HTML öğeleri oluşturma ve işlemeye katılmasını sağlar Razor .

Yukarıdaki kodda, tutturucu etiketi Yardımcısı , sayfada HTML öznitelik değerini dinamik olarak oluşturur href Razor (yol göreli olur),, asp-page ve yol tanımlayıcısı ( asp-route-id ). Daha fazla bilgi için bkz. Sayfalar Için URL oluşturma.

Oluşturulan biçimlendirmeyi incelemek için bir tarayıcıdan Görünüm kaynağı ' nı 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 iletir. Örneğin, ?id=1 içinde https://localhost:5001/Movies/Details?id=1 .

Rota şablonu Ekle

RazorYol şablonunu kullanmak Için düzenleme, Ayrıntılar ve silme sayfalarını güncelleştirin {id:int} . Bu sayfaların her biri için Page yönergesini ' den ' @page e değiştirin @page "{id:int}" . Uygulamayı çalıştırın ve kaynağı görüntüleyin.

Oluşturulan HTML, URL 'nin yol bölümüne KIMLIĞI 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ı içermeyen yol şablonuna sahip sayfaya yönelik bir istek, {id:int} HTTP 404 (bulunamadı) hatası döndürür. Örneğin, https://localhost:5001/Movies/Details bir 404 hatası döndürür. KIMLIĞI isteğe bağlı yapmak için ? yol kısıtlamasına ekleyin:

@page "{id:int?}"

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

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

@page "{id:int}"Yönergeyle, kesme noktası hiçbir şekilde vurılmaz. Yönlendirme Altyapısı HTTP 404 döndürür. Kullanarak @page "{id:int?}" , OnGetAsync yöntemi döndürü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();
}

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

OnPostAsync Pages/filmler/Edit. cshtml. cs dosyasındaki yöntemi 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 filmle değişiklik yaptığı zaman eşzamanlılık özel durumlarını algılar.

Bloğu test etmek için catch :

  1. Üzerinde bir kesme noktası ayarlayın catch (DbUpdateConcurrencyException) .
  2. Film için Düzenle ' yi seçin, değişiklikler yapın, ancak Kaydet' i girmeyin.
  3. Başka bir tarayıcı penceresinde, aynı filmin Sil bağlantısını seçin ve ardından filmi silin.
  4. Önceki tarayıcı penceresinde filmdeki değişiklikleri 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 incelemesi

Pages/filmler/Edit. cshtml. cs dosyasını 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 HTTP GET isteği yapıldığında, örneğin https://localhost:5001/Movies/Edit/3 :

  • OnGetAsyncYöntemi, filmi veritabanından getirir ve Page yöntemi döndürür.
  • PageYöntemi Sayfalar/filmler/Edit. cshtml Razor sayfasını işler. Pages/filmler/Edit. cshtml dosyası model yönergesini içerir @model RazorPagesMovie.Pages.Movies.EditModel , bu da film modelini sayfada kullanılabilir hale getirir.
  • Düzenleme formu filmdeki değerlerle birlikte görüntülenir.

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

  • Sayfadaki form değerleri Movie özelliğine bağlıdır. [BindProperty]Öznitelik, model bağlamayımümkün bir şekilde sunar.

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

  • Model hatası yoksa, film kaydedilir.

IndexSayfalarında, oluşturma ve silme gıbı http get yöntemleri Razor benzer bir düzene sahiptir. OnPostAsyncOluşturma SAYFASıNDAKI http post yöntemi, Razor OnPostAsync düzenleme sayfasındaki yöntemine benzer bir düzen izler Razor .

Ek kaynaklar