Migrate Page Skill
When the user invokes /migrate-page <EntityName>:
1. Analyze Legacy Code
First, thoroughly examine the existing MVC implementation:
- •Read the legacy controller:
Neptune.WebMvc/Controllers/{Entity}Controller.cs - •Read all views in:
Neptune.WebMvc/Views/{Entity}/ - •Check for partials in:
Neptune.WebMvc/Views/Shared/that may be used - •Look for JavaScript in:
Neptune.WebMvc/Scripts/related to the entity
Identify and document:
- •All CRUD operations (Index, Detail, New, Edit, Delete)
- •Special/custom endpoints
- •Bootstrap patterns used (panels, tables, forms, modals)
- •Client-side validation or JavaScript behavior
- •Related entities and their relationships
- •Authorization/permission requirements
Identify Components Requiring Specialized Skills
Based on your analysis, note which of these components the page contains:
| Component Found | Specialized Skill | When to Use |
|---|---|---|
| Data tables/grids | /migrate-grid | Index pages, detail pages with related entity lists |
| Maps with boundaries/locations | /migrate-map | Pages showing spatial data |
| Create/Edit forms | /crud-modal | Pages with New/Edit functionality |
| Multi-step wizards | /migrate-workflow | Pages with sequential data entry steps |
Document which skills you'll need for this migration.
2. Plan API Layer
Before writing code, plan the artifacts needed:
DTOs to create:
- •
{Entity}GridDto— Fields needed for list/index view - •
{Entity}Dto— Fields for detail view including related data - •
{Entity}UpsertDto— Fields for create/edit forms - •
{Entity}SimpleDto— If used in dropdowns elsewhere
Identify:
- •Which related entities need to be Included for extension methods
- •Query optimization opportunities (avoid N+1)
- •Validation rules to implement
3. Create API Files
Create the following files in order:
3.1 DTOs
Location: Neptune.Models/DataTransferObjects/
- •
{Entity}GridDto.cs - •
{Entity}Dto.cs - •
{Entity}UpsertDto.cs
3.2 Extension Methods
Extension methods are generated by scaffold in Neptune.EFModels/Entities/Generated/ExtensionMethods/{Entity}ExtensionMethods.cs. If you need custom extension methods beyond what scaffold generates, add them in Neptune.EFModels/Entities/ as a partial class or separate file:
- •
AsDto()— Full detail mapping - •
AsGridDto()— Grid row mapping - •
AsSimpleDto()— Simple/dropdown mapping
3.3 Static Helpers
Location: Neptune.EFModels/Entities/{PluralEntity}.cs
- •
ListAsDtoAsync()orListAsGridDto() - •
GetByIDAsDto() - •
GetByID() - •
GetByIDWithChangeTracking() - •
CreateNew() - •
Update() - •
DeleteAsync()
3.4 Controller
Location: Neptune.API/Controllers/{Entity}Controller.cs
- •Extend
SitkaController<{Entity}Controller>(dbContext, logger, neptuneConfiguration)with primary constructor (3 params) - •Implement endpoints matching the DTOs
3.5 Authorization
Apply authorization attributes to controller endpoints based on legacy feature attributes.
Step 1: Identify legacy features
Search for Feature] in the legacy controller:
grep -E "Feature\]" Neptune.WebMvc/Controllers/{Entity}Controller.cs
Step 2: Map to Neptune authorization attributes
| Legacy Feature Pattern | New Attribute | Roles |
|---|---|---|
| Public/anonymous endpoint | [AllowAnonymous] | No auth required |
| Admin-only operations | [AdminFeature] | Admin, SitkaAdmin |
| SitkaAdmin-only operations | [SitkaAdminFeature] | SitkaAdmin |
| Jurisdiction edit operations | [JurisdictionEditFeature] | Admin, SitkaAdmin, JurisdictionManager, JurisdictionEditor (+ jurisdiction match) |
| Jurisdiction manage operations | [JurisdictionManageFeature] | Admin, SitkaAdmin, JurisdictionManager (+ jurisdiction match) |
| Any authenticated user | [UserViewFeature] | All logged-in users |
| Unassigned users | [LoggedInUnclassifiedFeature] | Unassigned users |
Step 3: Apply attributes
- •Add
using Neptune.API.Services.Authorization;to the controller - •Add
using Microsoft.AspNetCore.Authorization;if using[AllowAnonymous] - •Apply appropriate attribute to each endpoint:
- •GET endpoints (public data): Usually
[AllowAnonymous]or[UserViewFeature] - •POST/PUT/DELETE: Apply the feature attribute that matches the legacy feature
- •GET endpoints (public data): Usually
Example:
[HttpGet]
[UserViewFeature]
public ActionResult<List<EntityGridDto>> List() { ... }
[HttpPost]
[AdminFeature]
public ActionResult<EntityDto> Create([FromBody] EntityUpsertDto dto) { ... }
[HttpPut("{entityID}")]
[JurisdictionEditFeature]
public ActionResult<EntityDto> Update([FromRoute] int entityID, [FromBody] EntityUpsertDto dto) { ... }
4. Generate TypeScript
After API code is complete:
# Build the API to generate swagger.json dotnet build Neptune.API/Neptune.API.csproj -c Debug # Generate TypeScript models cd Neptune.Web npm run gen-model
Verify the generated files in Neptune.Web/src/app/shared/generated/.
5. Create Angular Components
5.1 Component Structure
Location: Neptune.Web/src/app/pages/{entity}/
Create the folder structure based on identified components:
- •
{entity}-list/— If page has a main grid (use/migrate-grid) - •
{entity}-detail/— If page has a detail view - •
{entity}-modal/— If page needs create/edit forms (use/crud-modal)
All components must be standalone with explicit imports. Use @Input() with BehaviorSubject pattern for route params.
5.2 Grids
If the page contains data grids, follow the /migrate-grid skill for:
- •Column definition patterns
- •DTO design for grid rows
- •Grid component usage (
neptune-grid)
5.3 Maps
If the page contains maps, follow the /migrate-map skill for:
- •GeoJSON endpoint patterns
- •Map component integration (
neptune-map) - •Layer component usage
5.4 CRUD Modals
If the page needs create/edit/delete functionality, follow the /crud-modal skill for:
- •Modal component structure
- •Form creation with generated helpers
- •Validation patterns
- •Delete confirmation patterns
5.5 Route Configuration
Add route to Neptune.Web/src/app/app.routes.ts:
{
path: 'entities',
children: [
{
path: '',
loadComponent: () => import('./pages/entity/entity-list/entity-list.component').then(m => m.EntityListComponent)
},
{
path: ':entityID',
loadComponent: () => import('./pages/entity/entity-detail/entity-detail.component').then(m => m.EntityDetailComponent)
}
]
}
5.6 Route Guards
Apply guards as needed:
| Guard | Purpose |
|---|---|
UnsavedChangesGuard | Prevents navigation away from unsaved form changes |
Auth checks are typically done within components using AuthenticationService.
6. Write Tests
6.1 API Tests (MSTest)
Location: Neptune.Tests/
- •Test all controller actions
- •Use in-memory database
- •Test success and error cases
- •Remember 3-param constructor:
new EntityController(dbContext, logger, Options.Create(new NeptuneConfiguration()))
6.2 Angular Tests (Jasmine)
Location: Same folder as component with .spec.ts extension
- •Test component creation
- •Test data loading
- •Test user interactions
- •Mock services with
jasmine.createSpyObj
7. Remove/Deprecate Legacy Code
After migration is complete and tested:
- •Add
[Obsolete("Migrated to Angular SPA")]attribute to legacy controller - •Or remove legacy controller/views entirely if safe
- •Update any internal links to point to new Angular routes
8. Run Tests and Verify
# Run API tests dotnet test Neptune.Tests/Neptune.Tests.csproj # Run Angular tests cd Neptune.Web npm test # Manual verification npm start # Navigate to new pages and verify functionality
Checklist Before Completion
Core Migration
- • All CRUD operations migrated
- • Route params use
@Input()+BehaviorSubjectpattern - • All queries use
.AsNoTracking()with.Include()then.Select(x => x.AsDto())
Authorization
- • Legacy feature attributes identified for each action
- • Appropriate authorization attributes applied to all endpoints
- • Public GET endpoints marked with
[AllowAnonymous]or[UserViewFeature] - • Create/Edit/Delete endpoints protected with feature attributes
If Page Has Grids (per /migrate-grid)
- • Column parity verified with legacy
- • Filtering/sorting works
- • Links navigate correctly
If Page Has Maps (per /migrate-map)
- • All layers display correctly
- • Bounds/zoom behavior correct
- • Layer toggle works (if applicable)
If Page Has CRUD (per /crud-modal)
- • Create flow works
- • Edit flow works
- • Delete confirmation works
- • Form validation displays correctly
Final
- • API tests pass
- • Angular tests pass
- • Legacy code deprecated/removed
- • Manual testing complete