مقدمه

در درس‌های گذشته، زیرساخت‌های لازم را فراهم کردیم: مدل داده‌ی Movie و WebAppDbContext را ساختیم و آن‌ها را در سیستم تزریق وابستگی ASP.NET Core ثبت کردیم. همچنین با ساختار پایه‌ای Razor Pages و نحوه‌ی نمایش داده‌ها در یک صفحه آشنا شدیم. اکنون زمان آن است که این دو بخش را به هم متصل کرده و یک اپلیکیشن وب کامل با قابلیت‌های CRUD (Create, Read, Update, Delete) بسازیم.

در این درس، با استفاده از ابزارهای Scaffolding (داربست‌زنی) در ویژوال استودیو، به صورت خودکار صفحات Razor لازم برای تمام عملیات CRUD بر روی موجودیت Movie را تولید خواهیم کرد. سپس کد تولید شده را بررسی می‌کنیم تا ببینیم EF Core و ASP.NET Core چگونه با هم کار می‌کنند تا این قابلیت‌ها را پیاده‌سازی کنند.

استفاده از Scaffolding برای تولید صفحات CRUD

ASP.NET Core شامل یک ابزار قدرتمند به نام Scaffolding است که می‌تواند بر اساس یک مدل موجودیت و DbContext، به صورت خودکار کد لازم برای صفحات وب (یا کنترلرهای API) را تولید کند. این کار فرآیند توسعه را به شدت سرعت می‌بخشد.

برای تولید صفحات CRUD برای موجودیت Movie:

  1. در Solution Explorer، روی پوشه‌ی Pages راست‌کلیک کرده و گزینه‌ی AddNew Scaffolded Item... را انتخاب کنید.
  2. در پنجره‌ی باز شده، Razor Pages using Entity Framework (CRUD) را انتخاب کرده و دکمه‌ی Add را بزنید.
  3. در پنجره‌ی بعدی:
    • از منوی بازشوی Model class، کلاس Movie را انتخاب کنید.
    • از منوی بازشوی Data context class، کلاس WebAppDbContext را انتخاب کنید.
    • سایر گزینه‌ها را به صورت پیش‌فرض رها کرده و روی Add کلیک کنید.

ویژوال استودیو اکنون به طور خودکار یک پوشه‌ی جدید به نام Movies در داخل پوشه‌ی Pages ایجاد کرده و چهار صفحه‌ی Razor کامل را در آن قرار می‌دهد: Create.cshtml، Details.cshtml، Edit.cshtml و Delete.cshtml به همراه فایل‌های code-behind مربوط به آن‌ها. همچنین صفحه‌ی Index.cshtml را نیز برای نمایش لیست فیلم‌ها می‌سازد.

بررسی کدهای تولید شده

بیایید منطق پشت صحنه‌ی دو مورد از مهم‌ترین این صفحات یعنی Create و Edit را بررسی کنیم.

صفحه‌ی Create (ایجاد)

این صفحه شامل یک فرم برای وارد کردن اطلاعات یک فیلم جدید است.

Copy Icon Create.cshtml.cs (Simplified)
public class CreateModel : PageModel
{
    private readonly WebAppDbContext _context;
    public CreateModel(WebAppDbContext context) { _context = context; }

    // This property will be bound to the form fields.
    [BindProperty]
    public Movie Movie { get; set; }

    public IActionResult OnGet()
    {
        return Page();
    }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Movie.Add(Movie);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

نکات کلیدی:

  • [BindProperty]: این صفت به ASP.NET Core می‌گوید که هنگام دریافت یک درخواست POST، داده‌های فرم را به پراپرتی Movie متصل (bind) کند.
  • OnGet: این هندلر بسیار ساده است و فقط صفحه‌ی خالی را برای نمایش فرم برمی‌گرداند.
  • OnPostAsync: این هندلر پس از ارسال فرم اجرا می‌شود. ابتدا با ModelState.IsValid اعتبار داده‌های ورودی را بررسی می‌کند. اگر معتبر بود، شیء Movie را به DbContext اضافه کرده، با SaveChangesAsync آن را در پایگاه داده ذخیره می‌کند و در نهایت، کاربر را به صفحه‌ی اصلی لیست فیلم‌ها (./Index) هدایت می‌کند.

صفحه‌ی Edit (ویرایش)

این صفحه به ما اجازه می‌دهد تا اطلاعات یک فیلم موجود را ویرایش کنیم.

Copy Icon Edit.cshtml.cs (Simplified)
public class EditModel : PageModel
{
    private readonly WebAppDbContext _context;
    public EditModel(WebAppDbContext context) { _context = context; }

    [BindProperty]
    public Movie Movie { get; set; }

    public async Task<IActionResult> OnGetAsync(int? id)
    {
        Movie = await _context.Movie.FirstOrDefaultAsync(m => m.Id == id);
        if (Movie == null) return NotFound();
        return Page();
    }

    public async Task<IActionResult> OnPostAsync()
    {
        _context.Attach(Movie).State = EntityState.Modified;
        await _context.SaveChangesAsync();
        return RedirectToPage("./Index");
    }
}

نکات کلیدی:

  • OnGetAsync: این هندلر یک id را از آدرس URL دریافت کرده، فیلم مربوطه را از پایگاه داده پیدا می‌کند و آن را برای نمایش در فرم، به پراپرتی Movie اختصاص می‌دهد.
  • OnPostAsync: پس از ارسال فرم، این هندلر شیء Movie را که با داده‌های فرم پر شده، دریافت می‌کند. خط _context.Attach(Movie).State = EntityState.Modified به ردیاب تغییرات EF Core می‌گوید که "این یک شیء موجود است که تغییر کرده" و باید برای آن یک دستور UPDATE تولید شود. سپس با SaveChangesAsync تغییرات ذخیره می‌شوند.