This commit implements a complete rebranding of the project: - Updated all namespaces from `DocumentOperator` to `DocumentService`. - Renamed file paths, embedded resources, and test data references. - Updated configuration keys, logging paths, and Redis instance names. - Revised documentation to reflect the new project name. - Modified project and solution files to align with the new structure. - Updated class names, DTOs, commands, queries, and handlers. - Adjusted middleware, controllers, and API endpoints. - Updated Swagger metadata and API titles to `DocumentService API`. - Refactored test namespaces, resource paths, and embedded resources. - Updated build and deployment configurations for the new name. - Replaced all references to `DocumentOperator` in comments and literals. These changes ensure consistency across the codebase and documentation.
147 lines
5.1 KiB
C#
147 lines
5.1 KiB
C#
using Serilog;
|
|
using Serilog.Ui.Core.Extensions;
|
|
using Serilog.Ui.SqliteDataProvider.Extensions;
|
|
using Serilog.Ui.Web.Extensions;
|
|
using Scalar.AspNetCore;
|
|
using DocumentService.Infrastructure.Configuration;
|
|
using DocumentService.Application;
|
|
using DocumentService.Application.Common.Configuration;
|
|
using DocumentService.Infrastructure;
|
|
using DocumentService.API.Middleware;
|
|
using DocumentService.API.Configuration;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// ========================================
|
|
// 1. Serilog Configuration
|
|
// ========================================
|
|
Log.Logger = new LoggerConfiguration()
|
|
.ReadFrom.Configuration(builder.Configuration)
|
|
.Enrich.FromLogContext()
|
|
.Enrich.WithProperty("Application", "DocumentService")
|
|
.CreateLogger();
|
|
|
|
builder.Host.UseSerilog();
|
|
|
|
Log.Information("Starting DocumentService API...");
|
|
|
|
try
|
|
{
|
|
// ========================================
|
|
// 2. Options Pattern Configuration
|
|
// ========================================
|
|
builder.Services.Configure<DocumentServiceSettings>(
|
|
builder.Configuration.GetSection(DocumentServiceSettings.SectionName));
|
|
|
|
builder.Services.Configure<ZugferdSettings>(
|
|
builder.Configuration.GetSection("ZugferdSettings"));
|
|
|
|
builder.Services.Configure<RedisSettings>(
|
|
builder.Configuration.GetSection(RedisSettings.SectionName));
|
|
|
|
builder.Services.Configure<ApiKeySettings>(
|
|
builder.Configuration.GetSection(ApiKeySettings.SectionName));
|
|
|
|
builder.Services.Configure<SwaggerSettings>(
|
|
builder.Configuration.GetSection(SwaggerSettings.SectionName));
|
|
|
|
// ========================================
|
|
// 3. Services (Clean Architecture Layers)
|
|
// ========================================
|
|
builder.Services.AddApplication(builder.Configuration); // Application Layer (MediatR, FluentValidation, Behaviors)
|
|
builder.Services.AddInfrastructure(); // Infrastructure Layer (DevExpress, Services)
|
|
|
|
builder.Services.AddControllers(); // Controllers (Controller-based API)
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerDocumentation(builder.Configuration);
|
|
|
|
// ========================================
|
|
// 4. Serilog.UI Configuration
|
|
// ========================================
|
|
var logDirectory = builder.Configuration.GetValue<string>("Application:LogDirectory")
|
|
?? throw new InvalidOperationException("Application:LogDirectory not found in configuration.");
|
|
var sqliteDbPath = Path.Combine(logDirectory, "logs.db");
|
|
|
|
builder.Services.AddSerilogUi(logUIOpt =>
|
|
{
|
|
logUIOpt.UseSqliteServer(dbOpt =>
|
|
{
|
|
dbOpt.WithConnectionString($"Data Source={sqliteDbPath}");
|
|
dbOpt.WithTable("Logs");
|
|
});
|
|
});
|
|
|
|
// ========================================
|
|
// 5. Build App
|
|
// ========================================
|
|
var app = builder.Build();
|
|
|
|
// ========================================
|
|
// 5. Middleware Pipeline (Order matters!)
|
|
// ========================================
|
|
|
|
// Exception Handling FIRST (catches all exceptions from subsequent middleware)
|
|
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
|
|
|
// ========================================
|
|
// Swagger/OpenAPI (Conditional based on settings)
|
|
// ========================================
|
|
var swaggerSettings = builder.Configuration.GetSection(SwaggerSettings.SectionName).Get<SwaggerSettings>()
|
|
?? new SwaggerSettings();
|
|
|
|
if (app.Environment.IsDevelopment() || swaggerSettings.EnableInProduction)
|
|
{
|
|
app.UseSwagger();
|
|
|
|
// Swagger UI (classic)
|
|
app.UseSwaggerUI(options =>
|
|
{
|
|
options.SwaggerEndpoint($"/swagger/{swaggerSettings.Version}/swagger.json",
|
|
$"{swaggerSettings.Title} {swaggerSettings.Version}");
|
|
options.RoutePrefix = "swagger"; // /swagger
|
|
});
|
|
|
|
// Scalar UI (modern alternative)
|
|
app.MapScalarApiReference(options =>
|
|
{
|
|
options
|
|
.WithTitle(swaggerSettings.Title)
|
|
.WithTheme(ScalarTheme.DeepSpace)
|
|
.WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);
|
|
});
|
|
}
|
|
|
|
app.UseSerilogRequestLogging(); // Log HTTP Requests
|
|
|
|
app.UseHttpsRedirection();
|
|
|
|
// ========================================
|
|
// 6. Serilog.UI Dashboard
|
|
// ========================================
|
|
app.UseSerilogUi(); // Accessible at /serilog-ui
|
|
|
|
// ========================================
|
|
// 7. Endpoints (Controller-based API)
|
|
// ========================================
|
|
app.MapControllers(); // Maps all [ApiController] controllers
|
|
|
|
Log.Information("DocumentService API started successfully");
|
|
|
|
app.Run();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Fatal(ex, "Application startup failed");
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
Log.CloseAndFlush();
|
|
}
|
|
|
|
// Make Program class accessible for Integration Tests
|
|
/// <summary>
|
|
/// Entry point class for the DocumentService API.
|
|
/// Made partial and public for integration test access.
|
|
/// </summary>
|
|
public partial class Program { } |