A production-ready document summarization API built on .NET 8 using Azure OpenAI. This service provides intelligent document summarization with multiple style options (Executive, Risks, Actions, Technical) and comprehensive error handling.
- Multiple summarization styles optimized for different use cases
- Clean architecture with testable components
- Global exception handling with structured logging
- Input validation with detailed error responses
- Health check endpoint for monitoring
- Swagger/OpenAPI documentation
The service follows clean architecture principles with clear separation of concerns:
Program.cs
|
+-- ProblemDetailsExtensions (Exception handling)
|
+-- Endpoint (SummarizeEndpoints)
|
+-- Service (IDocumentSummaryService -> DocumentSummaryService)
|
+-- Client (IAzureOpenAiClient -> AzureOpenAiClient)
|
+-- Azure OpenAI
Key Components:
Program.cs: Application entry point with DI registration and middleware configurationSummarizeEndpoints: Minimal API endpoint mappingDocumentSummaryService: Business logic for document summarizationAzureOpenAiClient: Integration with Azure OpenAI serviceProblemDetailsExtensions: RFC 7807 ProblemDetails exception handling
- .NET 8 SDK
- Azure OpenAI resource with a deployed model
- Azure OpenAI API key and endpoint
-
Clone and restore dependencies:
git clone <repository-url> cd adl-docs-service dotnet restore
-
Configure Azure OpenAI settings:
Create or update
src/Api/appsettings.Development.json:{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AzureOpenAi": { "Endpoint": "https://your-resource.openai.azure.com/", "DeploymentName": "your-deployment-name", "ApiKey": "your-api-key-here" } }Recommended: Use .NET User Secrets for API keys:
cd src/Api dotnet user-secrets init dotnet user-secrets set "AzureOpenAi:Endpoint" "https://your-resource.openai.azure.com/" dotnet user-secrets set "AzureOpenAi:ApiKey" "your-api-key-here" dotnet user-secrets set "AzureOpenAi:DeploymentName" "your-deployment-name"
-
Run tests:
dotnet test -
Run the application:
cd src/Api dotnet runThe API will be available at
http://localhost:5135
GET http://localhost:5135/healthResponse:
OK
POST http://localhost:5135/api/summarize
Content-Type: application/json
{
"text": "Your document text here...",
"title": "Document Title",
"style": "Executive"
}Request Parameters:
text(required): The document text to summarizetitle(optional): Document title for contextstyle(optional): Summarization style -Executive(default),Risks,Actions, orTechnical
Response (200 OK):
{
"summary": "Generated summary text...",
"originalLength": 245,
"model": "gpt-4",
"generatedAt": "2024-11-25T18:30:00Z",
"style": "Executive"
}Error Response (400 Bad Request):
{
"error": "Validation failed",
"details": {
"Text": ["The Text field is required."]
}
}Error Response (500 Internal Server Error):
{
"error": "An error occurred while processing your request",
"details": "Detailed error information (in development only)"
}Executive Summary (Default):
POST http://localhost:5135/api/summarize
Content-Type: application/json
{
"text": "This is a long document that needs to be summarized. It contains multiple sentences and paragraphs of information that should be condensed into a brief summary. The document discusses various topics including business strategy, financial performance, and operational challenges.",
"title": "Q4 Business Review"
}Risk Analysis:
POST http://localhost:5135/api/summarize
Content-Type: application/json
{
"text": "The project is currently behind schedule due to resource constraints. Budget overruns have been identified in three key areas. Technical debt is accumulating in the legacy systems. Vendor dependencies pose potential delivery risks.",
"title": "Project Status Report",
"style": "Risks"
}Action Items:
POST http://localhost:5135/api/summarize
Content-Type: application/json
{
"text": "Meeting notes: Team agreed to refactor the authentication module by end of Q1. John will coordinate with the security team. Sarah needs to update the API documentation. We must schedule a review meeting next week.",
"style": "Actions"
}Technical Summary:
POST http://localhost:5135/api/summarize
Content-Type: application/json
{
"text": "The system uses a microservices architecture with event-driven communication via message queues. Authentication is handled through OAuth2 with JWT tokens. Data persistence layer implements repository pattern with Entity Framework Core.",
"style": "Technical"
}The service requires three configuration values:
| Setting | Description | Example |
|---|---|---|
AzureOpenAi:Endpoint |
Azure OpenAI resource endpoint URL | https://your-resource.openai.azure.com/ |
AzureOpenAi:ApiKey |
Azure OpenAI API key | abc123... |
AzureOpenAi:DeploymentName |
Deployed model name | gpt-4 |
Configuration sources (in priority order):
- .NET User Secrets (recommended for local development)
- Environment variables
appsettings.Development.json/appsettings.json
| Style | Use Case | Output Focus |
|---|---|---|
Executive |
High-level business summaries | Key points and strategic insights |
Risks |
Risk assessment and analysis | Potential issues, threats, and concerns |
Actions |
Action item extraction | Tasks, decisions, and next steps |
Technical |
Technical documentation | Technical details and implementation notes |
adl-docs-service/
├── src/Api/
│ ├── Configuration/ # Configuration and extension methods
│ ├── Endpoints/ # Minimal API endpoints (SummarizeEndpoints)
│ ├── Models/ # Request/response DTOs
│ ├── Services/ # Business logic and Azure OpenAI integration
│ ├── Program.cs # Application entry point
│ └── appsettings.json # Application configuration
└── tests/Api.Tests/ # Integration and unit tests
Run all tests:
dotnet testRun tests with coverage:
dotnet test --collect:"XPlat Code Coverage"The test suite includes:
- Integration tests using WebApplicationFactory
- Service layer unit tests with mocked dependencies
- Input validation tests
- Error handling tests
When running in Development mode, Swagger UI is available at:
http://localhost:5135/swagger
The project includes:
Api.httpfile for testing endpoints in Rider/Visual Studio- Swagger/OpenAPI for API exploration
- Structured logging with configurable log levels
This service is designed to be deployed as a container or to Azure App Service.
For a full example of production-ready Bicep infrastructure (App Service, APIM, Service Bus, monitoring, etc.), see:
adl-m365-automation-starter- Azure + M365 integration, Logic Apps, Service Bus, APIM, Bicep.HoldThatThread- .NET 8 reasoning chat service with Bicep infra and APIM configuration.
A simple Docker-based deployment example is provided below.
You can run the API in a local Docker container:
docker build -t adl-docs-service .
docker run -p 8080:8080 \
-e AzureOpenAi__Endpoint="https://your-endpoint.openai.azure.com" \
-e AzureOpenAi__ApiKey="your-api-key" \
-e AzureOpenAi__DeploymentName="your-deployment-name" \
adl-docs-serviceThe API will be available at http://localhost:8080.
See the Configuration section above for details on required settings.
MIT License - see LICENSE file for details