Skip to content

Проєкт із використанням Razor Pages (CRUD операції)

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (3 оценок, среднее: 5,00 из 5)
Завантаження...

[ Полезный рекламный блок ]

Попробуйте свои силы в игре, где ваши навыки программирования на C# станут решающим фактором. Переходите по ссылке 🔰.


У цьому уроці ми створимо CRUD-операції в ASP.NET Core Razor Pages, використовуючи патерн Repository. Додаток буде виконано в ASP.NET Core Razor Pages, а на рівні доступу до даних використовуватиметься Entity Framework Core «ORM».

Щоб створити проєкт RazorCrud, запустіть Visual Studio і виберіть у меню File (Файл) – New Project (Створити Проєкт). Вкажіть шаблон проєкту ASP.NET Core Web App (Razor Pages). Введіть RazorCrud, у полі Name, на наступній сторінці вкажіть Framework .Net 8.0 і натисніть кнопку Create:

razor pages проект

Модель і Entity Framework Core

Entity Framework Core – це ORM, який ми будемо використовувати для зв’язку з базою даних і виконання CRUD-операцій. Наш репозиторій буде звертатися до Entity Framework Core, щоб можна було виконувати ці операції з базою даних.

Для взаємодії з MS SQL Server і виконання міграцій через EF Core, додамо в проєкт через Nuget пакети:

Install-Package Microsoft.EntityFrameworkCore.SqlServer

Install-Package Microsoft.EntityFrameworkCore.Tools

Далі нам потрібно створити сутність, яка буде являти собою клас Assignment.cs. Ви повинні створити цей клас у папці Models. Тому спочатку створіть папку «Models» у корені додатка, а потім усередині неї створіть клас Assignment, з таким вмістом:

Для зберігання зображення в папці wwwroot створимо папку assignmentImages.

Створення класу контексту даних

У забезпеченні доступу до даних у БД інфраструктура Entity Framework Core покладається на клас контексту БД. Щоб забезпечити приклад додатка контекстом, додайте в папку Data файл класу на ім’я ApplicationContext.cs з таким кодом:

Коли інфраструктура Entity Framework Core використовується для збереження простої моделі даних на кшталт тієї, що визначена в додатку RazorCrud. Клас контексту БД відповідно простий – хоча ситуація зміниться зі зростанням складності моделі даних у наступних розділах.

Перейдемо у файл appsettings.json і пропишемо конфігурацію підключення та логування:

Рядки підключення визначаються у файлі appsettings.json, у коді вище наведено визначення рядка підключення для БД додатка RazorCrud. У проєкті застосовується версія LocalDB продукту SQL Server, яка спроєктована спеціально для розробників і не вимагає конфігурації або облікових даних.

Ви зобов’язані забезпечити, щоб рядок підключення був єдиним нерозривним рядком. Формат рядка підключення специфічний для кожного сервера баз даних.

Далі нам потрібно зареєструвати ApplicationContext у файлі Program.cs. Додамо наступний виділений рядок, який зареєструє наш контекст бази даних:

Отже, давайте виконаємо міграцію. Перейдемо в ІнструментиМенеджер пакетів NuGet ➤ Консоль менеджера пакетів і послідовно виконаємо такі команди:

PM> Add-Migration Initial

PM> Update-Database

Після завершення виконання команд міграції в додатку буде створено папку Migrations. Ця папка містить новостворені файли, які використовувалися для створення бази даних.

Далі перейдіть у меню View SQL Server Object Explorer, де знайдемо базу даних razorCrudDb. Ця база даних була створена, коли ми запускали міграцію. Ця база даних містить лише одну таблицю під назвою Assignments, яка відповідає сутності Assignment, створеній у нашому додатку ASP.NET Core Razor Pages.

Створення репозиторію

Паттерн репозиторій потребує двох речей:

  • Інтерфейс
  • Клас, який буде реалізовувати/успадковувати інтерфейс.

Інтерфейс міститиме всі методи, які працюватимуть із базою даних, наприклад CRUD. Зазвичай це методи для створення, читання, оновлення та видалення записів у базі даних. Іноді у нас буде ще кілька методів для фільтрації записів. Ми розглянемо їх пізніше.

Щоб створити інтерфейс сховища, створимо папку Interfaces і додамо в неї файл інтерфейсу на ім’я IRepository з таким вмістом:

IRepository<T> це загальний тип, у якому T обмежений як клас. Це означає, що T має бути посилальним типом, таким як клас, інтерфейс, делегат або масив.

Створимо папку Repository і додамо в неї файл класу на ім’я Repository.cs з таким вмістом:

