Course assignment – .NET Fullstack
This project is a Razor Pages client application that consumes the GoodFriends WebAPI. The application allows viewing, creating, updating, and deleting friends, pets, and quotes.
Focus areas:
- API integration via HttpClient
- DTO mapping
- Razor Pages architecture
- Validation and ModelState handling
- Relationship loading (Friends ↔ Pets ↔ Quotes)
- ASP.NET Core Razor Pages
- Service layer:
GoodFriendsApiClient - DTO-based communication with WebAPI
- TempData + PRG pattern for post actions
All data is retrieved via REST endpoints:
/api/Friends/api/Pets/api/Quotes/api/Overview/api/Admin
The client does not access the database directly.
- List friends
- View details
- Edit friend information
- View address
- Add pet to friend
- Delete pet
- Show pets per friend
- Add quote
- Delete quote
- Show quotes per friend
- Friends per country
- Friends per city
- City drill-down with pets
Symptoms:
- Sometimes all pets/quotes appeared for all friends
- Sometimes none appeared
Root cause:
-
The API returned relationship data in different shapes depending on endpoint and seed state:
friendIdfriendIds- embedded
friends[]
-
Server-side filtering was therefore unreliable.
Client-side filtering added in GoodFriendsApiClient:
Quotes and pets are matched against:
friendIdfriendIds- embedded
friends
Additionally:
- Relations are explicitly loaded in
GetFriendDetailsAsync() - Pets and quotes are fetched separately and mapped per friend
Result:
- Correct relation mapping
- Stable rendering of Friend Details
- No dependency on inconsistent API payload structures
The page contains multiple forms:
- Add Pet
- Add Quote
ModelState cleanup is used to ensure only the active form is validated:
- Quote keys removed when validating Pet
- Pet keys removed when validating Quote
This prevents cross-form validation errors.
Centralized HTTP error handling:
EnsureSuccessWithBodyAsync- Returns status + body for debugging
Validation responses (400):
- Parsed into field-level errors
- Displayed in UI
- Avoid heavy
flat=falsequeries where possible - Load relations explicitly for stability
- Use DTO mapping instead of direct API models
- PRG pattern used for POST actions
- Client resilient to API payload variations
- API contract is inconsistent regarding relationship structure
- Client-side filtering required as workaround
- Performance could improve if API enforced strict schema
- Enforce consistent API relationship contract
- Introduce caching for overview endpoints
- Add pagination for quotes/pets
- Move filtering logic to API once schema stabilizes
- .NET SDK
- GoodFriends WebAPI running locally
- User Secrets configured
-
Start WebAPI
-
Start Razor project
-
Navigate to:
/Friends/Overview/Friends/Details/{id}
Johan Persson .NET Fullstack student