Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions Analysis-of-AspNetCoreFeatures.Toggles-by-GitHub-Copilot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
## :bust_in_silhouette: (8/29/2026 7:18 AM)
Analyze this solution, tell me what it does, what it uses, and how it does it.
## :speech_balloon: GitHub Copilot
1. Read AspNetCoreFeatures.Toggles.sln, lines 1-300 :white_check_mark:

1. Read README.md, lines 1-260 :white_check_mark:
1. Read AspNetCoreFeatures.Toggles.Server.csproj, lines 1-220 :white_check_mark:
1. Read AspNetCoreFeatures.Toggles.Client.csproj, lines 1-220 :white_check_mark:
1. Read AspNetCoreFeatures.Toggles.Shared.csproj, lines 1-220 :white_check_mark:

1. Read Program.cs, lines 1-320 :white_check_mark:
1. Read Program.cs, lines 1-260 :white_check_mark:
1. Read appsettings.json, lines 1-260 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\appsettings.Development.json'. :negative_squared_cross_mark:

1. Read FeatureXService.cs, lines 1-220 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Controllers\FeatureXController.cs'. :negative_squared_cross_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Controllers\WeatherForecastController.cs'. :negative_squared_cross_mark:
1. Read Index.razor, lines 1-260 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Client\Pages\FeatureXPage.razor'. :negative_squared_cross_mark:
1. Read App.razor, lines 1-260 :white_check_mark:

1. Read NavMenu.razor, lines 1-320 :white_check_mark:
1. Read MainLayout.razor, lines 1-220 :white_check_mark:
1. Read _Host.cshtml, lines 1-320 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Controllers\WeatherForecastController.cs'. :negative_squared_cross_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Controllers\FeatureManagementController.cs'. :negative_squared_cross_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Controllers\DataEventRecordsController.cs'. :negative_squared_cross_mark:

1. Read DirectApi.razor, lines 1-320 :white_check_mark:
1. Read FeatureXApi.razor, lines 1-320 :white_check_mark:
1. Read GraphApiCall.razor, lines 1-320 :white_check_mark:
1. Read AccountController.cs, lines 1-320 :white_check_mark:
1. Read DirectApiController.cs, lines 1-320 :white_check_mark:
1. Read FeatureXApiController.cs, lines 1-320 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Controllers\GraphApiCallController.cs'. :negative_squared_cross_mark:

1. Read GraphApiCallsController.cs, lines 1-320 :white_check_mark:
1. Read MsGraphService.cs, lines 1-360 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Services\CaeClaimsChallengeService.cs'. :negative_squared_cross_mark:
1. Read SecurityHeadersDefinitions.cs, lines 1-360 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\UseNoUnauthorizedRedirectExtensions.cs'. :negative_squared_cross_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\NotFoundMapExtensions.cs'. :negative_squared_cross_mark:
1. Read Features.cs, lines 1-120 :white_check_mark:
1. Read AntiforgeryHttpClientFactory.cs, lines 1-320 :white_check_mark:
1. Read AuthorizedHandler.cs, lines 1-260 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Client\HostAuthenticationStateProvider.cs'. :negative_squared_cross_mark:
1. Found 1 results for symbol HostAuthenticationStateProvider :white_check_mark:

1. Read HostAuthenticationStateProvider.cs, lines 1-360 :white_check_mark:
1. Read IAntiforgeryHttpClientFactory.cs, lines 1-120 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\wwwroot\antiForgeryToken.js'. :negative_squared_cross_mark:
1. Read UserController.cs, lines 1-260 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Shared\UserInfo.cs'. :negative_squared_cross_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Controllers\ProfileController.cs'. :negative_squared_cross_mark:

1. Found 1 results for symbol UseNoUnauthorizedRedirect :white_check_mark:
1. Found 1 results for symbol MapNotFound :white_check_mark:
1. Found 1 results for symbol CaeClaimsChallengeService :white_check_mark:
1. Read antiForgeryToken.js, lines 1-120 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\wwwroot\js\antiForgeryToken.js'. :negative_squared_cross_mark:
1. Read UserInfo.cs, lines 1-260 :white_check_mark:
1. Read ClaimValue.cs, lines 1-220 :white_check_mark:

1. Read ApplicationBuilderExtensions.cs, lines 1-220 :white_check_mark:
1. Read EndpointRouteBuilderExtensions.cs, lines 1-220 :white_check_mark:
1. Read CaeClaimsChallengeService.cs, lines 1-320 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Cae\CaeUnauthorizedResultFilter.cs'. :negative_squared_cross_mark:
1. Read GraphApiCallsController.cs, lines 1-320 :white_check_mark:
1. No results found for symbol CheckForRequiredAuthContextIdToken :white_check_mark:
1. Found 3 results for symbol FEATUREX :white_check_mark:
1. Found 1 results for symbol CaeClaimsChallengeService :white_check_mark:
1. No results found for symbol GetGraphApiProfilePhoto :white_check_mark:

