Skip to content

ARCH-001 Phase 28: consolidate Admin/Store/Vendor HomeController infra actions - #829

Merged
KrzysztofPajak merged 1 commit into
developfrom
arch001/phase28-home-infra-consolidation
Sep 11, 2026
Merged

ARCH-001 Phase 28: consolidate Admin/Store/Vendor HomeController infra actions#829
KrzysztofPajak merged 1 commit into
developfrom
arch001/phase28-home-infra-consolidation

Conversation

@KrzysztofPajak

Copy link
Copy Markdown
Member

ARCH-001 Phase 28: HomeController infra actions

First infra-action consolidation in this initiative (not a domain entity):
GetStatesByCountryId, Logout, and SetLanguage were duplicated across
HomeController in 2 or 3 of the 3 hosts, each differing only in one small
parameterizable string.

What was actually duplicated (read all 3 originals first, not assumed)

  • SetLanguage: Admin+Store only — Vendor never had this action (confirmed
    by reading Grand.Web.Vendor/Controllers/HomeController.cs directly, not by
    trusting an earlier grep). Putting it on a base Vendor also extends would have
    silently added a brand-new route to Vendor (MVC discovers every public action
    across the whole inheritance chain) — so it lives on a second-level base,
    BaseHomeControllerWithSetLanguage : BaseHomeController, used only by
    Admin/Store. Vendor extends the plain BaseHomeController directly. Same
    two-level split BaseOrderController/BaseOrderManagementController already
    established for Order's Vendor-is-a-subset shape.
  • GetStatesByCountryId's SelectState resource key: Admin and Store use the
    identical literal "Admin.Address.SelectState" — not "Store.Address.SelectState",
    which would be the naming-pattern guess from elsewhere in this initiative.
    Verified by reading Admin's own method (the earlier survey only diffed
    Store vs. Vendor). Only Vendor differs ("Vendor.Address.SelectState").
    Parameterized via an abstract SelectStateResourceKey property.
  • The empty-countryId-branch key ("Address.SelectState", no host prefix) is
    byte-identical across all 3 hosts — left as a shared literal, not parameterized.
  • The addSelectStateItem/result.Any() check-order difference between
    Admin/Store (nested if) and Vendor (combined &&) is confirmed cosmetic,
    not behavioral — logically equivalent for every input.
  • Logout's route name ("AdminLogin"/"StoreLogin"/"VendorLogin") is the
    one genuinely 3-way difference, parameterized via LogoutRouteName.

DashboardActivity/ChangeStore (Admin-only) and Index/Statistics/
AccessDenied (real per-host views) stay untouched on each concrete controller.

Found, explicitly out of scope

AccessDenied() is also byte-identical across all 3 hosts — missed by the
earlier repo-wide survey because its method-name search only matched async
Task<IActionResult> signatures, and AccessDenied is synchronous
(IActionResult). Flagged for a future micro-phase rather than folded into this
one's diff.

Tests

No prior coverage existed for any of the 3 originals. Added:

  • BaseHomeControllerTests — parameterization proven via two differently-configured
    test subclasses
    (not just one), covering GetStatesByCountryId's 4 branches,
    Logout, and SetLanguage's both redirect paths.
  • HomeControllerAttributeTests (Admin + Store).
  • HomeControllerSurfaceTests (Vendor) — asserts Vendor's HomeController does
    not declare SetLanguage, the exact regression the two-level-base design
    exists to prevent.

Verification

dotnet build GrandNode.sln — 0 errors. Per-project test runs (parallel
full-solution runs are known-flaky):

  • Grand.Web.Admin.Tests: 1440/1440
  • Grand.Web.Store.Tests: 142/142
  • Grand.Web.Vendor.Tests: 27/27

No live smoke test run this phase — deferred, disclosed here rather than silently
skipped: pure infra plumbing (language switch, logout, states dropdown), no
cross-tenant/access-control surface, same justification class as Phase 24/25.

…a actions

First infra-action (not domain-entity) consolidation in this initiative:
GetStatesByCountryId, Logout, and SetLanguage were duplicated across
HomeController in 2 or 3 of the 3 hosts, differing only in a small
parameterizable string each.

Findings from reading all 3 hosts' full HomeController before designing:
- SetLanguage is Admin+Store only - Vendor never had this action. Confirmed
  by reading Vendor's HomeController.cs directly (no grep-based assumption).
  Putting it on a base Vendor also inherits from would have silently added a
  new route to Vendor, since MVC discovers every public action across the
  whole inheritance chain - so it lives on a second-level base,
  BaseHomeControllerWithSetLanguage : BaseHomeController, used only by
  Admin/Store. Vendor extends BaseHomeController directly. Same two-level
  split BaseOrderController/BaseOrderManagementController already
  established for Order's Vendor-is-a-subset shape.
- GetStatesByCountryId's SelectState resource key: Admin and Store use the
  IDENTICAL literal "Admin.Address.SelectState" (not "Store.Address.SelectState"
  as might be assumed from the naming pattern seen elsewhere in this
  initiative) - verified by reading Admin's own method, not just the
  earlier Store-vs-Vendor diff. Only Vendor differs
  ("Vendor.Address.SelectState"). Parameterized via an abstract
  SelectStateResourceKey property.
- The empty-countryId branch's key ("Address.SelectState", no host prefix)
  is byte-identical across all 3 hosts - not parameterized, left as a shared
  literal in the base.
- The addSelectStateItem/result.Any() check-order difference between
  Admin/Store (nested if) and Vendor (combined &&) is confirmed COSMETIC,
  not behavioral - both forms are logically equivalent for every input.
- Logout's route name ("AdminLogin"/"StoreLogin"/"VendorLogin") is the one
  genuinely 3-way difference, parameterized via LogoutRouteName.

DashboardActivity/ChangeStore (Admin-only) and Index/Statistics/AccessDenied
(real per-host views) stay untouched on each concrete host controller.
Admin/Store/Vendor's HomeController restate their host's attribute set
explicitly (BaseHomeController extends the generic BaseController, not any
host's own base, same as BaseProductController/BasePictureController).

Found but explicitly out of scope: AccessDenied() is also byte-identical
across all 3 hosts - missed by the earlier repo-wide survey because its
method-name search only matched async Task<IActionResult> signatures and
AccessDenied is synchronous. Flagged for a future micro-phase, not folded in
here to keep this phase's diff to its assigned scope.

No prior test coverage existed for any of the 3 originals' HomeController.
Added BaseHomeControllerTests (parameterization proven via two differently-
configured test subclasses, not just one), HomeControllerAttributeTests for
Admin/Store, and HomeControllerSurfaceTests for Vendor (asserting Vendor's
HomeController does NOT declare SetLanguage, the regression this whole
two-level-base design exists to prevent).

No behavior change. Verified: dotnet build GrandNode.sln 0 errors. Per-project
test runs (parallel full-solution runs are known-flaky): Admin 1440/1440,
Store 142/142, Vendor 27/27.

No live smoke test run this phase - deferred, disclosed in the PR body (pure
infra plumbing, no cross-tenant/access-control surface).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013y3MqvZq7y1Uc5p4JZad2i
Copilot AI lite review requested due to automatic review settings September 11, 2026 01:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KrzysztofPajak
KrzysztofPajak merged commit 3f49a5b into develop Sep 11, 2026
6 checks passed
@KrzysztofPajak
KrzysztofPajak deleted the arch001/phase28-home-infra-consolidation branch September 11, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants