This sample demonstrates a Blazor Server web application using Microsoft Agent Framework (MAF) with Claude models deployed in Microsoft Foundry. It provides a modern, interactive chat interface for real-time conversations with Claude using the elbruno.Extensions.AI.Claude NuGet package.
- Framework: Blazor Server (.NET 10) + Microsoft Agent Framework
- AI Model: Claude (Haiku, Sonnet, or Opus) via Microsoft Foundry
- Pattern: Interactive web chat with dependency injection
- Key Package: elbruno.Extensions.AI.Claude - provides seamless Claude integration
- Key Features: Real-time chat, streaming responses, modern UI
- Create a Microsoft Foundry project
- Deploy a Claude model (e.g.,
claude-haiku-4-5,claude-sonnet-4-5) - Note your:
- Claude Endpoint:
https://<resource-name>.services.ai.azure.com/anthropic/v1/messages - API Key: From Azure portal
- Deployment Name: Your Claude model deployment name
- Claude Endpoint:
- .NET 10 SDK or later
Set user secrets for the project:
cd samples/MAF/MAF-AIWebChatApp-FoundryClaude
dotnet user-secrets set "endpointClaude" "https://<resource-name>.services.ai.azure.com/anthropic/v1/messages"
dotnet user-secrets set "apikey" "<your-api-key>"
dotnet user-secrets set "deploymentName" "claude-haiku-4-5"# Navigate to the project directory
cd samples/MAF/MAF-AIWebChatApp-FoundryClaude
# Restore dependencies
dotnet restore
# Run the application
dotnet run
# Open your browser to https://localhost:5001 (or the URL shown in console)- Clean, gradient-themed UI
- Message bubbles for user and assistant
- Smooth animations and transitions
- Responsive design
- Send messages with Enter key (Shift+Enter for new line)
- Loading indicator while Claude thinks
- Auto-scroll to latest messages
- Disabled input during processing
- Claude agent registered via dependency injection
- Persistent agent instance across requests
- Error handling and logging
- Blazor Server interactive rendering
MAF-AIWebChatApp-FoundryClaude/
├── Program.cs # App configuration and DI setup
├── ClaudeToOpenAIMessageHandler.cs # HTTP handler for Claude API
├── Components/
│ ├── App.razor # Root component
│ ├── Routes.razor # Routing configuration
│ ├── Layout/
│ │ └── MainLayout.razor # Main layout
│ └── Pages/
│ └── Home.razor # Chat UI page
├── wwwroot/
│ └── app.css # Application styles
├── appsettings.json # App configuration
└── README.md # This file
// Configure Claude IChatClient
builder.Services.AddSingleton<IChatClient>(_ =>
{
var customHttpMessageHandler = new ClaudeToOpenAIMessageHandler
{
AzureClaudeDeploymentUrl = endpointClaude,
ApiKey = apiKey,
Model = deploymentName
};
HttpClient customHttpClient = new(customHttpMessageHandler);
var transport = new HttpClientPipelineTransport(customHttpClient);
return new AzureOpenAIClient(
endpoint: new Uri(endpoint),
credential: new ApiKeyCredential(apiKey),
options: new AzureOpenAIClientOptions { Transport = transport })
.GetChatClient(deploymentName)
.AsIChatClient()
.AsBuilder()
.Build();
});
// Register AI Agent
builder.Services.AddSingleton<AIAgent>(sp =>
{
var chatClient = sp.GetRequiredService<IChatClient>();
return chatClient.CreateAIAgent(
name: "ClaudeChat",
instructions: "You are a helpful and friendly AI assistant..."
);
});@inject AIAgent Agent
private async Task SendMessage()
{
_messages.Add(new ChatMessage("user", userMessage));
_isLoading = true;
StateHasChanged();
try
{
var response = await Agent.RunAsync(userMessage);
_messages.Add(new ChatMessage("assistant", response.Text));
}
finally
{
_isLoading = false;
StateHasChanged();
}
}- Header: Gradient background with app title
- Message Area: Scrollable conversation history
- User Messages: Blue gradient bubbles, right-aligned
- Claude Messages: White bubbles with border, left-aligned
- Input Area: Multi-line textarea with send button
- Enter: Send message
- Shift+Enter: New line in message
For production use, consider:
- Authentication: Add user authentication (Azure AD, Identity, etc.)
- Rate Limiting: Implement request throttling
- Session Management: Persist conversation history
- HTTPS: Ensure secure connections
- Logging: Enhanced logging and Application Insights
- Scalability: Consider Azure App Service or Azure Container Apps
For deployment environments, use environment variables instead of user secrets:
export endpoint="https://<resource-name>.cognitiveservices.azure.com"
export endpointClaude="https://<resource-name>.services.ai.azure.com/anthropic/v1/messages"
export apikey="<your-api-key>"
export deploymentName="claude-haiku-4-5"Potential improvements:
- Streaming Responses: Display tokens as they arrive
- Conversation History: Save and load past conversations
- Multiple Threads: Support multiple conversation threads
- Markdown Rendering: Render formatted responses
- File Attachments: Support document upload
- Function Calling: Add tools/functions for the agent
- MAF-FoundryClaude-01: Basic console chat with Claude
- MAF-FoundryClaude-Persisting-01: Console chat with conversation persistence
- MAF-AIWebChatApp-Simple: Web chat with OpenAI models
- Blazor Documentation
- Microsoft Agent Framework
- Microsoft Foundry - Claude Models
- Claude API Documentation
- Microsoft.Extensions.AI
- Verify .NET 10 SDK is installed
- Check user secrets are configured correctly
- Ensure ports 5000/5001 are available
- Verify API key and endpoints in user secrets
- Check Claude model deployment status in Azure
- Review application logs for detailed error messages
- Ensure
@rendermode InteractiveServeris set on the page - Check browser console for JavaScript errors
- Verify Blazor SignalR connection is established
This sample is part of the Generative AI for Beginners .NET course and follows the repository's MIT license.