1. Read _Imports.razor, lines 1-220 :white_check_mark:
1. Read appsettings.json, lines 1-220 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Client\wwwroot\appsettings.Development.json'. :negative_squared_cross_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Pages\_Layout.cshtml'. :negative_squared_cross_mark:
1. Read Error.cshtml, lines 1-220 :white_check_mark:
1. Couldn't run get_tests :negative_squared_cross_mark:
1. No tests found matching filters: Outcome=None :white_check_mark:
1. Read dotnet.yml, lines 1-260 :white_check_mark:

1. Read launchSettings.json, lines 1-260 :white_check_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Client\Properties\launchSettings.json'. :negative_squared_cross_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Pages\_ViewImports.cshtml'. :negative_squared_cross_mark:
1. Couldn't find file 'D:\GitHub\AspNetCoreFeatures.Toggles\Server\Pages\_ViewStart.cshtml'. :negative_squared_cross_mark:
1. Read Error.cshtml.cs, lines 1-200 :white_check_mark:
1. No results found for symbol AntiForgeryTokenInput :white_check_mark:
1. Read AntiForgeryTokenInput.razor, lines 1-120 :white_check_mark:
### Solution Summary

This is a **hosted Blazor WebAssembly app** on **.NET 10** that demonstrates **feature toggles** with authenticated API access.

It has 3 projects:

- `Server` (`Microsoft.NET.Sdk.Web`)
- `Client` (`Microsoft.NET.Sdk.BlazorWebAssembly`)
- `Shared` (shared DTO/constants)

---

### What it does

- Uses **Microsoft Entra ID / Azure AD** sign-in with **cookie auth**.
- Exposes secured server APIs:
- `api/DirectApi`
- `api/FeatureXApi`
- `api/GraphApiCalls`
- auth endpoints in `api/Account/*`
- current user endpoint `api/User`
- Shows/hides functionality via a feature flag (`FeatureX`):
- menu item visibility in `Client/Shared/NavMenu.razor`
- page behavior in `Client/Pages/FeatureXApi.razor`
- API behavior in `Server/Controllers/FeatureXApiController.cs`
- Calls Microsoft Graph (`Me`) and returns profile fields.
- Applies strict security defaults (CSP, HSTS, anti-forgery, removed server header).

---

### What it uses

- **Feature flags**
- `Microsoft.FeatureManagement` (client)
- `Microsoft.FeatureManagement.AspNetCore` (server)
- Feature key constant in `Shared/Features.cs`
- Configured in both:
- `Server/appsettings.json`
- `Client/wwwroot/appsettings.json`
- **Identity and Graph**
- `Microsoft.Identity.Web`
- `Microsoft.Identity.Web.UI`
- `Microsoft.Identity.Web.GraphServiceClient`
- **Security**
- `NetEscapades.AspNetCore.SecurityHeaders`
- Anti-forgery token flow with JS helper `Client/wwwroot/antiForgeryToken.js`
- **Image processing**
- `Magick.NET-Q16-AnyCPU` (used in `MsGraphService.GetGraphApiProfilePhoto`, currently not wired to a controller route)

---

### How it works (request flow)

1. App boots from Razor Page host `Server/Pages/_Host.cshtml` and loads Blazor WASM.
2. `Client/Services/HostAuthenticationStateProvider.cs` fetches `api/User` to determine auth state.
3. If unauthorized, client redirects to `api/Account/Login`.
4. For secured API calls, client adds anti-forgery header (`X-XSRF-TOKEN`) via `AntiforgeryHttpClientFactory`.
5. Server validates anti-forgery and cookie auth on API controllers.
6. Feature X is checked with `IFeatureManager` on both client and server.
7. Graph endpoint uses delegated scopes and `GraphServiceClient`.

---

### Notable implementation details

- `FeatureXService` is only registered when `FeatureManagement:FeatureX` is `true` in server config (`Program.cs`).
- `UseNoUnauthorizedRedirect("/api")` marks API calls as AJAX to avoid redirect-style auth behavior.
- `MapNotFound("/api/{**segment}")` forces unmapped API routes to return HTTP 404.
- CI workflow (`.github/workflows/dotnet.yml`) restores/builds/tests on .NET 10.
- No test cases are currently discovered in Test Explorer (`Outcome=None` returned no tests).