Нарешті, нам потрібно зареєструвати інтерфейс для його реалізації в Program.cs. Код, який необхідно додати, показано нижче:

Наведений вище код вказує ASP.NET Core на створення нового екземпляра Repository щоразу, коли присутня залежність IRepository. Typeof вказує, що тип може бути будь-яким, наприклад Movie, Teacher, Employee тощо.

Чудово, ми щойно завершили створення нашого шаблону Generic Repository. Залишилося тільки створити CRUD-операції в Razor Pages.

CRUD-операції з використанням патерну репозиторію

На деяких сторінках, ми будемо використовувати окремі стилі та скрипти. Якщо перейти у файл Views / Shared / _Layout.cshtml, можна побачити певну секцію для скриптів:

Давайте так само, визначимо подібну секцію, для стилів, вгорі сторінки:

У кореневій папці програми є папка Pages. Нам потрібно створити нову сторінку Razor Page у цій папці Pages і назвати її Create.cshtml.

Для цього клацніть правою кнопкою миші папку Pages і виберіть Add ➤ New Item. Далі у вікні Add New Item вибериv Razor Page – Empty template і назвемо його Create.cshtml.

Визначимо у файлі Create.cshtml, наступний код:

Сторінка містить як код razor, так і код C#. Верхня частина містить код razor, а коди C# розміщені в тілі функцій. Застосовуваний @page у верхній частині вказує на те, що це Razor-сторінка і вона може обробляти http-запити.

Тепер запустимо проєкт і відкриємо цю сторінку в браузері за її назвою, тобто url цієї сторінки буде – https://localhost:44329/Create. Порт localhost для вас буде іншим:

CRUD-операции razor pages

Прив’язка вхідних елементів до моделі здійснюється за допомогою помічника тега asp-for:

Помічники тегів дають змогу коду на стороні сервера створювати та відображати HTML-елементи. Помічник тегів asp-for додає 4 html-атрибути до елементів введення. Ви можете побачити ці атрибути, «проінспектувавши» їх у браузері.

Я також додав div перед формою на сторінці razor. Цей div показуватиме всі помилки валідації разом. Це робиться шляхом додавання тега-помічника asp-validation-summary=«All» у div.

Для роботи з календарем на сторінку так само додаються необхідні стилі та скрипти від Bootstrap. У секції Scripts, таким чином, окремий блок скриптів ініціалізує віджет вибору дати для елемента з ідентифікатором datepicker і встановлює поточну дату як обрану.

На сторінках razor є методи-обробники, які автоматично виконуються в результаті http-запиту. Існує 2 методи-обробники – OnGet і OnPostAsync.

Метод «OnGet» буде викликаний при http-запиті типу get на Create Razor Page, а «OnPostAsync», що є асинхронною версією OnPost, буде викликаний при http-запиті типу post на Create Razor Page.

Обробник OnGet() просто повертає сторінку razor. Обробник OnPostAsync(), через атрибут [FromServices], отримує залежність IWebHostEnvironment, яка надає доступ до шляхів до кореневої папки застосунку, папок, які містять статичні ресурси, а також шляхів до каталогів, які містять логи, конфігураційні файли та інші ресурси.

Далі перевіряє, чи дійсно стан моделі, перевіряє, чи є файл, і зберігає його в раніше створену нами папку.

Потім він викликає метод CreateAsync сховища. Цей метод CreateAsync надається разом з об’єктом задачі, щоб вона була додана в базу даних.

Не забуваємо, що ми можемо використовувати спочатку валідацію на стороні клієнта, через JavaScript. Для цього, в секцію Scripts, завантажимо часткове подання:

Тепер створимо функціональність для отримання завдань. Отже, нам потрібно додати новий метод у наше сховище, який виконуватиме завдання читання. Перейдемо в інтерфейс IRepository і додайте метод ReadAllAsync, як показано нижче:

Метод ReadAllAsync повертає список типів T асинхронно. Далі нам необхідно реалізувати цей метод у класі «Repository.cs». Код показано нижче у виділеному вигляді:

Метод використовує метод Set для створення об’єкта Microsoft.EntityFrameworkCore.DbSet для запиту сутності з бази даних. У загальному випадку він зчитуватиме сутність «T» з бази даних, а потім ми перетворимо її на список за допомогою методу ToListAsync().

Тепер створимо нову сторінку Razor Page у папці «Pages» з ім’ям Read.cshtml і додамо в неї такий код:

