AI-Assisted September 2026 · 9 min read

AI-Assisted CRUD Development with ASP.NET Core MVC

TL;DR

In an AI-assisted ASP.NET Core MVC project, one entity class is enough to drive a full CRUD slice: controller, CQRS handlers, validators, Minimal API endpoints, Razor views, and collocated JavaScript — as long as the rules and a reference implementation are explicit.

Most "AI writes CRUD" demos fall apart the moment they meet a real codebase. The model produces a controller that does not match your routing, a query that bypasses soft delete, or a view whose JavaScript is referenced from a path that 404s. None of those failures is about model quality. They happen because nothing told the agent what a finished CRUD slice looks like in your project.

In an AI-assisted ASP.NET Core MVC project, the fix is to make the slice itself the unit of specification. One entity class is enough to drive the whole thing, provided the rules and a reference implementation are explicit. For the framework-level view of this workflow, see AI-Assisted Development with ASP.NET Core.

From One Entity to a Full CRUD Slice

A CRUD slice is everything a single entity needs to be created, read, updated, and soft-deleted through both a web UI and an API. That definition matters, because it fixes the scope the agent works within. Without it, "add CRUD for Asset" can mean anything from a single controller action to a dozen files scattered across the solution.

The workflow starts before any code is generated. The developer fills exactly one file, .ai-assisted/DATA-DICTIONARY.md, with the application name and short name, the personas, and the main features. Each feature is described with a Group and SubGroup taxonomy and a Stage Enum where lifecycles apply. Then the instruction to the agent is a single phrase: start the development.

From there the pipeline runs in phases. Gate 0 checks AppSettings:Name in appsettings.json; if it is still Indotalent the agent proceeds, and otherwise it stops because the project has already been customized and is in maintenance mode. Phase 0 generates FEATURE.md. Phase 1 runs PROMPT.md to produce PRD.md. Phase 2 builds the features one at a time, with dotnet build required to report zero errors after every feature. CRUD slices are the unit of that third phase.

The File Set

For an entity named Asset, a complete slice is eighteen or more files. The exact set is fixed by the rules, not improvised per feature:

  • A Controller that serves the Razor pages and delegates to handlers.
  • GetAssetListHandler — the paged, filtered list query.
  • GetAssetByIdHandler — the single-record read.
  • CreateAssetHandler plus its CreateAssetValidator.
  • UpdateAssetHandler plus its UpdateAssetValidator.
  • DeleteAssetHandler for the soft delete.
  • A GetAsset{Lookup}LookupHandler when the entity is referenced by a dropdown on another form.
  • Endpoints/AssetEndpoint.cs, the Minimal API mapping file.
  • Razor views Index.cshtml, Create.cshtml, Edit.cshtml, and Detail.cshtml.
  • A collocated .cshtml.js file for each view.

Count the list: ten named handlers and validators, one endpoint file, four views, and four scripts, plus the controller. The exact number shifts with lookups and attachments, but the principle never does. The agent generates the whole set from one entity because the rules define the set, and the reference implementation shows the shape.

🔑 The Core Insight

The file set is derived, not decided. If the entity is a Pure Master, a Master with Lookup, or a Master-Detail, the rules already say which files exist. The agent's job is to fill them in, not to invent a structure.

MVC Areas and Feature Folders

Everything in the slice lives in one feature folder. MVC Areas give each domain a boundary, and the entity gives each feature its folder:

Areas/
  Asset/
    AssetController.cs
    Cqrs/
      GetAssetListHandler.cs
      GetAssetByIdHandler.cs
      CreateAssetHandler.cs
      CreateAssetValidator.cs
      UpdateAssetHandler.cs
      UpdateAssetValidator.cs
      DeleteAssetHandler.cs
    Endpoints/
      AssetEndpoint.cs
    Views/
      Index.cshtml
      Index.cshtml.js
      Create.cshtml
      Create.cshtml.js
      Edit.cshtml
      Edit.cshtml.js
      Detail.cshtml
      Detail.cshtml.js

One folder, one feature, one bounded context for the agent to read. This is the same reasoning that makes an AI-ready project structure a prerequisite rather than a nice-to-have: if a feature is spread across seven projects, no agent can assemble the context reliably.

Help Us Grow

Love this guide? Explore our ready-to-use enterprise starter kits built with ASP.NET Core and Vertical Slice Architecture.

Handlers, Validators, and Endpoints

CQRS keeps reads and writes separate, and that separation is what lets the agent generate predictable code. Each handler takes a request, does its work against the EF Core context, and returns a result. FluentValidation is the single source of truth: validators sit beside the create and update handlers, and the database stays open with no data annotations on the entities.

Minimal API endpoints follow one naming rule that removes almost all ambiguity: the last segment of the route names the entity. A list route ends in the entity name; a lookup route ends in {lookupentitylower}-lookup:

