5. Bölüm, ASP.NET Core uygulamasında oluşturulan sayfaları güncelleştirme
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.
İ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.
Modeli güncelleştirme
Aşağıdaki vurgulanmış kodla güncelleştirin Models/Movie.cs
:
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 birimine doğru şekilde eşlenebirPrice
. Daha fazla bilgi için bkz . Veri Türleri. - [Display] özniteliği bir alanın görünen adını belirtir. Yukarıdaki kodda yerine
Release Date
ReleaseDate
. - [DataType] özniteliği verilerin türünü (
Date
) belirtir. Alanda depolanan zaman bilgileri görüntülenmez.
DataAnnotations , sonraki öğreticide ele alınmıştır.
Sayfalar/Filmler'e göz atın ve hedef URL'yi görmek için düzenle bağlantısının üzerine gelin.
Düzenle, Ayrıntılar ve Sil bağlantıları, dosyadaki Pages/Movies/Index.cshtml
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ı, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun katılmasını etkinleştirir.
Yukarıdaki kodda Yer Işareti Etiketi Yardımcısı, Html öznitelik değerini Sayfadan href
(yol görelidir), asp-page
ve 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=1
.https://localhost:5001/Movies/Details?id=1
Rota şablonu ekleme
Yol ş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 şablonu içeren {id:int}
sayfaya yapılan 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ı yapmak için yönlendirme kısıtlamasının sonuna ?
ekleyin:
@page "{id:int?}"
davranışını test edin @page "{id:int?}"
:
- içindeki
Pages/Movies/Details.cshtml
sayfa yönergesini olarak@page "{id:int?}"
ayarlayın. - içinde
Pages/Movies/Details.cshtml.cs
içindepublic async Task<IActionResult> OnGetAsync(int? id)
bir kesme noktası ayarlayın. - Şuraya gidin:
https://localhost:5001/Movies/Details/
yönergesi @page "{id:int}"
ile kesme noktası hiçbir zaman isabet etmez. Yönlendirme altyapısı HTTP 404 döndürür. OnGetAsync
kullanarak @page "{id:int?}"
yöntemi döndürü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();
}
Eşzamanlılık özel durum işlemesini gözden geçirme
Dosyasındaki OnPostAsync
Pages/Movies/Edit.cshtml.cs
yöntemini 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:
- üzerinde
catch (DbUpdateConcurrencyException)
bir kesme noktası ayarlayın. - Film için Düzenle'yi seçin, değişiklikler yapın, ancak Kaydet'e girmeyin.
- Başka bir tarayıcı penceresinde, aynı film için Sil bağlantısını seçin ve ardından filmi silin.
- Ö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.
Deftere nakil 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; } = 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);
}
Filmler/Düzenleme sayfasına bir HTTP GET isteği yapıldığında, örneğin: https://localhost:5001/Movies/Edit/3
- yöntemi,
OnGetAsync
filmi veritabanından getirir ve yöntemini döndürürPage
. Page
yöntemi SayfayıPages/Movies/Edit.cshtml
Razor işler. dosyasıPages/Movies/Edit.cshtml
, film modelini sayfada kullanılabilir hale getiren model yönergesini@model RazorPagesMovie.Pages.Movies.EditModel
içerir.- Düzenleme 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. özniteliği Model[BindProperty]
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.
Dizin, Oluşturma ve Silme Razor sayfalarındaki HTTP GET yöntemleri benzer bir deseni izler. Oluşturma Razor Sayfasındaki HTTP POST OnPostAsync
yöntemi, Düzenleme Sayfası'ndaki Razor yönteme OnPostAsync
benzer bir desen izler.
Sonraki adımlar
İ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.
Modeli güncelleştirme
Aşağıdaki vurgulanmış kodla güncelleştirin Models/Movie.cs
:
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 birimine doğru şekilde eşlenebirPrice
. Daha fazla bilgi için bkz . Veri Türleri. - [Display] özniteliği bir alanın görünen adını belirtir. Yukarıdaki kodda yerine
Release Date
ReleaseDate
. - [DataType] özniteliği verilerin türünü (
Date
) belirtir. Alanda depolanan zaman bilgileri görüntülenmez.
DataAnnotations , sonraki öğreticide ele alınmıştır.
Sayfalar/Filmler'e göz atın ve hedef URL'yi görmek için düzenle bağlantısının üzerine gelin.
Düzenle, Ayrıntılar ve Sil bağlantıları, dosyadaki Pages/Movies/Index.cshtml
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ı, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun katılmasını etkinleştirir.
Yukarıdaki kodda Yer Işareti Etiketi Yardımcısı, Html öznitelik değerini Sayfadan href
(yol görelidir), asp-page
ve 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=1
.https://localhost:5001/Movies/Details?id=1
Rota şablonu ekleme
Yol ş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 şablonu içeren {id:int}
sayfaya yapılan 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ı yapmak için yönlendirme kısıtlamasının sonuna ?
ekleyin:
@page "{id:int?}"
davranışını test edin @page "{id:int?}"
:
- içindeki
Pages/Movies/Details.cshtml
sayfa yönergesini olarak@page "{id:int?}"
ayarlayın. - içinde
Pages/Movies/Details.cshtml.cs
içindepublic async Task<IActionResult> OnGetAsync(int? id)
bir kesme noktası ayarlayın. - Şuraya gidin:
https://localhost:5001/Movies/Details/
yönergesi @page "{id:int}"
ile kesme noktası hiçbir zaman isabet etmez. Yönlendirme altyapısı HTTP 404 döndürür. OnGetAsync
kullanarak @page "{id:int?}"
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şlemesini gözden geçirme
Dosyasındaki OnPostAsync
Pages/Movies/Edit.cshtml.cs
yöntemini 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:
- üzerinde
catch (DbUpdateConcurrencyException)
bir kesme noktası ayarlayın. - Film için Düzenle'yi seçin, değişiklikler yapın, ancak Kaydet'e girmeyin.
- Başka bir tarayıcı penceresinde, aynı film için Sil bağlantısını seçin ve ardından filmi silin.
- Ö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.
Deftere nakil 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; } = 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);
}
Filmler/Düzenleme sayfasına bir HTTP GET isteği yapıldığında, örneğin: https://localhost:5001/Movies/Edit/3
- yöntemi,
OnGetAsync
filmi veritabanından getirir ve yöntemini döndürürPage
. Page
yöntemi SayfayıPages/Movies/Edit.cshtml
Razor işler. dosyasıPages/Movies/Edit.cshtml
, film modelini sayfada kullanılabilir hale getiren model yönergesini@model RazorPagesMovie.Pages.Movies.EditModel
içerir.- Düzenleme 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. özniteliği Model[BindProperty]
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.
Dizin, Oluşturma ve Silme Razor sayfalarındaki HTTP GET yöntemleri benzer bir deseni izler. Oluşturma Razor Sayfasındaki HTTP POST OnPostAsync
yöntemi, Düzenleme Sayfası'ndaki Razor yönteme OnPostAsync
benzer bir desen izler.
Sonraki adımlar
İ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.
Modeli güncelleştirme
Aşağıdaki vurgulanmış kodla güncelleştirin Models/Movie.cs
:
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 birimine doğru şekilde eşlenebirPrice
. Daha fazla bilgi için bkz . Veri Türleri. - [Display] özniteliği bir alanın görünen adını belirtir. Yukarıdaki kodda yerine
Release Date
ReleaseDate
. - [DataType] özniteliği verilerin türünü (
Date
) belirtir. Alanda depolanan zaman bilgileri görüntülenmez.
DataAnnotations , sonraki öğreticide ele alınmıştır.
Sayfalar/Filmler'e göz atın ve hedef URL'yi görmek için düzenle bağlantısının üzerine gelin.
Düzenle, Ayrıntılar ve Sil bağlantıları, dosyadaki Pages/Movies/Index.cshtml
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ı, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun katılmasını etkinleştirir.
Yukarıdaki kodda Yer Işareti Etiketi Yardımcısı, Html öznitelik değerini Sayfadan href
(yol görelidir), asp-page
ve 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=1
.https://localhost:5001/Movies/Details?id=1
Rota şablonu ekleme
Yol ş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 şablonu içeren {id:int}
sayfaya yapılan 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ı yapmak için yönlendirme kısıtlamasının sonuna ?
ekleyin:
@page "{id:int?}"
davranışını test edin @page "{id:int?}"
:
- içindeki
Pages/Movies/Details.cshtml
sayfa yönergesini olarak@page "{id:int?}"
ayarlayın. - içinde
Pages/Movies/Details.cshtml.cs
içindepublic async Task<IActionResult> OnGetAsync(int? id)
bir kesme noktası ayarlayın. - Şuraya gidin:
https://localhost:5001/Movies/Details/
yönergesi @page "{id:int}"
ile kesme noktası hiçbir zaman isabet etmez. Yönlendirme altyapısı HTTP 404 döndürür. OnGetAsync
kullanarak @page "{id:int?}"
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şlemesini gözden geçirme
Dosyasındaki OnPostAsync
Pages/Movies/Edit.cshtml.cs
yöntemini 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:
- üzerinde
catch (DbUpdateConcurrencyException)
bir kesme noktası ayarlayın. - Film için Düzenle'yi seçin, değişiklikler yapın, ancak Kaydet'e girmeyin.
- Başka bir tarayıcı penceresinde, aynı film için Sil bağlantısını seçin ve ardından filmi silin.
- Ö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.
Deftere nakil 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; } = 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);
}
Filmler/Düzenleme sayfasına bir HTTP GET isteği yapıldığında, örneğin: https://localhost:5001/Movies/Edit/3
- yöntemi,
OnGetAsync
filmi veritabanından getirir ve yöntemini döndürürPage
. Page
yöntemi SayfayıPages/Movies/Edit.cshtml
Razor işler. dosyasıPages/Movies/Edit.cshtml
, film modelini sayfada kullanılabilir hale getiren model yönergesini@model RazorPagesMovie.Pages.Movies.EditModel
içerir.- Düzenleme 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. özniteliği Model[BindProperty]
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.
Dizin, Oluşturma ve Silme Razor sayfalarındaki HTTP GET yöntemleri benzer bir deseni izler. Oluşturma Razor Sayfasındaki HTTP POST OnPostAsync
yöntemi, Düzenleme Sayfası'ndaki Razor yönteme OnPostAsync
benzer bir desen izler.
Sonraki adımlar
İ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.
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 birimine doğru şekilde eşlenebirPrice
. 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" (Sürüm Tarihi) ifadesi kullanılır.
- [DataType] özniteliği verilerin türünü (
Date
) belirtir. Alanda depolanan zaman bilgileri görüntülenmez.
DataAnnotations , sonraki öğreticide ele alınmıştır.
Sayfalar/Filmler'e göz atın ve hedef URL'yi görmek için düzenle bağlantısının üzerine gelin.
Düzenle, Ayrıntılar ve Sil bağlantıları, dosyadaki Pages/Movies/Index.cshtml
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ı, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun katılmasını etkinleştirir.
Yukarıdaki kodda Yer Işareti Etiketi Yardımcısı, Html öznitelik değerini Sayfadan href
(yol görelidir), asp-page
ve 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=1
.https://localhost:5001/Movies/Details?id=1
Rota şablonu ekleme
Yol ş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}
yapılan istekte HTTP 404 (bulunamadı) hatası döndürülecektir. Örneğin, https://localhost:5001/Movies/Details
bir 404 hatası döndürür. Kimliği isteğe bağlı yapmak için yönlendirme kısıtlamasının sonuna ?
ekleyin:
@page "{id:int?}"
davranışını test edin @page "{id:int?}"
:
- içindeki
Pages/Movies/Details.cshtml
sayfa yönergesini olarak@page "{id:int?}"
ayarlayın. - içinde
Pages/Movies/Details.cshtml.cs
içindepublic async Task<IActionResult> OnGetAsync(int? id)
bir kesme noktası ayarlayın. - Şuraya gidin:
https://localhost:5001/Movies/Details/
yönergesi @page "{id:int}"
ile kesme noktası hiçbir zaman isabet etmez. Yönlendirme altyapısı HTTP 404 döndürür. OnGetAsync
kullanarak @page "{id:int?}"
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şlemesini gözden geçirme
Dosyasındaki OnPostAsync
Pages/Movies/Edit.cshtml.cs
yöntemini 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)).GetValueOrDefault();
}
Ö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. Önceki kod, aynı filmi eşzamanlı olarak düzenleyen iki veya daha fazla istemci nedeniyle oluşan çakışmaları algılamaz. Bu durumda, birden çok istemci tarafından yapılan düzenlemeler çağrılan sırayla SaveChanges
uygulanır ve daha sonra uygulanan düzenlemeler eski değerlerle önceki düzenlemelerin üzerine yazabilir.
Bloğu test etmek catch
için:
- üzerinde
catch (DbUpdateConcurrencyException)
bir kesme noktası ayarlayın. - Film için Düzenle'yi seçin, değişiklikler yapın, ancak Kaydet'e girmeyin.
- Başka bir tarayıcı penceresinde, aynı film için Sil bağlantısını seçin ve ardından filmi silin.
- Önceki tarayıcı penceresinde, değişiklikleri filme gönderin.
Üretim kodu, bir varlığı aynı anda birden çok istemcinin düzenlemesi gibi ek 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.
Deftere nakil 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; } = 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();
}
Filmler/Düzenleme sayfasına bir HTTP GET isteği yapıldığında, örneğin: https://localhost:5001/Movies/Edit/3
- yöntemi,
OnGetAsync
filmi veritabanından getirir ve yöntemini döndürürPage
. Page
yöntemi SayfayıPages/Movies/Edit.cshtml
Razor işler. dosyasıPages/Movies/Edit.cshtml
, film modelini sayfada kullanılabilir hale getiren model yönergesini@model RazorPagesMovie.Pages.Movies.EditModel
içerir.- Düzenleme 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. özniteliği Model[BindProperty]
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.
Dizin, Oluşturma ve Silme Razor sayfalarındaki HTTP GET yöntemleri benzer bir deseni izler. Oluşturma Razor Sayfasındaki HTTP POST OnPostAsync
yöntemi, Düzenleme Sayfası'ndaki Razor yönteme OnPostAsync
benzer bir desen izler.
Sonraki adımlar
İ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.
Oluşturulan kodu güncelleştirme
Models/Movie.cs
Dosyayı 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:
- Veri
[Column(TypeName = "decimal(18, 2)")]
ek açıklaması, Entity Framework Core'un veritabanındaki para birimine doğru şekilde eşlenebirPrice
. 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" (Sürüm Tarihi) ifadesi kullanılır.
- [DataType] özniteliği verilerin türünü (
Date
) belirtir. Alanda depolanan zaman bilgileri görüntülenmez.
DataAnnotations , sonraki öğreticide ele alınmıştır.
Sayfalar/Filmler'e göz atın ve hedef URL'yi görmek için düzenle bağlantısının üzerine gelin.
Düzenle, Ayrıntılar ve Sil bağlantıları, dosyadaki Pages/Movies/Index.cshtml
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ı, Razor dosyalarında HTML öğelerinin oluşturulmasına ve işlenmesine sunucu tarafı kodun katılmasını etkinleştirir.
Yukarıdaki kodda Yer Işareti Etiketi Yardımcısı, Html öznitelik değerini Sayfadan href
(yol görelidir), asp-page
ve 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=1
.https://localhost:5001/Movies/Details?id=1
Rota şablonu ekleme
Yol ş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}
yapılan istekte HTTP 404 (bulunamadı) hatası döndürülecektir. Örneğin, https://localhost:5001/Movies/Details
bir 404 hatası döndürür. Kimliği isteğe bağlı yapmak için yönlendirme kısıtlamasının sonuna ?
ekleyin:
@page "{id:int?}"
davranışını test edin @page "{id:int?}"
:
- içindeki
Pages/Movies/Details.cshtml
sayfa yönergesini olarak@page "{id:int?}"
ayarlayın. - içinde
Pages/Movies/Details.cshtml.cs
içindepublic async Task<IActionResult> OnGetAsync(int? id)
bir kesme noktası ayarlayın. - Şuraya gidin:
https://localhost:5001/Movies/Details/
yönergesi @page "{id:int}"
ile kesme noktası hiçbir zaman isabet etmez. Yönlendirme altyapısı HTTP 404 döndürür. OnGetAsync
kullanarak @page "{id:int?}"
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şlemesini gözden geçirme
Dosyasındaki OnPostAsync
Pages/Movies/Edit.cshtml.cs
yöntemini 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:
- üzerinde
catch (DbUpdateConcurrencyException)
bir kesme noktası ayarlayın. - Film için Düzenle'yi seçin, değişiklikler yapın, ancak Kaydet'e girmeyin.
- Başka bir tarayıcı penceresinde, aynı film için Sil bağlantısını seçin ve ardından filmi silin.
- Ö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.
Deftere nakil 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
- yöntemi,
OnGetAsync
filmi veritabanından getirir ve yöntemini döndürürPage
. Page
yöntemi SayfayıPages/Movies/Edit.cshtml
Razor işler. dosyasıPages/Movies/Edit.cshtml
, film modelini sayfada kullanılabilir hale getiren model yönergesini@model RazorPagesMovie.Pages.Movies.EditModel
içerir.- Düzenleme 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. özniteliği Model[BindProperty]
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.
Dizin, Oluşturma ve Silme Razor sayfalarındaki HTTP GET yöntemleri benzer bir deseni izler. Oluşturma Razor Sayfasındaki HTTP POST OnPostAsync
yöntemi, Düzenleme Sayfası'ndaki Razor yönteme OnPostAsync
benzer bir desen izler.
Sonraki adımlar
ASP.NET Core