Код цієї сторінки Razor Page доволі простий, спочатку я створив посилання на сторінку Razor Page «Create» за допомогою тега-помічника asp-page.

Далі у нас є HTML-таблиця, яка містить 3 стовпці для 3 полів сутності Assignment. У таблиці відображатимуться всі завдання, які наразі зберігаються в базі даних. У блоці функцій визначено властивість List<Assignment>, яка надається зі списком завдань методом OnGet().

Оскільки сторінка читання створена, ми повинні перенаправляти користувача на сторінку читання, коли створюється новий запис.

Перейдемо на сторінку Create.cshtml і змінимо останній рядок обробника OnPostAsync так, щоб він перенаправляв користувача на сторінку читання:

Перенаправлення здійснюється методом RedirectToPage(Read). Подивимося на зміни, які показані виділеним способом.

Пагінація

При додаванні більшої кількості записів, ми втратимо зручність роботи з ними. Це також призведе до такої проблеми, як уповільнення роботи сторінки.

Щоб вирішити цю проблему, ми створимо функцію Pagination. Отже, у папці Models, створимо нову папку Paging у корені додатка. У цю папку додамо 3 класи, а саме:

PagingInfo.cs – відстежує загальну кількість записів, поточну сторінку, елементи на сторінці та загальну кількість сторінок.

AssignmentList.cs – містить список записів поточної сторінки та PagingInfo.

PageLinkTagHelper.cs – це тег-помічник, який буде створювати посилання пейджинга всередині div.

Відкриємо клас PagingInfo.cs і визначимо такий вміст:

Відкриємо клас AssignmentList.cs і визначимо такий вміст:

Відкриємо клас PageLinkTagHelper.cs і визначимо такий вміст:

PageLinkTagHelper виконує основну роботу зі створення посилань пагінації. Давайте розглянемо, як він працює.

Помічники тегів повинні успадковувати клас TagHelper і перевизначати функцію Process. Функція process – це місце, де ми пишемо наш код помічника тега. У нашому випадку ми створимо якірні теги для посилань на сторінку і покажемо їх усередині div.

Клас-помічник тега застосовується з атрибутом HtmlTargetElement, який вказує, що він застосовуватиметься до будь-якого div, що має атрибут page-model:

Клас-помічник тега визначає низку властивостей, які отримуватимуть значення від Razor Page. Цими властивостями є PageModel, PageName, PageClassesEnabled, PageClass і PageClassSelected.

Є ще одна властивість типу ViewContext, яка пов’язується з даними контексту подання, що включають дані маршрутизації, ViewData, ViewBag, TempData, ModelState, поточний HTTP-запит тощо.

Використання атрибута [HtmlAttributeNotBound] в основному говорить про те, що цей атрибут не є тим, який ви збираєтеся встановити за допомогою допоміжного атрибута тега на сторінці razor.

Помічник тегів отримує об’єкт IUrlHelperFactory з функції ін’єкції залежностей і використовує його для створення тегів якорів сторінок. Існує також функція AnchorInnerHtml, яка займається створенням тексту для посилань на сторінку.

Наступне, що нам потрібно зробити, це зробити цей тег-помічник доступним для сторінок razor, що ми можемо зробити, додавши наведений нижче рядок коду в файл _ViewImports.cshtml:

Директива @addTagHelper робить помічники тегів доступними для сторінки Razor. Перший параметр після @addTagHelper вказує, які помічники тегів потрібно завантажити, я використовував синтаксис підстановки («*») у MovieCrud.Paging.*, тож це означає, що потрібно завантажити всі помічники тегів, які мають простір імен MovieCrud.Paging або будь-який простір імен, який починається з MovieCrud.Paging.

А другий параметр «RazorCrud» вказує збірку, що містить помічники тегів. Це ім’я програми.

Тепер нам потрібно інтегрувати цей тег-помічник на сторінку Read Razor Page. Тому спочатку нам потрібно додати новий метод у наш репозиторій. Додамо метод ReadAllFilterAsync в інтерфейс IRepository:

Цей метод повертає кортеж типу List<T> і int. Очевидно, це означає, що він поверне список записів поточної сторінки і загальну кількість записів у базі даних. Крім того, він приймає 2 параметри – skip і take, які допомагають нам побудувати логіку для отримання тільки записів поточної сторінки.

Потім додамо реалізацію цього методу в клас Repository.cs, як показано нижче:

Бачите, що тепер ми отримуємо тільки записи поточної сторінки за допомогою методів Linq Skip і Take. Потім повертаємо записи разом із кількістю всіх записів у кортежі.

