Одной из первых задач для большинства бизнес-приложений на ASP.NET Core является реализация операций CRUD (Create, Read, Update, Delete) для основных объектов, с которыми работает ваше решение.
Каждый разработчик, которому нужно решить эту задачу, знает, что
создание CRUD-страниц и форм очень скучный и трудоемкий
процесс.
Если делать это вручную, то получится очень медленно и наверняка с
кучей недоработок (пропущенные поля, забытые валидаторы и
т.д.).
Можно воспользоваться инструментом scaffolding'а, доступным в
Visual Studio. Но даже в этом случае это будет совсем не быстрый
процесс, поскольку его нужно запускать для каждого класса модели. В
итоге вы получаете множество .cs/.cshtml файлов, которые нужно
поддерживать и атуализировать по мере изменений в классах модели
или просто когда нужно что-то исправить в поведении или внешнем
виде CRUD страниц. Если количество сущностей в вашей БД превышает
десяток, то весьма велики шансы того, что файлы для реализации CRUD
операций занимают больше 50% всей кодовой базы вашего проекта.
Более того это решение все равно не обеспечивает некоторых важных,
а порой и необходимых функций, таких как разбитие на страницы в
режиме просмотра (pagination) или банальные поиск/фильтрация.
Решение: использовать библиотеку с открытым кодом EasyData, о которой и пойдет речь в данной статье.
Что такое EasyData?
EasyData и была создана для решения большинства (если не всех)
проблем описанных выше. Это библиотека с открытым кодом,
распространяется по MIT лицензии, исходники доступны на GitHub. Главной
особенностью является использование декларативного подхода.
Весь процесс можно разделить на два основных этапа:
- Вы описываете, с какими данными (сущностями и атрибутами) вы хотите работать и как ваша программа должна работать с этими данными (типы, ограничения, отношения между сущностями и т.д.).
- На основе этой информации библиотека EasyData разворачивает Web API для CRUD-операций и пользовательский интерфейс на основе чистого (ванильного) JavaScript, что позволяет вашим пользователям выполнять все те операции.
Самое замачательное здесь то, что в случае использования Entity Framework Core для первого шага (описания данных) вам нужен только ваш DbContext! Вы просто скармливаете его библиотеке, и EasyData автоматически извлекает оттуда всю необходимую информацию для разворачивания CRUD API и пользовательского интерфейса.
Весь процесс занимает всего несколько минут и около 10 строк кода:
Подключаем EasyData в свой проект
Прежде всего, чтобы попробовать EasyData в работе, вы можете открыть и запустить один из примеров проектов, доступных на GitHub.
Для установки EasyData в собственный проект надо выполнить следующие 3 простых шага:
1. Устанавливаем NuGet пакеты EasyData
- EasyData.AspNetCore
- EasyData.EntityFrameworkCore.Relational
2.
Добавляем EasyData middleware в
Startup.Configure
:
using EasyData.Services;. . . . . app.UseEndpoints(endpoints => { endpoints.MapEasyData(options => { options.UseDbContext<AppDbContext>(); }); endpoints.MapRazorPages(); });
В опциях нашего middleware мы указываем класс объекта DbContext, который и будет использоваться как источник метаданных.
3. Настраиваем страницу CRUD операций
Если вы используете Razor Pages, добавьте новую страницу (например, EasyData.chstml). Если это MVC, вам понадобятся новый контроллер и соответствующий ему view.
Наша новая страница должна будет ловить все адреса, которые
начинаются с определенного префикса (/easydata/
по
умолчанию, но это можно настроить). Для этого мы используем
специальный catch-all параметр в определении маршрута:
"/easydata/{**entity}"
.
Кроме того, мы также добавляем .css и .js файлы EasyData
(easydata.min.css
и easydata.min.js
),
которые обеспечивают отрисовку интерфейса управления данными и
обработку всех CRUD-операций на стороне клиента.
@page "/easydata/{**entity}"@{ ViewData["Title"] = "EasyData";}<link rel="stylesheet" href="http://personeltest.ru/aways/cdn.korzh.com/ed/1.2.4/easydata.min.css" /><div id="EasyDataContainer"></div>@section Scripts { <script src="http://personeltest.ru/aways/cdn.korzh.com/ed/1.2.4/easydata.min.js" type="text/javascript"></script> <script> window.addEventListener('load', function () { new easydata.crud.EasyDataViewDispatcher().run() }); </script>}
Вот и все. Теперь вы можете запустить свой проект, открыть
URL-адрес /easydata
и наслаждаться функциями CRUD.
Вот как это выглядит в итоге:
Страница просмотра значений для некоторой сущности (в данном
случае, Orders)
Диалог редактирования одной записи
Lookup диалог, который был открыт из диалога редактирования
записи
Как это работает
Коротко о том, как работает вся эта магия.
Как мы уже упоминали ранее, EasyData решает 3 основных задачи:
- Собирает метаданные из нашей базы данных.
- Устанавливает API для основных CRUD операций.
- Визуализирует интерфейс (опять же, на основе метаданных) и обрабатывает все взаимодействие пользователя с этим интерфейсом.
Давайте изучим все эти части более подробно.
Метаданные
Метаданные это данные о ваших данных: какие сущности (таблицы) хранятся в вашей базе данных, как они связаны, какие имеют атрибуты (поля) и другая полезная информация.
EasyData собирает метаданные (каким-либо способом об этом см. ниже) и сохраняет их в объекте класса MetaData. Этот объект содержит список сущностей (таблиц), атрибуты (поля) для каждой сущности, связи между сущностями и некоторую дополнительную информацию, используемую в API и при визуализации и обработке пользовательского интерфейса.
Для заполнения объекта MetaData нам нужно указать некоторый
загрузчик метаданных. В нашем примере мы сделали это с помощью
вызова UseDbContext
для загрузки метаданных из объекта
DbConext
. На данный момент (в версии 1.2), это пока
единственный доступный загрузчик метаданных. В будущих версиях
можно будет загружать метаданные непосредственно с БД или,
возможно, каким-нибудь другим способом.
EasyData middleware
EasyData middleware отвечает за обработку REST API для всех CRUD (и не только) операций, инициированных веб страницей.
Чтобы добавить middleware в очередь обработки вашего ASP.NET
Core приложения используйте функцию MapEasyData
в
процессе настроки точек вызова (endpoints)
UseEndpoints
:
app.UseEndpoints(endpoints => { endpoints.MapEasyData(options => { options.UseDbContext<AppDbContext>(); }); }
Этот вызов желательно поставить перед любым вызовом
MapControllerRoute
или MapRazorPages
.
По умолчанию EasyData API будет откликаться по адресу
/api/easydata
, но вы легко можете изменить его на
другой:
endpoints.MapEasyData(options => { options.Endpoint = "/api/my-crud"; . . . . });
Единственное, что нужно настроить для EasyData middleware, это
сказать ему, откуда брать метаданные. Как уже упоминалось выше,
сейчас доступен только один вариант, а именно получение метаданных
с DbContext. Вот почему мы добавляем вызов UseDbContext
<AppDbContext>()
в приведенном выше примере. Кроме
получения метаданных, UseDbContext
также обеспечивает
наш middlware всеми средствами для выполнения CRUD-операций (через
сам объект DbContext
).
Корневая страница интерфейса EasyData
В качестве такой страницы выступает Razor page или же MVC view.
Эта страница должна обрабатывать все URL адреса, которые начинается
с определенного префикса. По умолчанию это /easydata/
и поэтому все пути, типа /easydata/student
или
/easydata/invoice
, должны быть обработаны этой
страницей.
NB: /easydata/
префикс по умолчанию. Вы можете
установить и другой путь к этой странице, но в этом случае его
нужно будет указать в параметрах нашего объекта
RootDispatcherView
Наша корневая страница может содержать любые элементы HTML на ваш выбор. Но для нормальной работы CRUD интерфейса, она должна включать следующие 4 элемента:
-
<link>
элемент со ссылкой на CSS файл EasyData (easydata.min.cs
) -
Контейнер (пустой элемент
div
), где будет рисоваться наш CRUD интерфейс. По умолчанию он должен иметь идентификаторEasyDataContainer
, но это также можно настроить с помощью опций. -
<script>
элемент со ссылкой на файлeasydata.min.js
. -
небольшой скрипт, который создает и запускает объект
EasyDataViewDispatcher
при загрузке страницы.
Пример простейшей корневой страницы вы можете увидеть в разделе Подключаем EasyData в свой проект выше.
В завершение
На данный EasyData может работать с .NET Core 3.1 и .NET 5.
Очевидно, поддерживаются все версии ASP.NET Core и Entity Framework
Core, которые могут работать с указанными версиями .NET (Core).
Однако не будет большой проблемы при необходимости добавить также
поддержку предыдущих версий .NET Core или даже .NET Framework 4.x.
Если кому-то это нужно, создавайте новый issue про
это в GitHub репозитории библиотеки.
EasyData был сделан, в первую очередь, для быстрого создания прототипов новых проектов или так называемых POC (proof of concept), когда уже есть некоторое понимание с какими данными придется работать, но не хочется тратить много времени на реализацию простейших операций с этими данными.
Конечно, мы надеемся, что со временем можно будет полноценно использовать это решение и для вполне себе рабочих решений (не только прототипов). Будем рады любым вашим замечаниям или советам по этому поводу.
Ну и конечно, не забудьте поставить звездочку в EasyData репозитории на GitHub. Особенно если эта библиотека помогла сэкономить вам немного времени.