Install
$ agentstack add skill-davidortinau-maui-skills-maui-rest-api ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
REST API Consumption — Gotchas & Best Practices
Common Mistakes
1. Creating HttpClient per request
// ❌ Creates socket exhaustion — each instance opens a new connection
public async Task> GetItemsAsync()
{
using var client = new HttpClient();
var response = await client.GetAsync("https://api.example.com/items");
// ...
}
// ✅ Register once in DI, inject everywhere
builder.Services.AddSingleton(sp => new HttpClient
{
BaseAddress = new Uri("https://api.example.com")
});
2. Blocking with .Result or .Wait()
// ❌ Deadlocks on the UI thread
var items = _apiService.GetItemsAsync().Result;
// ✅ Always use async/await
var items = await _apiService.GetItemsAsync();
3. Deserializing before checking status
// ❌ Tries to deserialize error HTML/JSON as your model
var content = await response.Content.ReadAsStringAsync();
var items = JsonSerializer.Deserialize>(content, _jsonOptions);
// ✅ Check status first
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
var items = JsonSerializer.Deserialize>(content, _jsonOptions) ?? [];
4. Hardcoding BaseAddress in service methods
// ❌ Absolute URIs in every method — hard to change, easy to typo
await _httpClient.GetAsync("https://api.example.com/api/items");
// ✅ Set BaseAddress in DI, use relative URIs in methods
await _httpClient.GetAsync("api/items");
5. Missing error handling for network failures
// ❌ Crashes on network timeout, DNS failure, etc.
var items = await _apiService.GetItemsAsync();
// ✅ Catch both network and deserialization errors
try
{
var items = await _apiService.GetItemsAsync();
}
catch (HttpRequestException ex) { /* network or HTTP error */ }
catch (JsonException ex) { /* malformed response */ }
Platform Pitfalls
⚠️ Clear-text HTTP blocked on emulators/simulators
Local dev servers on http:// are blocked by default. Configure exceptions:
- Android: needs
network_security_config.xmlwithcleartextTrafficPermitted="true"for10.0.2.2 - iOS/Mac Catalyst: needs
NSAllowsLocalNetworkinginInfo.plist
⚠️ Android emulator uses 10.0.2.2 for localhost
The Android emulator maps 10.0.2.2 to the host machine. localhost refers to the emulator itself.
// ❌ On Android emulator, this hits the emulator, not your dev machine
new Uri("http://localhost:5000")
// ✅ Use the emulator's host loopback address
new Uri("http://10.0.2.2:5000")
iOS simulators use localhost directly.
⚠️ Inconsistent JSON casing
APIs typically use camelCase; C# properties are PascalCase. Without JsonSerializerOptions, deserialization silently returns default values.
// ❌ Properties stay null/default — no error thrown
JsonSerializer.Deserialize(content);
// ✅ Configure casing policy
private static readonly JsonSerializerOptions _jsonOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true
};
Decision Framework
| Scenario | Error handling approach | |---|---| | Failure is unexpected (auth'd endpoints) | EnsureSuccessStatusCode() — throws HttpRequestException | | Need to branch on status codes | Check IsSuccessStatusCode or response.StatusCode | | Network may be unreliable (mobile) | Wrap in try/catch for HttpRequestException | | Response format may vary | Also catch JsonException |
Checklist
- [ ]
HttpClientregistered as singleton or viaIHttpClientFactory— never created per-request - [ ]
BaseAddressset in DI; service methods use relative URIs - [ ]
JsonSerializerOptionswithCamelCasepolicy applied consistently - [ ]
IsSuccessStatusCodeorEnsureSuccessStatusCode()checked before deserializing - [ ]
try/catchforHttpRequestExceptionandJsonExceptionin ViewModel calls - [ ] All API calls use
async/await— no.Resultor.Wait() - [ ] Service interface pattern used so ViewModels depend on abstractions
- [ ] Android clear-text config for local dev (
10.0.2.2) - [ ] iOS
NSAllowsLocalNetworkingfor local dev
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: davidortinau
- Source: davidortinau/maui-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.