Нарешті, перейдемо до файлу Read.cshtml і внесемо такі зміни:

Для визначення стилів пагінації перейдемо до папки wwwroot/css/site.css і визначимо такі стилі:

Давайте розберемося в цих змінах по порядку. Зверху в директиву сторінки додається id маршруту:

Це робиться тому, що номер сторінки буде вказано в url як останній сегмент, наприклад:

Наведений вище тип маршрутизації створюється ASP.NET Core за замовчуванням. Наступна зміна – додавання властивості AssignmentList у блок функцій:

Ця властивість потім використовується в циклі foreach, який створює рядки таблиці із записів. Model.AssignmentList.Assignments буде містити список доручень.

Після цього я додав div, що містить атрибут page-model, і тому помічник тегів перетворює цей div на посилання пагінації.

У класі-помічнику тегів у мене є властивість PageOtherValues, визначена як тип словника:

Ця властивість отримує значення в типі Dictionary з атрибутів, що починаються з «page-other-». Прикладами таких атрибутів можуть бути:

Значення цих атрибутів будуть додані в рядок запиту url. Цю роботу виконує функція AddDictionaryToQueryString, визначена в класі. Хоча я не використовував її, вона може бути корисною, якщо ви хочете додати більше можливостей у клас-помічник тегів.

Переходимо до обробника OnGet, який тепер отримує як параметр значення номера сторінки. Нагадаємо, що деякий час тому ми додали його в директиву page.

Я встановив розмір сторінки рівним 3, який ви можете змінити на свій розсуд.

Поточна сторінка та елементи на сторінці додаються в об’єкт класу PagingInfo. Також обчислюється значення початкового запису для сторінки і додається в змінну skip:

Далі ми викликаємо метод ReadAllFilterAsync зі значенням skip і кількістю записів для вибірки (тобто pagesize).

Метод повертає кортеж, значення якого витягують і передають у TotalItems з pagingInfo і Assignment з AssignmentList.Assignments:

Нарешті, ми присвоюємо властивості pagingInfo об’єкта AssignmentList значення pagingInfo:

Давайте додамо кілька записів і перевіримо роботу пагінації:

пагинация razor pages

Шановні ентузіасти програмування на C#!

Ми розуміємо, що іноді ви можете зіткнутися з труднощами під час вирішення проблем під час роботи над своїми проектами на C#. Якщо у вас виникли проблеми, пов’язані з мовою програмування C#, ми готові вам допомогти!
https://dijix.com.ua/blog помощь
Ви можете зв’язатися з нами електронною поштою або зателефонувати нам по телефону. Наша команда досвідчених розробників C# буде рада допомогти вам із будь-якими питаннями чи проблемами, які у вас можуть виникнути. Ми прагнемо допомогти вам подолати будь-які перешкоди, з якими ви зіткнетеся на шляху освоєння C#.
Не соромтеся звертатися до нас за будь-якою допомогою або керівництвом. Ми завжди готові підтримати вас у ваших починаннях.

З найкращими побажаннями,
[Леонід/ Dijix Company]

info@dijix.com.ua
+380970601478

Доопрацювання інших Crud операцій

Перейдемо до функції Update, як і раніше, додамо новий методи ReadAsync і UpdateAsync в інтерфейс IRepository:

Також реалізуємо ці методи в класі Repository.cs:

У вищенаведеному методі ReadAsync, використовується метод FindAsync() з Entity Framework Core і передається id сутності, яку потрібно прочитати з бази даних. Метод UpdateAsync оновлює сутність у базі даних.

Після цього нам потрібно створити нову сторінку Razor Page під назвою Update.cshtml у папці «Pages». Потім додамо в неї наступний код:

Код сторінки «Update» дуже схожий на код сторінки «Update», тільки з деякими змінами:

В обробнику OnGet() викликається сховище для отримання доручення, чий id обробник отримав як параметр. Ідентифікатор доручення буде відправлено в Update як параметр рядка запиту. Я показав такі посилання нижче:

https://localhost:7182/Update?id=1

https://localhost:7182/Update?id=10

https://localhost:7182/Update?id=100

Обробник OnGet має в параметрі (int id), і функція прив’язки моделі автоматично зв’яже цей параметр id зі значенням id, зазначеним у рядку запиту.

Далі, отримуємо запис через метод репозиторію ReadAsync і проєктуємо у властивість за типом AssignmentViewModel, для відображення на сторінці.

Після оновлення потрапляємо на обробник OnPostAsync, де перевіряємо наявність зображення і видаляємо попереднє, якщо воно є. Далі, використовуючи метод репозиторію UpdateAsync, оновлюємо запис.

