• Korzh.com Blog
  • /
  • Super easy CRUD for ASP.NET Core apps with EasyData library

Super easy CRUD for ASP.NET Core apps with EasyData library

Problem

One of the first tasks for most business applications is implementing CRUD (Create, Read, Update, Delete) operations for the main entities this application works with.

Every developer who needs to solve this task faces the following problems:

  • Creating CRUD pages and forms is very boring and time-consuming. Believe me, I’ve been there a lot of times.

  • If you do it manually, it can be very slow and error-prone (missed fields, forgotten validators, etc).

  • Of course, you can use the scaffolding tool provided by Visual Studio.
    However, it’s also not a quick process since you need to run that tool for each model class. As a result, you get many .cs and .cshtml files, which you will need to edit manually if something in the default behavior or appearance does not suit your needs. In case of any changes in the model classes, you will need to update those generated controllers and pages manually or regenerate the code and forms for that model class from scratch.

  • Moreover, the built-in scaffolding does not provide some important and sometimes necessary functions like paging or search.

Solution: EasyData library

To solve most (if not all) of those problems we created the EasyData library. The main advantage of EasyData is that it employs a declarative approach. The whole process can be split into two main steps:

  1. You “describe” what data (entities and attributes) you want to work with and how exactly your application should work with that data (types, constraints, relations between entities, etc).

  2. Based on this information, the EasyData library establishes an API endpoint for CRUD operations and a vanilla JavaScript-based UI that allows your users to perform those operations via the API.

The most wonderful thing here is that in the case of using Entity Framework Core, all you need for the first step (“describing” the data) is your DbContext! You just “feed” it to the library and EasyData automatically extracts from there all the necessary information to create the API endpoints and the CRUD UI.

Quick demo

Here is a small introduction video that demonstrates how EasyData works:

EasyData quick demo

Getting Started

First of all, to test EasyData you can open and run one of the sample projects available in this repository.

Installing EasyData to your own project takes the following 3 simple steps:

1. Install EasyData NuGet packages

  • EasyData.AspNetCore
  • EasyData.EntityFrameworkCore.Relational

2. Add EasyData middleware in Startup.Configure

using EasyData.Services;
.    .    .    .    .

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapEasyData(options => {
            options.UseDbContext<AppDbContext>();
        });

        endpoints.MapRazorPages();
    });

In the middleware options, we also specify the type of DbContext object that will be used as the source of the metadata.

3. Set up a catch-all page for all CRUD operations

If you're using Razor Pages, add a new page (for example EasyData.chstml). If it’s MVC, you'll need a controller and a view. This page will "catch" all URLs that begin with a certain prefix (/easydata by default but it's configurable). So, we use a special catch-all parameter in the route definition ("/easydata/{**entity}").

We also add EasyData styles and the script file (easydata.min.js), which renders the data-management UI and handles all CRUD operations on the client-side.

@page "/easydata/{**entity}"
@{
    ViewData["Title"] = "EasyData";
}
<link rel="stylesheet" href="https://cdn.korzh.com/ed/1.2.2/easydata.min.css" />

<div id="EasyDataContainer"></div>

@section Scripts {
    <script src="https://cdn.korzh.com/ed/1.2.2/easydata.min.js" type="text/javascript"></script>
    <script>
        window.addEventListener('load', function () {
            new easydata.crud.EasyDataViewDispatcher().run()
        });
    </script>
}

That’s it. Now you can run your web app, open the /easydata URL and enjoy CRUD functionality.

Here how it may look like in result:

List view screen for one entity:

List view screen for Orders entity

"Edit Record" dialog:

Edit Record dialog

"Lookup" dialog (was opened from "Edit Record"):

Lookup dialog

How it works

Briefly about how all this magic works. As we mentioned before EasyData takes care of 3 main things:

  • Collects database metadata.

  • Establishes an API for the main CRUD operations.

  • Renders UI (again, based on the metadata) and processes all user interactions in that UI.

Let’s explore all these parts more in detail.

Metadata

Metadata is the data about your data: what entities (tables) are stored in your database, how they are connected, what attributes (fields) they have, what are the types of those attributes and what are the constraints for the values we can store in those attributes.

EasyData collects metadata (in one way or another) and stores it in the instance of MetaData class. This object contains the list of entities (tables), the attributes (fields) for each entity, the connections between entities, and some additional information used in API and during UI rendering and processing.

To fill the MetaData object we need to specify a metadata loader. In our example above we did that with the UseDbContext call, so the metadata is loaded from a DbConext object. Currently (in version 1.2) this is the only metadata loader available. In the future version, it will be possible to load metadata directly from a DbConnection object or, maybe, with some other ways.

EasyData middleware

EasyData middleware is responsible for establishing a REST API for all CRUD (and not only) operations initiated by the client-side.

To add the middleware to your pipeline use MapEasyData extension function inside UseEndpoints configuration delegate:

   app.UseEndpoints(endpoints =>
    {
       endpoints.MapEasyData(options => {
            options.UseDbContext<AppDbContext>();
        });
    }

This call should be made before MapMvc or MapRazorPages By default, EasyData middleware is assigned to /api/easydata endpoint but you can change it via the configuration function (action) passed in the parameter.

The only thing that is required to configure for MapEasyData is to tell it where to take the metadata. Currently, there is only one option available: getting metadata from a DbContext. So, that’s why we add UseDbContext<AppDbContext>() call in the example above. Besides getting metadata UseDbContext also provides our middleware with all means for performing CRUD operations as well (via the DbContext object itself).

EasyData UI root page

The third part of EasyData setup is the page where all CRUD user interface is rendered. It must be a so-called "catch-all" Razor page or MVC view. By default this page must be opened for any path started with /easydata/ prefix (so all paths like /easydata/student or /easydata/invoice must be processed by this page).

NB: /easydata is the default prefix. You can use another name but in this case, it will be necessary to specify it in the options of our RootDispatcherView object.

Our catch-all page can contain any HTML element of your choice. But to ensure the visualization and normal operation of the CRUD UI, it must include the following 4 elements:

  • <link> element with a reference to EasyData CSS file (easydata.min.cs)

  • Container (empty div element), where our interface will be displayed. By default, it must have the ID EasyDataContainer, but this can also be configured with options.

  • <script> element with a reference to easydata.min.js.

  • And a small script that creates and launches the EasyDataViewDispatcher object on page load.

An example of the simplest “catch-all” page you can see in the Getting Started section above.

Wrapping up

Currently, EasyData can work with .NET Core 3.1 and .NET 5. Obviously, all ASP.NET Core and Entity Framework Core versions that can work with the specified releases of .NET (Core) are supported. But it will not be a big problem to add support for previous versions of .NET Core or even .NET Framework 4.x. If anyone needs it, please submit an issue in EasyData's GitHub repository.

EasyData can be a good tool for quick prototyping of a new project or creating a POC (proof of concept) when we already understand what data we will need to work with but do not want to spend a lot of time on the simplest operations with that data. However, we hope that in time it will be possible to fully use this solution in the production environment.

So, we look forward to hearing from you for any comments or advice you may have. And of course, don't forget to ad a start for EasyData repository on GitHub especially if this library helped you and saved some time.

Subscribe

Subscribe to blog's updates. You will get notifications about new posts, and only them.

Recent posts

Supported by EasyQuery

EasyQuery is a multi-platform solution that lets you embedding ad-hoc reporting or advanced search functionality to your application