Simple personal task and project management system built with .NET, Blazor, ASP.NET Core, and Aspire.
The application currently contains a Blazor web frontend, an API service, shared Aspire service defaults, and an Aspire app host that wires the services together.
- .NET 10
- ASP.NET Core
- Blazor interactive server components
- .NET Aspire app hosting and service discovery
- Bootstrap
AppHost.sln
+-- AppHost.AppHost Aspire orchestration project
+-- AppHost.ApiService ASP.NET Core API service
+-- AppHost.Web Blazor web frontend
+-- AppHost.ServiceDefaults Shared Aspire defaults
+-- Shared Shared class library
- Blazor web UI with Home, Counter, Weather, and Login pages.
- API service with sample weather endpoint.
- Login API endpoint that returns a temporary JWT-shaped token.
- Browser
localStoragetoken persistence. - Custom Blazor authentication state provider.
- Blazor route guard for pages marked with
[RequireAuthentication]. - Aspire service discovery between the web app and API service.
- .NET 10 SDK
- An IDE such as Visual Studio, Rider, or VS Code
- Trusted ASP.NET Core development certificate if you run HTTPS endpoints directly
To trust the local development certificate:
dotnet dev-certs https --trustThe recommended way is to run the Aspire app host:
dotnet run --project AppHost.AppHost/AppHost.AppHost.csprojThe Aspire dashboard will show the running webfrontend and apiservice projects, including their available URLs.
You can also run projects individually:
dotnet run --project AppHost.ApiService/AppHost.ApiService.csproj
dotnet run --project AppHost.Web/AppHost.Web.csprojDefault launch profile URLs:
- API HTTP:
http://localhost:5333 - API HTTPS:
https://localhost:7349 - Web HTTP:
http://localhost:5281 - Web HTTPS:
https://localhost:7024
GET /healthGET /weatherforecastReturns sample weather forecast data.
POST /api/auth
Content-Type: application/json
{
"username": "demo",
"password": "demo"
}Returns a temporary token:
{
"token": "..."
}The login logic is currently a placeholder and should be replaced with real user validation before production use.
/- Home page/login- Login page/counter- Protected counter page/weather- Weather page
Protected pages use the custom [RequireAuthentication] attribute and are checked by GuardedRouteView.
The web app stores the login token in browser localStorage. Because server middleware cannot read browser localStorage on page refresh, protected Blazor pages are guarded in the Blazor route layer instead of ASP.NET Core endpoint authorization middleware.
Important files:
AppHost.Web/Services/AuthService.csAppHost.Web/Services/TokenService.csAppHost.Web/Services/LocalStorageService.csAppHost.Web/Authentication/CustomAuthenticationStateProvider.csAppHost.Web/Authentication/RequireAuthenticationAttribute.csAppHost.Web/Components/GuardedRouteView.razorAppHost.Web/Components/Routes.razorAppHost.ApiService/Controllers/AuthController.cs
In development, the web app uses http://apiservice for the login API client to avoid local HTTPS certificate trust issues between services. Production uses https+http://apiservice.
Build the full solution:
dotnet buildBuild individual projects:
dotnet build AppHost.ApiService/AppHost.ApiService.csproj
dotnet build AppHost.Web/AppHost.Web.csprojIf the error mentions UntrustedRoot, trust the local development certificate:
dotnet dev-certs https --trustThe web login client is configured to use HTTP service discovery in Development to avoid this issue.
Do not use ASP.NET Core [Authorize] middleware for localStorage-only Blazor route protection. Use [RequireAuthentication] on the page and let GuardedRouteView check the Blazor authentication state.
localStorage requires JavaScript interop, which is not available during static prerender. Routes.razor disables prerendering:
@rendermode @(new InteractiveServerRenderMode(prerender: false))This usually means the app threw an unhandled startup exception. Ensure all service registrations, such as AddControllers(), happen before builder.Build().
The active login endpoint is:
POST /api/authUse /api/auth for login requests unless a separate user controller is added.
- Current authentication is for development only.
- The API currently returns a fake JWT-shaped token.
- Replace placeholder login logic with a real user store, password validation, and signed JWTs before production.
- Add tests once the authentication and project/task domain model are finalized.