Modern .NET systems are increasingly embedding LLM capabilities to automate workflows, enrich user experiences, and accelerate development. This guide walks through a production-grade approach to integrating Claude AI into .NET applications—covering architecture, code-level implementation, security, and operational best practices.
1) Reference Architecture
A clean separation of concerns keeps your system maintainable and secure:
Core components
Client/UI (Web, Mobile, Blazor, SPA)
API Layer (ASP.NET Core Web API / Minimal APIs)
Application Services (Prompt builders, orchestration)
AI Gateway (typed client for Claude API)
Data Layer (SQL/NoSQL + vector store if needed)
Observability (logging, metrics, tracing)
Flow
Client sends request (e.g., “summarize this report”).
API validates, enriches context (user profile, permissions).
Application service constructs prompt + system instructions.
AI Gateway calls Claude API.
Response is post-processed (formatting, validation).
Persist logs/metadata; return structured result.
For scale: place the AI Gateway behind a message queue (e.g., Azure Service Bus) for async workloads and rate control.
2) Project Setup (.NET 8+)
Create a Web API:
dotnet new webapi -n ClaudeNetDemo
cd ClaudeNetDemo
dotnet add package System.Text.Json
Add configuration (appsettings.json):
{
"Claude": {
"ApiKey": "YOUR_API_KEY",
"Model": "claude-3-opus-20240229",
"BaseUrl": "https://api.anthropic.com/v1/messages",
"MaxTokens": 1024
}
}
Bind options:
public class ClaudeOptions
{
public string ApiKey { get; set; } = default!;
public string Model { get; set; } = default!;
public string BaseUrl { get; set; } = default!;
public int MaxTokens { get; set; }
}
builder.Services.Configure<ClaudeOptions>(
builder.Configuration.GetSection("Claude"));
builder.Services.AddHttpClient<IClaudeClient, ClaudeClient>();
3) Implementing a Typed Claude Client
Define contracts:
public record ClaudeMessage(string role, object content);
public record ClaudeRequest(
string model,
int max_tokens,
List<ClaudeMessage> messages,
string? system = null,
double? temperature = 0.2);
public record ClaudeTextContent(string type, string text);
public record ClaudeResponseContent(string type, string text);
public record ClaudeResponse(
string id,
string model,
List<ClaudeResponseContent> content);
Client implementation:
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Options;
public interface IClaudeClient
{
Task<string> GenerateAsync(string prompt, string? system = null, CancellationToken ct = default);
}
public class ClaudeClient : IClaudeClient
{
private readonly HttpClient _http;
private readonly ClaudeOptions _opts;
public ClaudeClient(HttpClient http, IOptions<ClaudeOptions> opts)
{
_http = http;
_opts = opts.Value;
_http.BaseAddress = new Uri(_opts.BaseUrl);
_http.DefaultRequestHeaders.Clear();
_http.DefaultRequestHeaders.Add("x-api-key", _opts.ApiKey);
_http.DefaultRequestHeaders.Add("anthropic-version", "2023-06-01");
_http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<string> GenerateAsync(string prompt, string? system = null, CancellationToken ct = default)
{
var req = new ClaudeRequest(
model: _opts.Model,
max_tokens: _opts.MaxTokens,
system: system,
messages: new List<ClaudeMessage>
{
new("user", new[] { new ClaudeTextContent("text", prompt) })
}
);
var json = JsonSerializer.Serialize(req);
using var content = new StringContent(json, Encoding.UTF8, "application/json");
using var response = await _http.PostAsync("", content, ct);
var body = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
throw new ApplicationException($"Claude API error: {response.StatusCode} - {body}");
var parsed = JsonSerializer.Deserialize<ClaudeResponse>(body,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var text = parsed?.content?.FirstOrDefault()?.text ?? string.Empty;
return text.Trim();
}
}
4) Application Service (Prompt Orchestration)
Encapsulate prompt construction and guardrails:
public interface IAiService
{
Task<string> SummarizeAsync(string input, CancellationToken ct = default);
}
public class AiService : IAiService
{
private readonly IClaudeClient _client;
public AiService(IClaudeClient client) => _client = client;
public Task<string> SummarizeAsync(string input, CancellationToken ct = default)
{
var system = "You are a concise, factual assistant. Avoid speculation. Output bullet points.";
var prompt = $"""
Summarize the following content into 5-7 bullet points:
---
{input}
---
""";
return _client.GenerateAsync(prompt, system, ct);
}
}
Register:
builder.Services.AddScoped<IAiService, AiService>();
5) Expose API Endpoints
Minimal API example:
app.MapPost("/ai/summarize", async (IAiService ai, HttpContext ctx) =>
{
using var reader = new StreamReader(ctx.Request.Body);
var input = await reader.ReadToEndAsync();
if (string.IsNullOrWhiteSpace(input))
return Results.BadRequest("Input required");
var result = await ai.SummarizeAsync(input);
return Results.Ok(new { result });
});
6) Advanced Patterns
a) Streaming Responses (Server-Sent Events)
For long outputs, stream tokens to the client. Use HttpCompletionOption.ResponseHeadersRead and forward chunks via SSE to improve UX.
b) Function Calling / Tool Use
Wrap deterministic operations (DB lookup, pricing calc) as tools. Let the model decide when to call them; execute server-side and feed results back into the conversation loop.
c) Retrieval-Augmented Generation (RAG)
Store embeddings in a vector DB (e.g., Azure AI Search, Pinecone).
Retrieve top-k relevant chunks.
Inject into the prompt as grounding context to reduce hallucinations.
7) Real-World Use Cases
Customer Support Copilot: Draft replies from ticket history; enforce tone & policy.
Document Intelligence: Summarize contracts, extract clauses, classify documents.
Code Assistance for .NET Teams: Generate scaffolding, refactor suggestions, test cases.
Healthcare & Compliance: Triage notes, generate summaries with strict system prompts and PII controls.
E-commerce Content: Product descriptions, FAQs, multilingual content at scale.
8) Security & Compliance
Secret Management: Store API keys in Azure Key Vault / environment variables; never in source.
PII Handling: Redact or tokenize sensitive fields before sending to the model.
Content Filtering: Add pre/post filters; reject unsafe prompts or outputs.
Audit Logging: Log prompts (hashed where needed), responses, latency, token usage.
Rate Limiting: Protect endpoints (ASP.NET rate limiting middleware) and queue heavy jobs.
9) Performance & Cost Control
Token Discipline: Keep prompts tight; use bullet instructions; limit max_tokens.
Caching: Cache deterministic prompts (e.g., identical summaries).
Batching: For offline jobs, batch requests through queues.
Model Selection: Use smaller/cheaper models for non-critical tasks; reserve premium models for high-value flows.
Timeouts & Retries: Configure Polly policies on HttpClient (exponential backoff, circuit breaker).
Example with Polly
builder.Services.AddHttpClient<IClaudeClient, ClaudeClient>()
.AddTransientHttpErrorPolicy(p => p.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(2 * i)))
.AddTransientHttpErrorPolicy(p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
10) Testing Strategy
Unit Tests: Mock IClaudeClient; validate prompt construction and parsing.
Contract Tests: Validate JSON schema against sample responses.
Load Tests: Simulate concurrency; ensure rate limits and queues behave.
Golden Files: Snapshot expected outputs for stable prompts.
11) Observability
Structured Logging (Serilog): include correlation IDs, latency, tokens.
Metrics: requests/sec, error rate, p95 latency, cost per request.
Tracing: OpenTelemetry across API → AI Gateway → external call.
12) Deployment Topology
Containerized API (Docker) on Azure App Service / AKS.
Background Workers for async AI jobs.
CDN + Edge for static assets; WAF for API protection.
Blue/Green or Canary releases when changing prompts/models.
13) Best Practices Checklist
Clear system prompts with constraints and format requirements
Centralized AI Gateway (no direct calls from controllers)
RAG for domain grounding; avoid blind generation
Rate limiting + queuing for burst control
PII redaction and secure key management
Caching and model tiering to manage cost
Continuous prompt iteration based on analytics
14) Common Pitfalls
Overly long prompts → high cost and latency
No grounding data → hallucinations
Mixing business logic in controllers instead of services
Lack of retries/circuit breakers → fragile integrations
Ignoring output validation (JSON schema, regex guards)
15) Minimal End-to-End Example (Controller + Service)
[ApiController]
[Route("api/ai")]
public class AiController : ControllerBase
{
private readonly IAiService _ai;
public AiController(IAiService ai) => _ai = ai;
[HttpPost("summarize")]
public async Task<IActionResult> Summarize([FromBody] string input, CancellationToken ct)
{
if (string.IsNullOrWhiteSpace(input))
return BadRequest("Input required");
var result = await _ai.SummarizeAsync(input, ct);
return Ok(new { result });
}
}
Closing
Integrating Claude AI into .NET is straightforward at the API level, but production success depends on architecture, guardrails, and operations. By introducing a dedicated AI Gateway, strong prompt discipline, and robust observability, you can deliver reliable, scalable AI features across enterprise .NET applications.