Add Aspire AppHost template, CleanArgs API, and coreex-domain naming fixes - #182
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new coreex-aspire add-on template for generating an Aspire AppHost, introduces a CleanArgs parameter to make Cleaner.Clean<T> default-collapsing explicitly opt-in, and fixes coreex-domain template naming/symbol derivation so the .Domain suffix behaves consistently with other add-on templates.
Changes:
- Added the
coreex-aspiretemplate and updated template pack docs + validation scenarios to scaffold/build it in composite runs. - Introduced
CleanArgsand updatedCleaner/RuntimeMetadata/WebApi request cleaning behavior, plus new/updated unit tests. - Fixed
coreex-domainsourceName/derived symbols and hardened scaffolding docs and guidance to prevent common generation/runtime pitfalls.
Reviewed changes
Copilot reviewed 51 out of 55 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/validate-template-pack.ps1 | Adds composite scaffolding/build scenarios and negative content assertions. |
| tests/CoreEx.Test.Unit/Runtime/RuntimeMetadataTests.cs | Expands cleaning tests to cover CleanArgs root/nested behavior and ChangeLog defaults. |
| tests/CoreEx.Test.Unit/Entities/CleanerTests.cs | Adds unit coverage for new default clean option behavior and per-type overrides. |
| tests/CoreEx.Test.Unit/Entities/CleanArgsTests.cs | New unit tests for CleanArgs defaults and init behavior. |
| tests/CoreEx.AspNetCore.Test.Unit/PersonApi_MutateTestsBase.cs | Adds request-validation coverage for empty request bodies. |
| tests/CoreEx.AspNetCore.Test.Api/Services/PersonService.cs | Ensures service-level identifier requirement aligns with request validation expectations. |
| src/CoreEx/Metadata/RuntimeMetadata.Clean.cs | Adds CleanArgs plumbing and opt-in default collapsing for CleanAndDefault. |
| src/CoreEx/Metadata/PropertyRuntimeMetadata.cs | Threads CleanArgs into property cleaning and aligns default clean option lookup. |
| src/CoreEx/Metadata/IPropertyRuntimeMetadata.cs | Updates interface to pass CleanArgs during cleaning. |
| src/CoreEx/Mapping/IMapperT.cs | Formatting-only change (trailing newline/brace alignment). |
| src/CoreEx/Mapping/BiDirectionMapperT2.cs | Formatting-only change (trailing newline/brace alignment). |
| src/CoreEx/Entities/README.md | Documents CleanArgs in the entities package overview. |
| src/CoreEx/Entities/Cleaner.cs | Adds CleanArgs support, per-type clean options registry, and changes default clean option to Clean. |
| src/CoreEx/Entities/CleanArgs.cs | New CleanArgs struct controlling root/nested default-collapsing behavior. |
| src/CoreEx/Entities/ChangeLog.cs | Formatting-only change (trailing newline/brace alignment). |
| src/CoreEx.Validation/Abstractions/SelfRuntimeMetadata.cs | Updates IPropertyRuntimeMetadata implementation to new signature. |
| src/CoreEx.Template/README.md | Updates template pack documentation for coreex-aspire and coreex-domain naming fix. |
| src/CoreEx.Template/CoreEx.Template.csproj | Packs the new CoreEx.Aspire template’s template.json directly. |
| src/CoreEx.Template/content/CoreEx.Subscribe/src/app-name.Subscribe/Program.cs | Fixes conditional usings for symbol-dependent compilation. |
| src/CoreEx.Template/content/CoreEx.Subscribe/src/app-name.Subscribe/GlobalUsing.cs | Guards global usings behind template symbols to prevent invalid references. |
| src/CoreEx.Template/content/CoreEx.Domain/src/app-name.Domain/app-name.Domain.csproj | Fixes Contracts ProjectReference to use derived solution-name symbol. |
| src/CoreEx.Template/content/CoreEx.Domain/.template.config/template.json | Corrects sourceName to include .Domain and adds derived symbols. |
| src/CoreEx.Template/content/CoreEx.Core/README.md | Strengthens CodeGen guidance (required before first dotnet run when refdata enabled). |
| src/CoreEx.Template/content/CoreEx.Core/AGENTS.md | Updates domain add-on invocation guidance to require .Domain suffix. |
| src/CoreEx.Template/content/CoreEx.Aspire/src/app-name.Aspire/Properties/launchSettings.json | Adds launch profiles and Aspire dashboard environment wiring. |
| src/CoreEx.Template/content/CoreEx.Aspire/src/app-name.Aspire/Extensions.cs | Adds dashboard “sugar” extensions (endpoints + hosted-service commands). |
| src/CoreEx.Template/content/CoreEx.Aspire/src/app-name.Aspire/appsettings.json | Adds basic logging defaults for AppHost. |
| src/CoreEx.Template/content/CoreEx.Aspire/src/app-name.Aspire/appsettings.Development.json | Adds empty development config stub. |
| src/CoreEx.Template/content/CoreEx.Aspire/src/app-name.Aspire/AppHost.cs | New AppHost orchestration wiring with host inclusion flags. |
| src/CoreEx.Template/content/CoreEx.Aspire/src/app-name.Aspire/app-name.Aspire.csproj | New AppHost project with conditional host ProjectReferences and CVE override. |
| src/CoreEx.Template/content/CoreEx.Aspire/src/app-name.Aspire/AGENTS.md | Adds AppHost-specific agent guidance and safe update instructions. |
| src/CoreEx.Template/content/CoreEx.Aspire/.template.config/template.json | New coreex-aspire template definition with symbols and port generators. |
| src/CoreEx.Template/content/CoreEx.Api/src/app-name.Api/Program.cs | Guards symbol-dependent using to prevent compilation issues. |
| src/CoreEx.Template/content/CoreEx.Api/src/app-name.Api/GlobalUsing.cs | Guards database global using behind has-data-provider. |
| src/CoreEx.DomainDriven/AGENTS.md | Documents per-aggregate Domain-layer adoption (not all-or-nothing). |
| src/CoreEx.Database/Abstractions/DatabaseArgs.cs | Formatting-only change (trailing newline/brace alignment). |
| src/CoreEx.AspNetCore/WebApiRequestResponseOptions.cs | Updates request cleaning call to use explicit CleanArgs.Default. |
| src/CoreEx.AspNetCore/WebApiRequestOptions.cs | Updates request cleaning call to use explicit CleanArgs.Default. |
| src/CoreEx.AspNetCore/Abstractions/IWebApiRequestOptions.cs | Updates docs to reference new Cleaner.Clean<T>(..., CleanArgs) overload. |
| samples/tests/Contoso.Products.Test.Api/ProductMutateTests.Create.cs | Adds API test for empty create request validation. |
| samples/docs/tooling.md | Clarifies safe usage boundaries for DbEx $/$^ merge seed data. |
| samples/docs/hosts-layer.md | Adds guidance on split vs consolidated host topology. |
| samples/docs/domain-layer.md | Clarifies Domain-layer adoption can be per-aggregate. |
| docs/getting-started.md | Updates onboarding to mark CodeGen as required before first run when refdata enabled. |
| .github/skills/coreex-solution-scaffolder/SKILL.md | Updates scaffolding skill to include optional Aspire AppHost guidance and naming rules. |
| .github/skills/coreex-solution-scaffolder/references/workflow.md | Adds interview step and workflow routing for optional Aspire AppHost. |
| .github/skills/coreex-aggregate/SKILL.md | Documents per-aggregate adoption guidance in aggregate skill. |
| .github/skills/coreex-aggregate/references/workflow.md | Updates Domain-layer creation command example to include .Domain suffix. |
| .github/prompts/coreex-scaffold.prompt.md | Updates prompt metadata to include Aspire AppHost option. |
| .github/instructions/coreex-tooling.instructions.md | Adds explicit warning about $/$^ merge limitations for non-lookup tables. |
| .github/instructions/coreex-host-setup.instructions.md | Adds split-vs-consolidate guidance reference. |
| .github/instructions/coreex-domain.instructions.md | Adds per-aggregate adoption guidance. |
| .github/copilot-instructions.md | Adds reminder to validate template changes via validate-template-pack.ps1 and updates template list. |
| .github/agents/coreex-expert.agent.md | Updates agent routing guidance to mention Aspire orchestration. |
| .claude/commands/coreex-scaffold.md | Updates scaffold command metadata to include Aspire AppHost option. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 52 out of 56 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/CoreEx/Entities/Cleaner.cs:18
ResetDefaults()now leavesCleanOptions(the new mutable per-type registry) untouched and the XML summary doesn’t reflect that it also resetsDefaultDateTimeTransform/DefaultCleanOption. BecauseCleanerTestscallsResetDefaults()in[SetUp], any test (or consumer) that mutatesCleanOptionsand fails before cleanup can leak global state into later tests/runs. Consider resettingCleanOptionsback to the built-in defaults (and updating the summary) soResetDefaults()truly restores default behavior.
src/CoreEx/Metadata/RuntimeMetadata.Clean.cs:16- The XML remarks say only value-type collection/dictionary entries are “unable to be cleaned/replaced,” but the implementation never replaces/nuls out entries at all (it only cleans nested object graphs). With the new
CleanArgs.CleanAndDefaultNested, this can mislead callers into thinking default-collapsing will apply to items inside lists/dictionaries/arrays.
Added new coreex-aspire template for scaffolding a .NET Aspire AppHost that orchestrates Api/Relay/Subscribe hosts for local development. Updated README, workflow guides, and skill instructions to document AppHost usage, parameters, and integration. Enhanced validate-template-pack.ps1 with composite scenarios to test AppHost generation and symbol-conditional code. Added sample AppHost project files and updated .csproj/template config for references and package overrides. Clarified host composition conventions in docs and improved guidance for AppHost updates. Minor fixes to symbol handling and documentation consistency. Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Introduced CleanArgs to control Cleaner.Clean<T> behavior, allowing opt-in collapsing of default values at root and nested levels via CleanAndDefaultRoot/Nested. Updated Cleaner, RuntimeMetadata, and related APIs to accept CleanArgs. Changed default cleaning to Clean (no null-collapsing) and registered ChangeLog as CleanAndDefault by default. Enhanced documentation to clarify Clean vs. CleanAndDefault. Added unit tests for CleanArgs, Cleaner, and web API request validation, covering edge cases and ensuring correct handling of empty/default values. Minor doc and prompt updates for coreex-scaffold regarding Aspire AppHost. Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Clarifies and enforces that the Domain layer add-on (`coreex-domain`) must always use the full four-part name with the `.Domain` suffix in all templates, docs, and validation scripts. Updates all references and examples to consistently use the `.Domain` suffix. Adjusts `template.json` and symbol derivations to require and process the suffix. Fixes `App.Domain.csproj` project references to resolve the correct Contracts project. Updates documentation to clarify Domain layer adoption is per-aggregate and that CRUD entities can coexist with DDD aggregates. Adds warnings about `$`/`$^` merge prefixes in seed data, restricting their use to reference/lookup tables. Provides guidance for re-running CodeGen when adding new API hosts. Updates validation script to test naming requirements and project reference resolution. Includes minor clarifications and consistency improvements throughout documentation. Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
PersonService2.CreateAsync used an unguarded person.Id! that threw a raw
ArgumentNullException (500) instead of a validation error (400) once the new
CleanArgs default stopped collapsing an empty-but-present request body to
default — PersonService already had the matching Required("Identifier") guard,
PersonService2 was missed. RuntimeMetadata.Clean<T> was keying the per-type
CleanAndDefault lookup off typeof(T) instead of the value's actual runtime
type, so a type registered in Cleaner.CleanOptions (e.g. ChangeLog) wouldn't
collapse when reached via a base type/interface. Also fixes a doc typo.
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
chullybun
force-pushed
the
coreex-aspire-skill
branch
from
August 16, 2026 23:23
cf6a64b to
7769822
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three independent pieces of work landed on this branch:
Aspire AppHost template (
coreex-aspire) — a newdotnet newaddon that scaffolds a .NET Aspire AppHost orchestrating a solution'sApi/Relay/Subscribehosts for local development, with dashboard sugar (health-check links, pause/resume-all-services buttons). Docs, skill workflow, andvalidate-template-pack.ps1scenarios updated to match.CleanArgsAPI —Cleaner.Clean<T>now accepts aCleanArgsparameter controlling opt-in null/default collapsing (CleanAndDefaultRoot/CleanAndDefaultNested), decoupled from the previous implicit default-collapsing behavior.ChangeLogis registeredCleanAndDefaultby default; everything else defaults to plainClean(no collapsing). Includes new unit test coverage acrossCleaner,CleanArgs,RuntimeMetadata, and web API request validation.coreex-domainnaming fix + documentation hardening — fixes a real bug wherecoreex-domain'ssourceNamedidn't carry the.Domainsuffix used by every other addon template, causing the generated project'sContractsreference to resolve incorrectly depending on how you invoked it.template.jsonnow derivessolution-name/domain-name/solution-parent-namesymbols consistently with the other templates, and the.csprojreference uses the derived symbol instead of a hardcoded literal. A regression scenario was added tovalidate-template-pack.ps1that scaffolds a real siblingContractsproject and builds against it, since a standalone scaffold can't catch a dangling reference.Alongside the naming fix, several documentation gaps identified during scaffold testing were closed:
$/$^merge-prefix seed data guidance (coreex-tooling.instructions.md,samples/docs/tooling.md) now explicitly restricts merge to reference/lookup-shaped tables — it's unsafe for transactional/master tables carrying audit columns, concurrency tokens,IsDeleted, or FK-heavy business columns.dotnet runwhen reference data is enabled (not "optional verification") — running a host withASPNETCORE_ENVIRONMENT=Developmentbefore CodeGen has ever run throws a DI-validation exception at startup, sinceIReferenceDataRepositoryhas no registration until CodeGen emits it.*.Apiproject that exists at generation time, silently skipping it (a log warning, not an error) otherwise.Test plan
validate-template-pack.ps1run locally — 19/19 scenarios pass, including the newcoreex-domain-regressionscenariocoreex-domainnaming fix verified empirically: fresh scaffold with-n App.Domainnow resolvesApp.ContractscorrectlyASPNETCORE_ENVIRONMENT=Development) to confirm the new documentation accurately describes the failure modeCleanArgs/Cleaner/RuntimeMetadataunit tests passCleanArgsdefault-behavior change (Cleaninstead of implicit collapsing,ChangeLogexcepted) doesn't affect existing consumers relying on the old default