Перейти к содержанию

Проект с использованием Razor Pages (CRUD операции)

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (2 оценок, среднее: 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

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


 

Опубликовано в рубрикеAsp.Net Core
Подписаться
Уведомить о
guest
1 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Vera
Vera
3 месяцев назад

Спасибо, все просто и интересно!

1
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x