Bike Rental Shop Web Client
Add a standalone Razor Pages frontend that talks to the BikeRentalShop API over HTTP while keeping the backend services focused on API concerns.
Full source
Files:
pwsh/tutorial/examples/BikeRentalShop/Web/README.mdpwsh/tutorial/examples/BikeRentalShop/Web/Service.ps1pwsh/tutorial/examples/BikeRentalShop/Web/Pages/Index.cshtmlpwsh/tutorial/examples/BikeRentalShop/Web/Pages/Operations.cshtmlpwsh/tutorial/examples/BikeRentalShop/Web/wwwroot/app.js
# Use the real BikeRentalShop web client from the tutorial examples.
pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Web\Service.ps1 -Port 5445 -Backend Synchronized
Step-by-step
- Entry point: The standalone web client source lives at
pwsh/tutorial/examples/BikeRentalShop/Web/Service.ps1; run the repo-local script from the checkout when you want to execute it. - Backend selection: The web service accepts
Synchronized,Concurrent, orCustomso the same frontend can point at any compatible bike-rental API. - HTTPS: The web client creates or reuses its own development certificate and binds a separate HTTPS listener.
- Razor runtime:
Add-KrPowerShellRazorPagesRuntimeenables page rendering while sibling.cshtml.ps1scripts build page data per request. - Browser assets: The service exposes
site.cssandapp.jsunder/staticso the frontend stays self-contained. - Page model flow: The service publishes backend metadata into script-scoped variables, and the page model scripts turn that into
ClientConfigJsonfor the browser. - CORS boundary: The browser calls the backend directly, so the backend must allow the web origin with
-AllowedCorsOrigins. - Operations flow: The same frontend supports customer booking and staff actions, but protected browser calls still go through the backend API key boundary.
Try it
Start the backend and web client together:
pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Synchronized\Service.ps1 -Port 5443 `
-AllowedCorsOrigins @('https://127.0.0.1:5445', 'https://localhost:5445')
pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Web\Service.ps1 -Port 5445 -Backend Synchronized
Open the browser-facing routes:
Invoke-WebRequest https://127.0.0.1:5445/ -SkipCertificateCheck | Select-Object StatusCode
Invoke-WebRequest https://127.0.0.1:5445/Operations -SkipCertificateCheck | Select-Object StatusCode
Invoke-WebRequest https://127.0.0.1:5445/static/site.css -SkipCertificateCheck | Select-Object StatusCode
Point the same frontend at the concurrent backend:
pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Concurrent\Service.ps1 -Port 5444 `
-AllowedCorsOrigins @('https://127.0.0.1:5445', 'https://localhost:5445')
pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Web\Service.ps1 -Port 5445 -Backend Concurrent
How the web flow works
- The web service renders
/and/Operationswith Razor Pages. - Each page includes a JSON config block with the backend base URL and the API paths the browser should call.
- The browser JavaScript loads the live bike catalog, rental health, and staff dashboard from the backend.
- Customer booking uses
POST /api/rentals, rental lookup usesGET /api/rentals/{rentalId}, and staff actions use the protected/api/staff/*routes. - The backend remains the system of record, so the web client never mutates local state directly.
Why keep the web client separate
- The backend samples stay focused on routing, persistence, authentication, and OpenAPI.
- The browser-facing service can evolve its layout, styles, and interaction logic without changing the backend API shape.
- CORS becomes explicit instead of hidden inside the backend routing layer.
- The same frontend can be pointed at a package-deployed backend or a custom endpoint by changing startup parameters.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| The home page loads but API calls fail in the browser | The backend was not started with the web origin in -AllowedCorsOrigins | Start the backend with both https://127.0.0.1:5445 and https://localhost:5445 |
| The page returns but looks unstyled | The /static asset routes are unavailable | Verify GET /static/site.css succeeds on the web service origin |
| Browser fetches fail with certificate warnings | The dev certificate is not trusted by the browser | Accept the certificate in the browser or trust it locally before testing cross-origin calls |
| The UI points at the wrong backend | The -Backend or -ApiBaseUrl startup option is incorrect | Restart the web service with -Backend Concurrent, -Backend Synchronized, or -Backend Custom -ApiBaseUrl ... |
References
- Add-KrPowerShellRazorPagesRuntime
- Add-KrStaticFilesMiddleware
- Add-KrEndpoint
- Write-KrFileResponse
- New-KrCorsPolicyBuilder
- Add-KrCorsPolicy
- Razor Guide
- CORS Tutorial
Previous / Next
Previous: Bike Rental Shop Application Next: Bike Rental Shop Backend Variants