# Maui Rest Api

> >

- **Type:** Skill
- **Install:** `agentstack add skill-davidortinau-maui-skills-maui-rest-api`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [davidortinau](https://agentstack.voostack.com/s/davidortinau)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [davidortinau](https://github.com/davidortinau)
- **Source:** https://github.com/davidortinau/maui-skills/tree/main/plugins/maui-skills/skills/maui-rest-api

## Install

```sh
agentstack add skill-davidortinau-maui-skills-maui-rest-api
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# REST API Consumption — Gotchas & Best Practices

## Common Mistakes

### 1. Creating HttpClient per request

```csharp
// ❌ 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()

```csharp
// ❌ Deadlocks on the UI thread
var items = _apiService.GetItemsAsync().Result;

// ✅ Always use async/await
var items = await _apiService.GetItemsAsync();
```

### 3. Deserializing before checking status

```csharp
// ❌ 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

```csharp
// ❌ 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

```csharp
// ❌ 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.xml` with `cleartextTrafficPermitted="true"` for `10.0.2.2`
- **iOS/Mac Catalyst**: needs `NSAllowsLocalNetworking` in `Info.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.

```csharp
// ❌ 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.

```csharp
// ❌ 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

- [ ] `HttpClient` registered as singleton or via `IHttpClientFactory` — never created per-request
- [ ] `BaseAddress` set in DI; service methods use relative URIs
- [ ] `JsonSerializerOptions` with `CamelCase` policy applied consistently
- [ ] `IsSuccessStatusCode` or `EnsureSuccessStatusCode()` checked before deserializing
- [ ] `try/catch` for `HttpRequestException` and `JsonException` in ViewModel calls
- [ ] All API calls use `async/await` — no `.Result` or `.Wait()`
- [ ] Service interface pattern used so ViewModels depend on abstractions
- [ ] Android clear-text config for local dev (`10.0.2.2`)
- [ ] iOS `NSAllowsLocalNetworking` for 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](https://github.com/davidortinau)
- **Source:** [davidortinau/maui-skills](https://github.com/davidortinau/maui-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-davidortinau-maui-skills-maui-rest-api
- Seller: https://agentstack.voostack.com/s/davidortinau
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