Ще одна річ, яку нам потрібно зробити, – це пов’язати сторінку оновлення зі сторінкою читання. Таблиця в Read.cshml, у якій відображаються записи доручень, ідеально підходять для цього.

Додамо ще один стовпець для таблиці, до цього стовпця буде додано тег якоря, що посилатиметься на сторінку оновлення:

Значення href тега anchor буде створено помічниками тегів asp-page і asp-route. У asp-page вказується ім’я сторінки, яке дорівнює Update, а в asp-route – ім’я маршруту, яке дорівнює id. Значення id додається в помічник тега з механізму циклу foreach.

Тепер додамо в інтерфейс IRepository, метод під назвою DeleteAsync. Цей метод приймає як параметр id сутності:

Також реалізуємо цей метод у класі IRepository.cs:

У цьому методі ми використовуємо метод FindAsync сховища, щоб знайти сутність за її ідентифікатором. А потім видаляємо сутність методом Remove.

Далі перейдемо до сторінки Read. Нам не потрібно створювати нову сторінку Razor Page для операції Delete. Щоб створити CRUD-операцію Delete, додамо ще один стовпець у таблицю на Razor-сторінці Read.cshml. Цей стовпець міститиме кнопку видалення, натискання на яку призведе до видалення запису:

Нарешті, нам потрібно додати обробник OnPostDeleteAsync у файл Read.cshtml. Цей обробник буде викликатися при натисканні кнопки видалення:

Обробник OnPostDeleteAsync є асинхронним обробником, оскільки в його кінці стоїть «Async». Термін OnPost на початку його назви вказує на те, що це обробник типу Post. Спочатку, використовуючи метод DeleteAsync, видаляємо запис. Потім, перевіряємо чи є зображення, тоді видаляємо.

Запустимо додаток і перевіримо його роботу:

razor onpost on get

Фільтрація даних

Давайте створимо функцію для пошуку сутності за її ім’ям за допомогою LINQ виразів. Додамо новий метод ReadAllAsync в інтерфейс IRepository. Цей метод матиме параметр типу Expression<Func<T, bool>>, який можна використовувати для передачі виразу фільтрації:

Далі у файлі Repository.cs додамо цей метод:

Func<T, bool> – означає, що вираз фільтра буде працювати з сутностями типу «T» і повертає тип bool. Тому ми можемо застосувати цей вираз фільтрації до речення «Де», як показано нижче:

Для того щоб синхронізувати пагінацію і фільтрацію, змінимо сторінку Read.cshtml таким чином:

Для отримання запиту, на сторінці визначили властивість SearchTerm, значення якої передаємо в клас PageLinkTagHelper, у колекцію PageOtherValues:

Цей код дає змогу визначити атрибути HTML із префіксом «page-other-» і зберігати їхні значення в словнику PageOtherValues. Значення з цієї колекції витягуються і додаються як параметри запиту:

Таким чином, у методі OnGet, сторінки Read.cshtml, ми можемо отримати ці значення через параметри:

Запустимо додаток і перевіримо його роботу:

razor pages пагинация

На цьому все, сподіваюся вам було цікаво і просто. Пишіть у коментарях, якщо хочете продовження, в якому ми реалізуємо авторизацію та реєстрацію, поділ частин програми за ролями.

Я сподіваюся, що вам сподобалося читати цю статтю, і вона виявилася легкою для розуміння. Будь ласка, дайте мені знати, якщо у вас є якісь коментарі або виправлення.

Так само вам може бути цікава попередня стаття – Найкращі книги з C# на 2024 рік.


Ви хочете навчитися писати код мовою програмування C#?

Створювати різні інформаційні системи, що складаються з сайтів, мобільних клієнтів, десктопних додатків, телеграм-ботів тощо.

Переходьте до нас на сторінку Dijix і ознайомтеся з умовами навчання, ми спеціалізуємося тільки на індивідуальних заняттях, як для початківців, так і для просунутих програмістів. Ви можете взяти як одне заняття для опрацювання питання, що вас цікавить, так і кілька, для більш щільної роботи. Завдяки особистому кабінету, кожен студент підвищить якість свого навчання, у вашому розпорядженні:

  • Доступ до пройденого матеріалу
  • Тематичні статті
  • Бібліотека книг
  • Онлайн тестування
  • Спілкування в закритих групах

https://dijix.com.ua

Живи у своєму світі, програмуй у нашому.

Published inAsp.Net Core
Subscribe
Notify of
guest
0 комментариев
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x