Scaffolding From an Entity

Scaffolding support is experimental. Please be sure to stash or commit changes before running the scaffolder in case it doesn’t quite work the way you expect it to.

The scaffolder takes an entity as an input and generates a ton of boilerplate code to make it easier to build and deploy features. This includes all the objects, services, and pages that get data to and from the database to the browser following the patterns used throughout the solution.

  • TOC

Set Up Your Entity

The scaffolder assumes you’re scaffolding an entity model intended for typical CRUD operations in a database. It’s not required that the target object be an EF entity, but there is some code in the generated service that expects it.

It’s recommended that entities are stored in the Data\Entities folder of the LightNap.Core project. We’ll use TestEntity as the example for this tutorial.

namespace LightNap.Core.Data.Entities
{
    public class TestEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Quantity { get; set; }
        public double Price { get; set; }
    }
}

Next, we’ll add a reference to it in ApplicationDbContext:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
    public DbSet<TestEntity> TestEntities { get; set; } = null!;
    ...

Note that it’s expected that the DbSet will use the pluralized version of the entity name. If you don’t have it set up this way then some of the generated code won’t compile without minor edits.

Running the Scaffolder

At this time, the scaffolder is provided in source form in the src/Scaffolding folder. You’ll need to build it before you can run it.

  cd src
  dotnet build ./Scaffolding
  .\Scaffolding\LightNap.Scaffolding\bin\Debug\net9.0\LightNap.Scaffolding.exe TestEntity

The script above is run from the repo’s main src directory to cleanly align with the default parameters. You can override most of these parameters if needed.

Generated Files

New files are generated to create a new area based around the provided entity. Instead of changing content within the other areas (Profile, Admin, etc.) the new area will match the entity name (like TestEntity) and provide a starting point for integration. It’s up to the developer to decide whether and which items are merged into other areas or kept contained within the newly created area.

In the Core project, everything is added in a new TestEntities area folder:

File Purpose
Dto/Response/TestEntityDto.cs Returned from get or search requests.
Dto/Request/CreateTestEntityDto.cs Parameter for create requests.
Dto/Request/SearchTestEntityDto.cs Parameter for search requests.
Dto/Request/UpdateTestEntityDto.cs Parameter for update requests.
Extensions/TestEntityExtensions.cs Includes methods for mapping between the entity and DTOs.
Interfaces/ITestEntityService.cs Interface for the area service.
Services/TestEntityService.cs Implementation of the area service.

In the Web API project:

File Purpose
Controllers/TestEntitiesController.cs The Web API endpoints that map to core service methods.

In the Angular project, everything is added in a new app/test-entities area folder:

File Purpose
components/pages/create/create.component.html Markup for the create item page.
components/pages/create/create.component.ts Code for the create item page.
components/pages/get/get.component.html Markup for the get item page.
components/pages/get/get.component.ts Code for the get item page.
components/pages/edit/edit.component.html Markup for the edit item page.
components/pages/edit/edit.component.ts Code for the edit item page.
components/pages/index/index.component.html Markup for the area landing/search page.
components/pages/index/index.component.ts Code for the area landing/search page.
components/pages/routes.ts Relative routes for the area pages.
helpers/test-entity.helper.ts Rehydrates dates from DTOs if needed.
models/response/test-entity.ts Maps to the server’s TestEntityDto.
models/request/create-test-entity-request.ts Maps to the server’s CreateTestEntityDto.
models/request/search-test-entities-request.ts Maps to the server’s SearchTestEntityDto.
models/request/update-test-entity-request.ts Maps to the server’s UpdateTestEntityDto.
services/data.service.ts The private service for HTTP calls to the REST API.
services/test-entity.service.ts The area service for app usage.

Final Configuration

After the scaffolder completes there are still a couple of things that need to be done for it to be ready for testing.

Registering the Core Service For the Web API Controller

The new Web API controller expects to have the new Core service injected. This needs to be configured in the AddApplicationServices method of Extensions/ApplicationServiceExtensions.cs and will look something like this:

public static IServiceCollection AddApplicationServices(this IServiceCollection services)
{
  ...
  services.AddScoped<ITestEntityService, TestEntityService>();
  ...

Now you can build and run the back-end.

Registering the Area Routes in the Angular Front-End

The new Angular area routes need to be added to the root route tree in app/routing/routes.ts so that the area pages can be accessed.

First, add the import of the routes at the top:

import { Routes as TestEntityRoutes } from "../test-entities/components/pages/routes";

Next, add the routes themselves to the tree. For example, if you want them to only be accessible to logged-in users, put them after the profile routes:

...
children: [
  { path: "home", data: { breadcrumb: "Home" }, children: UserRoutes },
  { path: "profile", data: { breadcrumb: "Profile" }, children: ProfileRoutes },
  { path: "test-entities", children: TestEntityRoutes }
  ...

Now you can build and run the front-end. You can access the new area at a URL like http://localhost:4200/test-entities.

Undoing the Scaffolder

The scaffolder only creates files, so deleting those files will undo its work.

Updating Scaffolding

The scaffolder does not support updating existing files. It will exit without making changes if there are any files already in locations it plans to write to.