// Entity-named routes, and a cancellation token on every handler call.
app.MapGet("/api/asset", async (IMediator mediator, CancellationToken ct) =>
    Results.Ok(await mediator.Send(new GetAssetListQuery(), ct)));

app.MapGet("/api/asset/{id}", async (int id, IMediator mediator, CancellationToken ct) =>
    Results.Ok(await mediator.Send(new GetAssetByIdQuery(id), ct)));

app.MapGet("/api/asset/assetmodel-lookup", async (IMediator mediator, CancellationToken ct) =>
    Results.Ok(await mediator.Send(new GetAssetAssetModelLookupQuery(), ct)));

CancellationToken is mandatory on every CQRS handler and every Minimal API endpoint. The token on an endpoint lambda binds to HttpContext.RequestAborted, so a long query stops when the caller disconnects. It is a small rule with an outsized effect on quality, because it is exactly the kind of detail an agent omits unless told.

❌ Ad-hoc CRUD

  • • Routes named inconsistently
  • • Validation split across layers
  • • Hard delete slips in
  • • Missing cancellation tokens
  • • Script path 404s and blanks the page

✅ Rules-driven CRUD

  • • Entity-named endpoints, including lookups
  • • FluentValidation beside the handler
  • • Soft delete with a global query filter
  • • CancellationToken on handlers and endpoints
  • • JS referenced by physical path

Razor Views and Collocated JavaScript

The views are conventional: Index lists records with server-side DataTables, Create and Edit share a form shape, and Detail shows one record with its audit trail. The rule that trips up most generated projects is not the Razor markup, it is how the JavaScript is attached.

Collocated JavaScript lives in the same view folder and is referenced by its physical path: ~/areas/{Area}/{Entity}/Views/{Page}.cshtml.js. A wrong path returns a 404 and the page silently blanks, because the script that initializes the table or the lookup never runs. The agent must derive the path from the actual folder, not from a convention it half-remembers.

There is a second trap here: dotnet build does not compile JavaScript. A malformed script passes the build and fails in the browser. The rules therefore require an explicit JavaScript check after generation — brace balance at minimum, and node --check when Node is available.

The Build Gate

After every CRUD slice, the agent runs dotnet build and requires zero errors before starting the next entity. This is the workflow's verification ceiling, and it is deliberately modest. A clean build proves the slice is well-formed and self-consistent; it does not prove the page works. The agent does not run the application. A human tests at runtime, exercises the forms, and confirms the lifecycle rules behave as specified.

Keeping the gate small is what makes it usable. An agent asked to verify behavior end to end will hallucinate success, because it cannot click a button. An agent asked to produce a zero-error build is being asked for something it can actually check, and the human owns the part that requires judgment.

A Worked Example: Asset Model

Return to the reference ASP.NET Core asset management application. AssetModel is a clear Master with Lookup: it carries a string ManufactureId and a Manufacture? Manufacture navigation, so the rules classify it immediately and the agent follows the Currency reference implementation rather than guessing.

The generated slice includes the controller, the five core handlers with their validators, a GetAssetModelManufactureLookupHandler that fills the Manufacture dropdown, the endpoint file, and the four Razor views with collocated scripts. AutoNumber assigns each model a reference in the mandated format, for example AST/2026/0001, and because AutoNumber is never a form field, that value appears only as a DataTable column and an Audit Trail entry.

The slice is then built. If a using directive is missing or a query returns the wrong type, the build says so, the agent fixes it, and the next entity begins. Repeating that loop across the entity list — Branch, Department, Manufacture, Vendor, AssetModelGroup, AssetModelSubGroup, AssetModel, Asset, Employee — produces a consistent application without a single hand-written controller.

Key Takeaways

  • One entity drives a full CRUD slice: controller, CQRS handlers, validators, lookup handler, Minimal API endpoints, Razor views, and collocated JavaScript.
  • The file set is derived from the entity type — Pure Master, Master with Lookup, or Master-Detail — not invented per feature.
  • Name the last route segment by entity, keep FluentValidation as the single source of truth, and put a CancellationToken on every handler and endpoint.
  • Reference collocated JS by its physical ~/areas/{Area}/{Entity}/Views/{Page}.cshtml.js path, and check it separately because the build will not.
  • dotnet build with zero errors is the gate after every slice; a human still tests the running application.

Stop fighting your AI tools. Start using VSA.

Every Indotalent product is a complete VSA application — the perfect foundation for AI-assisted development. $21 each.

Explore Products

Looking for a ready-to-use traditional monolithic multilayered clean architecture?

Monolithic Clean Architecture — 1,300+ devs, 500+ forks. Clean Arch + CQRS + Repository Pattern. Free & open source for commercial use. ⭐ Star our repo or ❤️ buy our products — your support means everything!

Star on GitHub
Get the MVC EDevKit ASP.NET Core MVC AI-Ready Starter