skills/microservice/controlpanel/gateway-facade/SKILL.md
Use when creating typed HttpClient wrappers for control panel API calls.
npx skillsauth add faysilalshareef/dotnet-ai-kit gateway-facadeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
HttpClient for calling gateway REST endpoints??= pattern) for management classesHttpExtensions provide consistent serialization and error handlingResponseResult<T> for uniform error handlingnamespace {Company}.{Domain}.ControlPanel.Gateways;
public sealed class OrderGateway(HttpClient http)
{
private OrderManagement? _orders;
private CustomerManagement? _customers;
public OrderManagement Orders => _orders ??= new(http);
public CustomerManagement Customers => _customers ??= new(http);
}
namespace {Company}.{Domain}.ControlPanel.Gateways;
public sealed class OrderManagement(HttpClient http)
{
private const string BaseRoute = "api/v1/orders";
public async Task<ResponseResult<Paginated<OrderSummaryResponse>>> GetAllAsync(
int page, int pageSize, string? search = null)
{
var url = $"{BaseRoute}?page={page}&pageSize={pageSize}";
if (!string.IsNullOrEmpty(search))
url += $"&search={Uri.EscapeDataString(search)}";
return await http.GetAsync<Paginated<OrderSummaryResponse>>(url);
}
public async Task<ResponseResult<OrderDetailResponse>> GetByIdAsync(Guid id)
=> await http.GetAsync<OrderDetailResponse>($"{BaseRoute}/{id}");
public async Task<ResponseResult<OrderResponse>> CreateAsync(
CreateOrderRequest request)
=> await http.PostAsJsonAsync<OrderResponse>(BaseRoute, request);
public async Task<ResponseResult<OrderResponse>> UpdateAsync(
Guid id, UpdateOrderRequest request)
=> await http.PutAsJsonAsync<OrderResponse>($"{BaseRoute}/{id}", request);
public async Task<ResponseResult<bool>> DeleteAsync(Guid id)
=> await http.DeleteAsync<bool>($"{BaseRoute}/{id}");
}
namespace {Company}.{Domain}.ControlPanel.Extensions;
public static class HttpExtensions
{
public static async Task<ResponseResult<T>> GetAsync<T>(
this HttpClient http, string url)
{
try
{
var response = await http.GetAsync(url);
return await HandleResponse<T>(response);
}
catch (Exception ex)
{
return ResponseResult<T>.Failure(ex.Message);
}
}
public static async Task<ResponseResult<T>> PostAsJsonAsync<T>(
this HttpClient http, string url, object content)
{
try
{
var response = await http.PostAsJsonAsync(url, content);
return await HandleResponse<T>(response);
}
catch (Exception ex)
{
return ResponseResult<T>.Failure(ex.Message);
}
}
public static async Task<ResponseResult<T>> PutAsJsonAsync<T>(
this HttpClient http, string url, object content)
{
try
{
var response = await http.PutAsJsonAsync(url, content);
return await HandleResponse<T>(response);
}
catch (Exception ex)
{
return ResponseResult<T>.Failure(ex.Message);
}
}
private static async Task<ResponseResult<T>> HandleResponse<T>(
HttpResponseMessage response)
{
if (response.IsSuccessStatusCode)
{
var data = await response.Content
.ReadFromJsonAsync<T>();
return ResponseResult<T>.Success(data!);
}
var problem = await response.Content
.ReadFromJsonAsync<ProblemDetails>();
return ResponseResult<T>.Failure(
problem?.Detail ?? $"HTTP {(int)response.StatusCode}");
}
}
public static IServiceCollection AddGatewayClients(
this IServiceCollection services, IConfiguration configuration)
{
var gatewayUrl = configuration["GatewayUrl"]!;
services.AddHttpClient<OrderGateway>(client =>
{
client.BaseAddress = new Uri(gatewayUrl);
});
return services;
}
| Anti-Pattern | Correct Approach | |---|---| | Direct HttpClient in components | Use gateway facade classes | | No error handling in HTTP calls | Wrap in try/catch, return ResponseResult | | Hardcoded URLs | Use BaseRoute constants and configuration | | Missing serialization handling | Use HttpExtensions for consistency |
# Find gateway classes
grep -r "Gateway.*HttpClient\|Management.*HttpClient" --include="*.cs" src/ControlPanel/
# Find HttpExtensions
grep -r "HttpExtensions\|GetAsync<\|PostAsJsonAsync<" --include="*.cs" src/ControlPanel/
# Find gateway registration
grep -r "AddHttpClient<.*Gateway" --include="*.cs" src/ControlPanel/
HttpExtensions for all HTTP callsResponseResult<T> from all management methodsdata-ai
Use when about to claim work is complete, fixed, passing, or ready — before committing, creating PRs, or moving to the next task. Requires running verification commands and confirming output before making any success claims.
development
Use when encountering any bug, test failure, build error, or unexpected behavior — before proposing fixes or making changes.
development
Use when checkpointing, wrapping up, or handing off an AI-assisted development session.
development
Use when following the Specification-Driven Development lifecycle from plan through ship.