commit
acdc447bb4
32 changed files with 1239 additions and 0 deletions
@ -0,0 +1,45 @@ |
|||||
|
# .NET Core |
||||
|
bin/ |
||||
|
obj/ |
||||
|
*.user |
||||
|
*.userosscache |
||||
|
*.suo |
||||
|
*.userprefs |
||||
|
.vs/ |
||||
|
.vscode/ |
||||
|
*.swp |
||||
|
*.*~ |
||||
|
project.lock.json |
||||
|
.DS_Store |
||||
|
*.pyc |
||||
|
nupkg/ |
||||
|
|
||||
|
# Visual Studio Code |
||||
|
.vscode/* |
||||
|
!.vscode/settings.json |
||||
|
!.vscode/tasks.json |
||||
|
!.vscode/launch.json |
||||
|
!.vscode/extensions.json |
||||
|
|
||||
|
# Build results |
||||
|
[Dd]ebug/ |
||||
|
[Dd]ebugPublic/ |
||||
|
[Rr]elease/ |
||||
|
[Rr]eleases/ |
||||
|
x64/ |
||||
|
x86/ |
||||
|
build/ |
||||
|
bld/ |
||||
|
[Bb]in/ |
||||
|
[Oo]bj/ |
||||
|
[Oo]ut/ |
||||
|
msbuild.log |
||||
|
msbuild.err |
||||
|
msbuild.wrn |
||||
|
|
||||
|
# Visual Studio |
||||
|
.vs/ |
||||
|
*.ncrunchsolution |
||||
|
*.ncrunchproject |
||||
|
*.DotSettings |
||||
|
*.DotSettings.user |
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"ApiVersioning": { |
||||
|
"DefaultVersion": "1.0", |
||||
|
"ShowVersionInHeader": true, |
||||
|
"ShowVersionInResponse": true, |
||||
|
"ShowVersionInUrl": true, |
||||
|
"ShowVersionInQueryString": true, |
||||
|
"ShowVersionInMediaType": true, |
||||
|
"ReportApiVersions": true, |
||||
|
"AssumeDefaultVersionWhenUnspecified": true |
||||
|
} |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
{ |
||||
|
"Serilog": { |
||||
|
"MinimumLevel": { |
||||
|
"Default": "Information", |
||||
|
"Override": { |
||||
|
"Microsoft": "Warning", |
||||
|
"System": "Warning" |
||||
|
} |
||||
|
}, |
||||
|
"WriteTo": [ |
||||
|
{ |
||||
|
"Name": "Console", |
||||
|
"Args": { |
||||
|
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"Name": "File", |
||||
|
"Args": { |
||||
|
"path": "logs/log-.txt", |
||||
|
"rollingInterval": "Day", |
||||
|
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}", |
||||
|
"shared": true, |
||||
|
"flushToDiskInterval": "00:00:01" |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"Enrich": [ "FromLogContext" ] |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
{ |
||||
|
"RequestLogging": { |
||||
|
"LogRequestBody": true, |
||||
|
"LogResponseBody": true, |
||||
|
"MaxRequestBodySize": 2097152, |
||||
|
"MaxResponseBodySize": 2097152, |
||||
|
"ExcludePaths": [ |
||||
|
"/health", |
||||
|
"/metrics", |
||||
|
"/swagger", |
||||
|
"/favicon.ico" |
||||
|
], |
||||
|
"ExcludeMethods": [ |
||||
|
"OPTIONS" |
||||
|
] |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
{ |
||||
|
"RequestLogging": { |
||||
|
"LogRequestBody": true, |
||||
|
"LogResponseBody": true, |
||||
|
"MaxRequestBodySize": 1048576, |
||||
|
"MaxResponseBodySize": 1048576, |
||||
|
"ExcludePaths": [ |
||||
|
"/health", |
||||
|
"/metrics", |
||||
|
"/swagger", |
||||
|
"/favicon.ico" |
||||
|
], |
||||
|
"ExcludeMethods": [ |
||||
|
"OPTIONS" |
||||
|
] |
||||
|
} |
||||
|
} |
@ -0,0 +1,45 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
|
||||
|
namespace CoreAgent.API.Controllers |
||||
|
{ |
||||
|
[ApiController] |
||||
|
[ApiVersion("1.0")] |
||||
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
|
public class WeatherForecastController : ControllerBase |
||||
|
{ |
||||
|
private readonly ILogger<WeatherForecastController> _logger; |
||||
|
private static readonly string[] Summaries = new[] |
||||
|
{ |
||||
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" |
||||
|
}; |
||||
|
|
||||
|
public WeatherForecastController(ILogger<WeatherForecastController> logger) |
||||
|
{ |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public IActionResult Get() |
||||
|
{ |
||||
|
_logger.LogInformation("Weather forecast requested"); |
||||
|
|
||||
|
var forecast = Enumerable.Range(1, 5).Select(index => |
||||
|
new WeatherForecast |
||||
|
( |
||||
|
DateOnly.FromDateTime(DateTime.Now.AddDays(index)), |
||||
|
Random.Shared.Next(-20, 55), |
||||
|
Summaries[Random.Shared.Next(Summaries.Length)] |
||||
|
)) |
||||
|
.ToArray(); |
||||
|
|
||||
|
_logger.LogDebug("Generated forecast for {Count} days", forecast.Length); |
||||
|
return Ok(forecast); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) |
||||
|
{ |
||||
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); |
||||
|
} |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<InvariantGlobalization>true</InvariantGlobalization> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.1.0" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.1.0" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" /> |
||||
|
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" /> |
||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\CoreAgent.Infrastructure\CoreAgent.Infrastructure.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Update="Configurations\*.json"> |
||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
||||
|
</None> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
@ -0,0 +1,6 @@ |
|||||
|
@CoreAgent.API_HostAddress = http://localhost:5228 |
||||
|
|
||||
|
GET {{CoreAgent.API_HostAddress}}/weatherforecast/ |
||||
|
Accept: application/json |
||||
|
|
||||
|
### |
@ -0,0 +1,67 @@ |
|||||
|
using CoreAgent.API; |
||||
|
using CoreAgent.Infrastructure.Logging; |
||||
|
using Serilog; |
||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
|
||||
|
var builder = WebApplication.CreateBuilder(args); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
// 第一步:添加所有配置
|
||||
|
builder.AddConfigurations(); |
||||
|
|
||||
|
// 第二步:创建Startup实例
|
||||
|
var startup = builder.CreateStartup(); |
||||
|
|
||||
|
// 第三步:配置服务
|
||||
|
startup.ConfigureServices(builder.Services); |
||||
|
|
||||
|
var app = builder.Build(); |
||||
|
|
||||
|
// 配置中间件
|
||||
|
startup.Configure(app); |
||||
|
|
||||
|
// 配置Swagger
|
||||
|
app.ConfigureSwagger(); |
||||
|
|
||||
|
Log.Information("Application startup completed"); |
||||
|
|
||||
|
// 注册应用程序关闭事件
|
||||
|
var lifetime = app.Lifetime; |
||||
|
lifetime.ApplicationStopping.Register(() => |
||||
|
{ |
||||
|
Log.Information("Application is stopping..."); |
||||
|
// 在这里可以添加清理代码,比如关闭数据库连接等
|
||||
|
}); |
||||
|
|
||||
|
lifetime.ApplicationStopped.Register(() => |
||||
|
{ |
||||
|
Log.Information("Application has stopped."); |
||||
|
// 确保所有日志都被写入
|
||||
|
Log.CloseAndFlush(); |
||||
|
}); |
||||
|
|
||||
|
app.Run(); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Log.Fatal(ex, "Application failed to start: {Message}", ex.Message); |
||||
|
|
||||
|
// 记录详细的启动失败信息
|
||||
|
var errorDetails = new |
||||
|
{ |
||||
|
Message = ex.Message, |
||||
|
StackTrace = ex.StackTrace, |
||||
|
Source = ex.Source, |
||||
|
InnerException = ex.InnerException?.Message |
||||
|
}; |
||||
|
|
||||
|
Log.Fatal("Startup failure details: {Details}", JsonSerializer.Serialize(errorDetails)); |
||||
|
|
||||
|
// 确保所有日志都被写入
|
||||
|
Log.CloseAndFlush(); |
||||
|
|
||||
|
// 使用非零退出码表示错误
|
||||
|
Environment.Exit(1); |
||||
|
} |
@ -0,0 +1,41 @@ |
|||||
|
{ |
||||
|
"$schema": "http://json.schemastore.org/launchsettings.json", |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:3074", |
||||
|
"sslPort": 44378 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"http": { |
||||
|
"commandName": "Project", |
||||
|
"dotnetRunMessages": true, |
||||
|
"launchBrowser": true, |
||||
|
"launchUrl": "swagger", |
||||
|
"applicationUrl": "http://localhost:5228", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"https": { |
||||
|
"commandName": "Project", |
||||
|
"dotnetRunMessages": true, |
||||
|
"launchBrowser": true, |
||||
|
"launchUrl": "swagger", |
||||
|
"applicationUrl": "https://localhost:7133;http://localhost:5228", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"IIS Express": { |
||||
|
"commandName": "IISExpress", |
||||
|
"launchBrowser": true, |
||||
|
"launchUrl": "swagger", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,118 @@ |
|||||
|
using CoreAgent.Infrastructure.Extensions; |
||||
|
using CoreAgent.Infrastructure.Logging; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Hosting; |
||||
|
using Serilog; |
||||
|
|
||||
|
namespace CoreAgent.API |
||||
|
{ |
||||
|
public class Startup |
||||
|
{ |
||||
|
public IConfiguration Configuration { get; } |
||||
|
public IHostEnvironment Environment { get; } |
||||
|
|
||||
|
public Startup(IConfiguration configuration, IHostEnvironment environment) |
||||
|
{ |
||||
|
Configuration = configuration; |
||||
|
Environment = environment; |
||||
|
} |
||||
|
|
||||
|
public void ConfigureServices(IServiceCollection services) |
||||
|
{ |
||||
|
|
||||
|
// 添加基础设施服务
|
||||
|
services.AddInfrastructure(Configuration); |
||||
|
|
||||
|
// 添加控制器
|
||||
|
services.AddControllers(); |
||||
|
|
||||
|
// 添加API文档
|
||||
|
services.AddEndpointsApiExplorer(); |
||||
|
services.AddSwaggerGen(); |
||||
|
} |
||||
|
|
||||
|
public void Configure(IApplicationBuilder app) |
||||
|
{ |
||||
|
// 配置开发环境中间件
|
||||
|
if (Environment.IsDevelopment()) |
||||
|
{ |
||||
|
app.UseSwagger(); |
||||
|
app.UseSwaggerUI(); |
||||
|
Log.Debug("Swagger UI enabled in development environment"); |
||||
|
} |
||||
|
|
||||
|
// 使用基础设施中间件
|
||||
|
app.UseInfrastructure(Configuration); |
||||
|
|
||||
|
// 配置控制器路由
|
||||
|
app.UseRouting(); |
||||
|
app.UseEndpoints(endpoints => |
||||
|
{ |
||||
|
endpoints.MapControllers(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static class StartupExtensions |
||||
|
{ |
||||
|
public static WebApplicationBuilder AddConfigurations(this WebApplicationBuilder builder) |
||||
|
{ |
||||
|
const string configurationsDirectory = "Configurations"; |
||||
|
var env = builder.Environment; |
||||
|
|
||||
|
// 基础配置
|
||||
|
builder.Configuration |
||||
|
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) |
||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) |
||||
|
.AddEnvironmentVariables(); |
||||
|
|
||||
|
// 基础设施配置
|
||||
|
builder.Configuration |
||||
|
.AddJsonFile($"{configurationsDirectory}/logger.json", optional: false, reloadOnChange: true) |
||||
|
.AddJsonFile($"{configurationsDirectory}/logger.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) |
||||
|
.AddJsonFile($"{configurationsDirectory}/request-logging.json", optional: false, reloadOnChange: true) |
||||
|
.AddJsonFile($"{configurationsDirectory}/request-logging.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) |
||||
|
.AddJsonFile($"{configurationsDirectory}/api-versioning.json", optional: false, reloadOnChange: true) |
||||
|
.AddJsonFile($"{configurationsDirectory}/api-versioning.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); |
||||
|
|
||||
|
return builder; |
||||
|
} |
||||
|
|
||||
|
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration config) |
||||
|
{ |
||||
|
return services |
||||
|
.AddLoggingServices(config) |
||||
|
.AddApiVersioningExtension(config) |
||||
|
.AddRequestLogging(config) |
||||
|
.AddAuthorization() |
||||
|
.AddSwaggerGen(); |
||||
|
} |
||||
|
|
||||
|
public static IApplicationBuilder UseInfrastructure(this IApplicationBuilder app, IConfiguration config) |
||||
|
{ |
||||
|
return app |
||||
|
.UseHttpsRedirection() |
||||
|
.UseExceptionMiddleware() |
||||
|
.UseAuthorization() |
||||
|
.UseRequestLogging(config) |
||||
|
.UseApiVersioningExtension(); |
||||
|
} |
||||
|
|
||||
|
public static void ConfigureSwagger(this WebApplication app) |
||||
|
{ |
||||
|
if (app.Environment.IsDevelopment()) |
||||
|
{ |
||||
|
app.UseSwagger(); |
||||
|
app.UseSwaggerUI(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 新增:创建Startup实例的扩展方法
|
||||
|
public static Startup CreateStartup(this WebApplicationBuilder builder) |
||||
|
{ |
||||
|
return new Startup(builder.Configuration, builder.Environment); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"Logging": { |
||||
|
"LogLevel": { |
||||
|
"Default": "Information", |
||||
|
"Microsoft.AspNetCore": "Warning" |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,9 @@ |
|||||
|
{ |
||||
|
"Logging": { |
||||
|
"LogLevel": { |
||||
|
"Default": "Information", |
||||
|
"Microsoft.AspNetCore": "Warning" |
||||
|
} |
||||
|
}, |
||||
|
"AllowedHosts": "*" |
||||
|
} |
@ -0,0 +1,98 @@ |
|||||
|
2025-06-10 23:09:05.046 +08:00 [INF] Logger initialized successfully |
||||
|
2025-06-10 23:09:05.092 +08:00 [INF] Application starting... |
||||
|
2025-06-10 23:09:06.063 +08:00 [FTL] Application failed to start: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'.) |
||||
|
System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'.) |
||||
|
---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'. |
||||
|
---> System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'. |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain, Int32 slot) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor) |
||||
|
--- End of inner exception stack trace --- |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) |
||||
|
--- End of inner exception stack trace --- |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) |
||||
|
at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build() |
||||
|
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build() |
||||
|
at Program.<Main>$(String[] args) in D:\HistoryCode\CoreAgent\src\CoreAgent.API\Program.cs:line 17 |
||||
|
2025-06-10 23:09:06.162 +08:00 [FTL] Startup failure details: {"Message":"Some services are not able to be constructed (Error while validating the service descriptor \u0027ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027: Unable to resolve service for type \u0027Microsoft.AspNetCore.Http.RequestDelegate\u0027 while attempting to activate \u0027CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027.)","StackTrace":" at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection\u00601 serviceDescriptors, ServiceProviderOptions options)\r\n at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)\r\n at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()\r\n at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()\r\n at Program.\u003CMain\u003E$(String[] args) in D:\\HistoryCode\\CoreAgent\\src\\CoreAgent.API\\Program.cs:line 17","Source":"Microsoft.Extensions.DependencyInjection","InnerException":"Error while validating the service descriptor \u0027ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027: Unable to resolve service for type \u0027Microsoft.AspNetCore.Http.RequestDelegate\u0027 while attempting to activate \u0027CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027."} |
||||
|
2025-06-10 23:09:40.611 +08:00 [INF] Logger initialized successfully |
||||
|
2025-06-10 23:09:40.653 +08:00 [INF] Application starting... |
||||
|
2025-06-10 23:09:40.752 +08:00 [FTL] Application failed to start: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'.) |
||||
|
System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'.) |
||||
|
---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'. |
||||
|
---> System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'. |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain, Int32 slot) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor) |
||||
|
--- End of inner exception stack trace --- |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) |
||||
|
--- End of inner exception stack trace --- |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) |
||||
|
at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build() |
||||
|
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build() |
||||
|
at Program.<Main>$(String[] args) in D:\HistoryCode\CoreAgent\src\CoreAgent.API\Program.cs:line 17 |
||||
|
2025-06-10 23:09:40.820 +08:00 [FTL] Startup failure details: {"Message":"Some services are not able to be constructed (Error while validating the service descriptor \u0027ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027: Unable to resolve service for type \u0027Microsoft.AspNetCore.Http.RequestDelegate\u0027 while attempting to activate \u0027CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027.)","StackTrace":" at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection\u00601 serviceDescriptors, ServiceProviderOptions options)\r\n at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)\r\n at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()\r\n at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()\r\n at Program.\u003CMain\u003E$(String[] args) in D:\\HistoryCode\\CoreAgent\\src\\CoreAgent.API\\Program.cs:line 17","Source":"Microsoft.Extensions.DependencyInjection","InnerException":"Error while validating the service descriptor \u0027ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027: Unable to resolve service for type \u0027Microsoft.AspNetCore.Http.RequestDelegate\u0027 while attempting to activate \u0027CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027."} |
||||
|
2025-06-10 23:10:25.939 +08:00 [INF] Logger initialized successfully |
||||
|
2025-06-10 23:10:25.975 +08:00 [INF] Application starting... |
||||
|
2025-06-10 23:10:26.021 +08:00 [FTL] Application failed to start: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'.) |
||||
|
System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'.) |
||||
|
---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware': Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'. |
||||
|
---> System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'CoreAgent.Infrastructure.Middleware.ExceptionMiddleware'. |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain, Int32 slot) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor) |
||||
|
--- End of inner exception stack trace --- |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) |
||||
|
--- End of inner exception stack trace --- |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) |
||||
|
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) |
||||
|
at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build() |
||||
|
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build() |
||||
|
at Program.<Main>$(String[] args) in D:\HistoryCode\CoreAgent\src\CoreAgent.API\Program.cs:line 17 |
||||
|
2025-06-10 23:10:26.056 +08:00 [FTL] Startup failure details: {"Message":"Some services are not able to be constructed (Error while validating the service descriptor \u0027ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027: Unable to resolve service for type \u0027Microsoft.AspNetCore.Http.RequestDelegate\u0027 while attempting to activate \u0027CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027.)","StackTrace":" at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection\u00601 serviceDescriptors, ServiceProviderOptions options)\r\n at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)\r\n at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()\r\n at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()\r\n at Program.\u003CMain\u003E$(String[] args) in D:\\HistoryCode\\CoreAgent\\src\\CoreAgent.API\\Program.cs:line 17","Source":"Microsoft.Extensions.DependencyInjection","InnerException":"Error while validating the service descriptor \u0027ServiceType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware Lifetime: Scoped ImplementationType: CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027: Unable to resolve service for type \u0027Microsoft.AspNetCore.Http.RequestDelegate\u0027 while attempting to activate \u0027CoreAgent.Infrastructure.Middleware.ExceptionMiddleware\u0027."} |
||||
|
2025-06-10 23:11:14.432 +08:00 [INF] Logger initialized successfully |
||||
|
2025-06-10 23:11:14.474 +08:00 [INF] Application starting... |
||||
|
2025-06-10 23:11:14.527 +08:00 [FTL] Application failed to start: Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddAuthorization' in the application startup code. |
||||
|
System.InvalidOperationException: Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddAuthorization' in the application startup code. |
||||
|
at Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.VerifyServicesRegistered(IApplicationBuilder app) |
||||
|
at Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization(IApplicationBuilder app) |
||||
|
at CoreAgent.API.Startup.UseInfrastructure(IApplicationBuilder app, IConfiguration config) in D:\HistoryCode\CoreAgent\src\CoreAgent.API\Startup.cs:line 45 |
||||
|
at Program.<Main>$(String[] args) in D:\HistoryCode\CoreAgent\src\CoreAgent.API\Program.cs:line 28 |
||||
|
2025-06-10 23:11:14.601 +08:00 [FTL] Startup failure details: {"Message":"Unable to find the required services. Please add all the required services by calling \u0027IServiceCollection.AddAuthorization\u0027 in the application startup code.","StackTrace":" at Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.VerifyServicesRegistered(IApplicationBuilder app)\r\n at Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization(IApplicationBuilder app)\r\n at CoreAgent.API.Startup.UseInfrastructure(IApplicationBuilder app, IConfiguration config) in D:\\HistoryCode\\CoreAgent\\src\\CoreAgent.API\\Startup.cs:line 45\r\n at Program.\u003CMain\u003E$(String[] args) in D:\\HistoryCode\\CoreAgent\\src\\CoreAgent.API\\Program.cs:line 28","Source":"Microsoft.AspNetCore.Authorization.Policy","InnerException":null} |
||||
|
2025-06-10 23:14:51.039 +08:00 [INF] Logger initialized successfully |
||||
|
2025-06-10 23:14:51.069 +08:00 [INF] Application starting... |
||||
|
2025-06-10 23:14:51.124 +08:00 [FTL] Application failed to start: Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddAuthorization' in the application startup code. |
||||
|
System.InvalidOperationException: Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddAuthorization' in the application startup code. |
||||
|
at Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.VerifyServicesRegistered(IApplicationBuilder app) |
||||
|
at Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization(IApplicationBuilder app) |
||||
|
at CoreAgent.API.Startup.UseInfrastructure(IApplicationBuilder app, IConfiguration config) in D:\HistoryCode\CoreAgent\src\CoreAgent.API\Startup.cs:line 45 |
||||
|
at Program.<Main>$(String[] args) in D:\HistoryCode\CoreAgent\src\CoreAgent.API\Program.cs:line 28 |
||||
|
2025-06-10 23:14:51.149 +08:00 [FTL] Startup failure details: {"Message":"Unable to find the required services. Please add all the required services by calling \u0027IServiceCollection.AddAuthorization\u0027 in the application startup code.","StackTrace":" at Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.VerifyServicesRegistered(IApplicationBuilder app)\r\n at Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization(IApplicationBuilder app)\r\n at CoreAgent.API.Startup.UseInfrastructure(IApplicationBuilder app, IConfiguration config) in D:\\HistoryCode\\CoreAgent\\src\\CoreAgent.API\\Startup.cs:line 45\r\n at Program.\u003CMain\u003E$(String[] args) in D:\\HistoryCode\\CoreAgent\\src\\CoreAgent.API\\Program.cs:line 28","Source":"Microsoft.AspNetCore.Authorization.Policy","InnerException":null} |
||||
|
2025-06-10 23:15:27.651 +08:00 [INF] Logger initialized successfully |
||||
|
2025-06-10 23:15:27.682 +08:00 [INF] Application starting... |
||||
|
2025-06-10 23:15:27.735 +08:00 [INF] Application startup completed |
||||
|
2025-06-10 23:23:44.793 +08:00 [INF] Logger initialized successfully |
||||
|
2025-06-10 23:23:44.837 +08:00 [INF] Application starting... |
||||
|
2025-06-10 23:23:45.207 +08:00 [INF] Application startup completed |
||||
|
2025-06-10 23:23:51.434 +08:00 [INF] Request started: GET /api/v1/WeatherForecast |
||||
|
2025-06-10 23:23:51.497 +08:00 [INF] Weather forecast requested |
||||
|
2025-06-10 23:23:51.530 +08:00 [INF] Response for GET /api/v1/WeatherForecast: 200 - [{"date":"2025-06-11","temperatureC":-19,"summary":"Scorching","temperatureF":-2},{"date":"2025-06-12","temperatureC":-11,"summary":"Bracing","temperatureF":13},{"date":"2025-06-13","temperatureC":10,"summary":"Chilly","temperatureF":49},{"date":"2025-06-14","temperatureC":7,"summary":"Mild","temperatureF":44},{"date":"2025-06-15","temperatureC":35,"summary":"Warm","temperatureF":94}] |
||||
|
2025-06-10 23:23:51.547 +08:00 [INF] Request completed: GET /api/v1/WeatherForecast in 119ms with status code 200 |
||||
|
2025-06-10 23:24:10.107 +08:00 [INF] Logger initialized successfully |
||||
|
2025-06-10 23:24:10.148 +08:00 [INF] Application starting... |
||||
|
2025-06-10 23:24:10.527 +08:00 [INF] Application startup completed |
||||
|
2025-06-10 23:24:23.522 +08:00 [INF] Request started: GET /api/v1/WeatherForecast |
||||
|
2025-06-10 23:24:23.584 +08:00 [INF] Weather forecast requested |
||||
|
2025-06-10 23:24:23.612 +08:00 [INF] Response for GET /api/v1/WeatherForecast: 200 - [{"date":"2025-06-11","temperatureC":24,"summary":"Warm","temperatureF":75},{"date":"2025-06-12","temperatureC":4,"summary":"Bracing","temperatureF":39},{"date":"2025-06-13","temperatureC":54,"summary":"Chilly","temperatureF":129},{"date":"2025-06-14","temperatureC":-6,"summary":"Freezing","temperatureF":22},{"date":"2025-06-15","temperatureC":-20,"summary":"Sweltering","temperatureF":-3}] |
||||
|
2025-06-10 23:24:23.632 +08:00 [INF] Request completed: GET /api/v1/WeatherForecast in 120ms with status code 200 |
@ -0,0 +1,9 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<Nullable>enable</Nullable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
</Project> |
@ -0,0 +1,13 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<Nullable>enable</Nullable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
@ -0,0 +1,14 @@ |
|||||
|
namespace CoreAgent.Domain.Exceptions |
||||
|
{ |
||||
|
public class NotFoundException : Exception |
||||
|
{ |
||||
|
public NotFoundException(string message) : base(message) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public NotFoundException(string name, object key) |
||||
|
: base($"Entity \"{name}\" ({key}) was not found.") |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
namespace CoreAgent.Domain.Exceptions |
||||
|
{ |
||||
|
public class ValidationException : Exception |
||||
|
{ |
||||
|
public IDictionary<string, string[]> Errors { get; } |
||||
|
|
||||
|
public ValidationException(string message) : base(message) |
||||
|
{ |
||||
|
Errors = new Dictionary<string, string[]>(); |
||||
|
} |
||||
|
|
||||
|
public ValidationException(string message, IDictionary<string, string[]> errors) : base(message) |
||||
|
{ |
||||
|
Errors = errors; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
namespace CoreAgent.Domain.Models |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 表示API错误响应的领域模型
|
||||
|
/// </summary>
|
||||
|
public class ErrorResponse |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 请求的唯一跟踪标识符
|
||||
|
/// </summary>
|
||||
|
public string TraceId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 错误消息
|
||||
|
/// </summary>
|
||||
|
public string Message { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 验证错误集合,键为字段名,值为错误消息数组
|
||||
|
/// </summary>
|
||||
|
public IDictionary<string, string[]> Errors { get; set; } |
||||
|
} |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<Nullable>enable</Nullable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.1.0" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.1.0" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> |
||||
|
<PackageReference Include="Serilog" Version="3.1.1" /> |
||||
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" /> |
||||
|
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.0" /> |
||||
|
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" /> |
||||
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\CoreAgent.Domain\CoreAgent.Domain.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
@ -0,0 +1,13 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<Nullable>enable</Nullable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Serilog" Version="4.3.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
@ -0,0 +1,44 @@ |
|||||
|
using CoreAgent.Infrastructure.Options; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Versioning; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
|
||||
|
namespace CoreAgent.Infrastructure.Extensions |
||||
|
{ |
||||
|
public static class ApiVersioningExtensions |
||||
|
{ |
||||
|
public static IServiceCollection AddApiVersioningExtension(this IServiceCollection services, IConfiguration config) |
||||
|
{ |
||||
|
var settings = config.GetSection("ApiVersioning").Get<ApiVersioningSettings>() ?? new ApiVersioningSettings(); |
||||
|
|
||||
|
services.AddApiVersioning(options => |
||||
|
{ |
||||
|
options.DefaultApiVersion = ApiVersion.Parse(settings.DefaultVersion); |
||||
|
options.AssumeDefaultVersionWhenUnspecified = settings.AssumeDefaultVersionWhenUnspecified; |
||||
|
options.ReportApiVersions = settings.ReportApiVersions; |
||||
|
options.ApiVersionReader = ApiVersionReader.Combine( |
||||
|
settings.ShowVersionInUrl ? new UrlSegmentApiVersionReader() : null, |
||||
|
settings.ShowVersionInQueryString ? new QueryStringApiVersionReader("api-version") : null, |
||||
|
settings.ShowVersionInHeader ? new HeaderApiVersionReader("api-version") : null, |
||||
|
settings.ShowVersionInMediaType ? new MediaTypeApiVersionReader("version") : null |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
services.AddVersionedApiExplorer(options => |
||||
|
{ |
||||
|
options.GroupNameFormat = "'v'VVV"; |
||||
|
options.SubstituteApiVersionInUrl = true; |
||||
|
}); |
||||
|
|
||||
|
return services; |
||||
|
} |
||||
|
|
||||
|
public static IApplicationBuilder UseApiVersioningExtension(this IApplicationBuilder app) |
||||
|
{ |
||||
|
// 可以在这里添加版本控制相关的中间件
|
||||
|
return app; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
using CoreAgent.Infrastructure.Middleware; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
|
||||
|
namespace CoreAgent.Infrastructure.Extensions |
||||
|
{ |
||||
|
public static class ExceptionMiddlewareExtensions |
||||
|
{ |
||||
|
public static IApplicationBuilder UseExceptionMiddleware(this IApplicationBuilder builder) |
||||
|
{ |
||||
|
return builder.UseMiddleware<ExceptionMiddleware>(); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
using CoreAgent.Infrastructure.Logging; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Serilog; |
||||
|
|
||||
|
namespace CoreAgent.Infrastructure.Extensions |
||||
|
{ |
||||
|
public static class LoggingExtensions |
||||
|
{ |
||||
|
public static IServiceCollection AddLoggingServices(this IServiceCollection services, IConfiguration configuration) |
||||
|
{ |
||||
|
// 初始化应用程序日志记录器
|
||||
|
ApplicationLogger.Initialize(configuration); |
||||
|
Log.Information("Application starting..."); |
||||
|
|
||||
|
// 添加 Serilog 到依赖注入容器
|
||||
|
services.AddLogging(loggingBuilder => |
||||
|
{ |
||||
|
loggingBuilder.ClearProviders(); |
||||
|
loggingBuilder.AddSerilog(dispose: true); |
||||
|
}); |
||||
|
|
||||
|
return services; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
using CoreAgent.Infrastructure.Middleware; |
||||
|
using CoreAgent.Infrastructure.Options; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
|
||||
|
namespace CoreAgent.Infrastructure.Extensions |
||||
|
{ |
||||
|
public static class RequestLoggingExtensions |
||||
|
{ |
||||
|
public static IServiceCollection AddRequestLogging(this IServiceCollection services, IConfiguration config) |
||||
|
{ |
||||
|
services.Configure<RequestLoggingOptions>(config.GetSection("RequestLogging")); |
||||
|
return services; |
||||
|
} |
||||
|
|
||||
|
public static IApplicationBuilder UseRequestLogging(this IApplicationBuilder app, IConfiguration config) |
||||
|
{ |
||||
|
app.UseMiddleware<RequestLoggingMiddleware>(); |
||||
|
app.UseMiddleware<ResponseLoggingMiddleware>(); |
||||
|
return app; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Serilog; |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
|
||||
|
namespace CoreAgent.Infrastructure.Logging |
||||
|
{ |
||||
|
public static class ApplicationLogger |
||||
|
{ |
||||
|
private static readonly object _lock = new object(); |
||||
|
private static bool _isInitialized; |
||||
|
|
||||
|
public static void Initialize(IConfiguration configuration) |
||||
|
{ |
||||
|
ArgumentNullException.ThrowIfNull(configuration, nameof(configuration)); |
||||
|
|
||||
|
if (_isInitialized) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
lock (_lock) |
||||
|
{ |
||||
|
if (_isInitialized) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
// 确保日志目录存在
|
||||
|
var logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs"); |
||||
|
Directory.CreateDirectory(logDirectory); |
||||
|
|
||||
|
// 从配置文件初始化
|
||||
|
Log.Logger = new LoggerConfiguration() |
||||
|
.ReadFrom.Configuration(configuration) |
||||
|
.CreateLogger(); |
||||
|
|
||||
|
_isInitialized = true; |
||||
|
Log.Information("Logger initialized successfully"); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
// 如果初始化失败,创建一个基本的控制台日志记录器
|
||||
|
Log.Logger = new LoggerConfiguration() |
||||
|
.MinimumLevel.Debug() |
||||
|
.WriteTo.Console() |
||||
|
.CreateLogger(); |
||||
|
|
||||
|
_isInitialized = true; |
||||
|
Log.Error(ex, "Failed to initialize logger with full configuration"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void EnsureInitialized() |
||||
|
{ |
||||
|
if (!_isInitialized) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Logger has not been initialized. Call Initialize() first."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,75 @@ |
|||||
|
using CoreAgent.Domain.Exceptions; |
||||
|
using CoreAgent.Domain.Models; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using System.Net; |
||||
|
using System.Text.Json; |
||||
|
|
||||
|
namespace CoreAgent.Infrastructure.Middleware |
||||
|
{ |
||||
|
public class ExceptionMiddleware |
||||
|
{ |
||||
|
private readonly RequestDelegate _next; |
||||
|
private readonly ILogger<ExceptionMiddleware> _logger; |
||||
|
|
||||
|
public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger) |
||||
|
{ |
||||
|
_next = next; |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
public async Task InvokeAsync(HttpContext context) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
await _next(context); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
await HandleExceptionAsync(context, ex); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async Task HandleExceptionAsync(HttpContext context, Exception exception) |
||||
|
{ |
||||
|
var response = context.Response; |
||||
|
response.ContentType = "application/json"; |
||||
|
|
||||
|
var errorResponse = new ErrorResponse |
||||
|
{ |
||||
|
TraceId = context.TraceIdentifier, |
||||
|
Message = "An error occurred while processing your request." |
||||
|
}; |
||||
|
|
||||
|
switch (exception) |
||||
|
{ |
||||
|
case ValidationException validationEx: |
||||
|
response.StatusCode = (int)HttpStatusCode.BadRequest; |
||||
|
errorResponse.Message = validationEx.Message; |
||||
|
errorResponse.Errors = validationEx.Errors; |
||||
|
_logger.LogWarning("Validation error: {Message}", validationEx.Message); |
||||
|
break; |
||||
|
|
||||
|
case NotFoundException notFoundEx: |
||||
|
response.StatusCode = (int)HttpStatusCode.NotFound; |
||||
|
errorResponse.Message = notFoundEx.Message; |
||||
|
_logger.LogWarning("Resource not found: {Message}", notFoundEx.Message); |
||||
|
break; |
||||
|
|
||||
|
case UnauthorizedAccessException: |
||||
|
response.StatusCode = (int)HttpStatusCode.Unauthorized; |
||||
|
errorResponse.Message = "You are not authorized to access this resource."; |
||||
|
_logger.LogWarning("Unauthorized access attempt"); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
response.StatusCode = (int)HttpStatusCode.InternalServerError; |
||||
|
_logger.LogError(exception, "Unhandled exception occurred"); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
var result = JsonSerializer.Serialize(errorResponse); |
||||
|
await response.WriteAsync(result); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,110 @@ |
|||||
|
using CoreAgent.Infrastructure.Options; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System.Diagnostics; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace CoreAgent.Infrastructure.Middleware |
||||
|
{ |
||||
|
public class RequestLoggingMiddleware |
||||
|
{ |
||||
|
private readonly RequestDelegate _next; |
||||
|
private readonly ILogger<RequestLoggingMiddleware> _logger; |
||||
|
private readonly RequestLoggingOptions _options; |
||||
|
|
||||
|
public RequestLoggingMiddleware( |
||||
|
RequestDelegate next, |
||||
|
ILogger<RequestLoggingMiddleware> logger, |
||||
|
IOptions<RequestLoggingOptions> options) |
||||
|
{ |
||||
|
_next = next; |
||||
|
_logger = logger; |
||||
|
_options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public async Task InvokeAsync(HttpContext context) |
||||
|
{ |
||||
|
if (ShouldSkipLogging(context)) |
||||
|
{ |
||||
|
await _next(context); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var sw = Stopwatch.StartNew(); |
||||
|
var requestBody = string.Empty; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
if (_options.LogRequestBody && context.Request.Body != null) |
||||
|
{ |
||||
|
requestBody = await ReadRequestBodyAsync(context.Request); |
||||
|
} |
||||
|
|
||||
|
_logger.LogInformation( |
||||
|
"Request started: {Method} {Path} {QueryString} {RequestBody}", |
||||
|
context.Request.Method, |
||||
|
context.Request.Path, |
||||
|
context.Request.QueryString, |
||||
|
requestBody); |
||||
|
|
||||
|
await _next(context); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
sw.Stop(); |
||||
|
_logger.LogInformation( |
||||
|
"Request completed: {Method} {Path} in {ElapsedMilliseconds}ms with status code {StatusCode}", |
||||
|
context.Request.Method, |
||||
|
context.Request.Path, |
||||
|
sw.ElapsedMilliseconds, |
||||
|
context.Response.StatusCode); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private bool ShouldSkipLogging(HttpContext context) |
||||
|
{ |
||||
|
if (_options.ExcludePaths.Any(p => context.Request.Path.StartsWithSegments(p))) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (_options.ExcludeMethods.Contains(context.Request.Method)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
private async Task<string> ReadRequestBodyAsync(HttpRequest request) |
||||
|
{ |
||||
|
if (!request.Body.CanRead || !request.Body.CanSeek) |
||||
|
{ |
||||
|
return string.Empty; |
||||
|
} |
||||
|
|
||||
|
var originalPosition = request.Body.Position; |
||||
|
request.Body.Position = 0; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
using var reader = new StreamReader( |
||||
|
request.Body, |
||||
|
encoding: Encoding.UTF8, |
||||
|
detectEncodingFromByteOrderMarks: false, |
||||
|
bufferSize: 1024 * 45, |
||||
|
leaveOpen: true); |
||||
|
|
||||
|
var body = await reader.ReadToEndAsync(); |
||||
|
return body.Length > _options.MaxRequestBodySize |
||||
|
? body.Substring(0, _options.MaxRequestBodySize) + "..." |
||||
|
: body; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
request.Body.Position = originalPosition; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
using CoreAgent.Infrastructure.Options; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace CoreAgent.Infrastructure.Middleware |
||||
|
{ |
||||
|
public class ResponseLoggingMiddleware |
||||
|
{ |
||||
|
private readonly RequestDelegate _next; |
||||
|
private readonly ILogger<ResponseLoggingMiddleware> _logger; |
||||
|
private readonly RequestLoggingOptions _options; |
||||
|
|
||||
|
public ResponseLoggingMiddleware( |
||||
|
RequestDelegate next, |
||||
|
ILogger<ResponseLoggingMiddleware> logger, |
||||
|
IOptions<RequestLoggingOptions> options) |
||||
|
{ |
||||
|
_next = next; |
||||
|
_logger = logger; |
||||
|
_options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public async Task InvokeAsync(HttpContext context) |
||||
|
{ |
||||
|
if (ShouldSkipLogging(context)) |
||||
|
{ |
||||
|
await _next(context); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 保存原始响应流
|
||||
|
var originalBodyStream = context.Response.Body; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
// 创建一个新的内存流来捕获响应
|
||||
|
using var responseBody = new MemoryStream(); |
||||
|
context.Response.Body = responseBody; |
||||
|
|
||||
|
// 继续处理请求
|
||||
|
await _next(context); |
||||
|
|
||||
|
// 读取响应内容
|
||||
|
responseBody.Seek(0, SeekOrigin.Begin); |
||||
|
var response = await ReadResponseBodyAsync(responseBody); |
||||
|
|
||||
|
// 记录响应
|
||||
|
_logger.LogInformation( |
||||
|
"Response for {Method} {Path}: {StatusCode} - {Response}", |
||||
|
context.Request.Method, |
||||
|
context.Request.Path, |
||||
|
context.Response.StatusCode, |
||||
|
response); |
||||
|
|
||||
|
// 将响应写回原始流
|
||||
|
responseBody.Seek(0, SeekOrigin.Begin); |
||||
|
await responseBody.CopyToAsync(originalBodyStream); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
// 确保响应体被恢复
|
||||
|
context.Response.Body = originalBodyStream; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private bool ShouldSkipLogging(HttpContext context) |
||||
|
{ |
||||
|
if (!_options.LogResponseBody) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (_options.ExcludePaths.Any(p => context.Request.Path.StartsWithSegments(p))) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (_options.ExcludeMethods.Contains(context.Request.Method)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
private async Task<string> ReadResponseBodyAsync(Stream responseBody) |
||||
|
{ |
||||
|
using var reader = new StreamReader( |
||||
|
responseBody, |
||||
|
encoding: Encoding.UTF8, |
||||
|
detectEncodingFromByteOrderMarks: false, |
||||
|
bufferSize: 1024 * 45, |
||||
|
leaveOpen: true); |
||||
|
|
||||
|
var body = await reader.ReadToEndAsync(); |
||||
|
return body.Length > _options.MaxResponseBodySize |
||||
|
? body.Substring(0, _options.MaxResponseBodySize) + "..." |
||||
|
: body; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,45 @@ |
|||||
|
namespace CoreAgent.Infrastructure.Options |
||||
|
{ |
||||
|
public class ApiVersioningSettings |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 默认 API 版本
|
||||
|
/// </summary>
|
||||
|
public string DefaultVersion { get; set; } = "1.0"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否在响应头中显示版本信息
|
||||
|
/// </summary>
|
||||
|
public bool ShowVersionInHeader { get; set; } = true; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否在响应中显示版本信息
|
||||
|
/// </summary>
|
||||
|
public bool ShowVersionInResponse { get; set; } = true; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否在 URL 中显示版本信息
|
||||
|
/// </summary>
|
||||
|
public bool ShowVersionInUrl { get; set; } = true; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否在查询字符串中显示版本信息
|
||||
|
/// </summary>
|
||||
|
public bool ShowVersionInQueryString { get; set; } = true; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否在媒体类型中显示版本信息
|
||||
|
/// </summary>
|
||||
|
public bool ShowVersionInMediaType { get; set; } = true; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否报告 API 版本
|
||||
|
/// </summary>
|
||||
|
public bool ReportApiVersions { get; set; } = true; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否假设默认版本
|
||||
|
/// </summary>
|
||||
|
public bool AssumeDefaultVersionWhenUnspecified { get; set; } = true; |
||||
|
} |
||||
|
} |
@ -0,0 +1,35 @@ |
|||||
|
namespace CoreAgent.Infrastructure.Options |
||||
|
{ |
||||
|
public class RequestLoggingOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 是否记录请求体
|
||||
|
/// </summary>
|
||||
|
public bool LogRequestBody { get; set; } = true; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否记录响应体
|
||||
|
/// </summary>
|
||||
|
public bool LogResponseBody { get; set; } = true; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 最大请求体大小(字节)
|
||||
|
/// </summary>
|
||||
|
public int MaxRequestBodySize { get; set; } = 1024 * 1024; // 1MB
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 最大响应体大小(字节)
|
||||
|
/// </summary>
|
||||
|
public int MaxResponseBodySize { get; set; } = 1024 * 1024; // 1MB
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 要排除的路径列表
|
||||
|
/// </summary>
|
||||
|
public string[] ExcludePaths { get; set; } = Array.Empty<string>(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 要排除的HTTP方法列表
|
||||
|
/// </summary>
|
||||
|
public string[] ExcludeMethods { get; set; } = Array.Empty<string>(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
|
||||
|
Microsoft Visual Studio Solution File, Format Version 12.00 |
||||
|
# Visual Studio Version 17 |
||||
|
VisualStudioVersion = 17.0.31903.59 |
||||
|
MinimumVisualStudioVersion = 10.0.40219.1 |
||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreAgent.API", "CoreAgent.API\CoreAgent.API.csproj", "{DC3259F5-9A7E-1AEA-FA79-13C78AA9FDAC}" |
||||
|
EndProject |
||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreAgent.Application", "CoreAgent.Application\CoreAgent.Application.csproj", "{D74FF074-0A13-BF0E-A637-41E48C0FB9AB}" |
||||
|
EndProject |
||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreAgent.Domain", "CoreAgent.Domain\CoreAgent.Domain.csproj", "{3269E8BF-134E-9410-E1DA-A62044875E72}" |
||||
|
EndProject |
||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreAgent.Infrastructure", "CoreAgent.Infrastructure\CoreAgent.Infrastructure.csproj", "{3EBCA8A2-F1CD-23F7-C943-0CAADACFFCDD}" |
||||
|
EndProject |
||||
|
Global |
||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||
|
Debug|Any CPU = Debug|Any CPU |
||||
|
Release|Any CPU = Release|Any CPU |
||||
|
EndGlobalSection |
||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||
|
{DC3259F5-9A7E-1AEA-FA79-13C78AA9FDAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
|
{DC3259F5-9A7E-1AEA-FA79-13C78AA9FDAC}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
|
{DC3259F5-9A7E-1AEA-FA79-13C78AA9FDAC}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
|
{DC3259F5-9A7E-1AEA-FA79-13C78AA9FDAC}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
|
{D74FF074-0A13-BF0E-A637-41E48C0FB9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
|
{D74FF074-0A13-BF0E-A637-41E48C0FB9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
|
{D74FF074-0A13-BF0E-A637-41E48C0FB9AB}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
|
{D74FF074-0A13-BF0E-A637-41E48C0FB9AB}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
|
{3269E8BF-134E-9410-E1DA-A62044875E72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
|
{3269E8BF-134E-9410-E1DA-A62044875E72}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
|
{3269E8BF-134E-9410-E1DA-A62044875E72}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
|
{3269E8BF-134E-9410-E1DA-A62044875E72}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
|
{3EBCA8A2-F1CD-23F7-C943-0CAADACFFCDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
|
{3EBCA8A2-F1CD-23F7-C943-0CAADACFFCDD}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
|
{3EBCA8A2-F1CD-23F7-C943-0CAADACFFCDD}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
|
{3EBCA8A2-F1CD-23F7-C943-0CAADACFFCDD}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
|
EndGlobalSection |
||||
|
GlobalSection(SolutionProperties) = preSolution |
||||
|
HideSolutionNode = FALSE |
||||
|
EndGlobalSection |
||||
|
EndGlobal |
Loading…
Reference in new issue