using AuthServer.Host; using BaseService; using Hangfire; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using StackExchange.Redis; using Swashbuckle.AspNetCore.SwaggerUI; using System; using System.IO; using System.Linq; using System.Text.Json; using Volo.Abp; using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.ExceptionHandling; using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.Autofac; using Volo.Abp.BackgroundJobs.Hangfire; using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring.FileSystem; using Volo.Abp.BlobStoring.Minio; using Volo.Abp.Caching; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore.SqlServer; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.Threading; using Volo.Abp.VirtualFileSystem; using Win.Sfs.BaseData.ImportExcelCommon; using Win.Sfs.SettleAccount.ImportExcelCommon; using Win.Sfs.Shared.Constant; using Win.Utils; namespace Win.Sfs.SettleAccount { [DependsOn( typeof(AbpAutofacModule), typeof(AuthServerHostModule), typeof(BaseServiceHostModule), typeof(SettleAccountApplicationModule), typeof(SettleAccountEntityFrameworkCoreModule), typeof(SettleAccountHttpApiModule), //typeof(AbpAspNetCoreMvcUiMultiTenancyModule), //typeof(AbpCachingStackExchangeRedisModule), typeof(AbpEntityFrameworkCoreSqlServerModule), typeof(AbpAuditLoggingEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpAspNetCoreSerilogModule), typeof(AbpBlobStoringModule), typeof(AbpBlobStoringFileSystemModule), typeof(AbpBackgroundJobsHangfireModule) //typeof(AbpEventBusRabbitMqModule) //typeof(AbpHangfireModule) //typeof(AbpSwashbuckleModule) )] public class SettleAccountHttpApiHostModule : AbpModule { private const string DefaultCorsPolicyName = "Default"; public override void ConfigureServices(ServiceConfigurationContext context) { // System.AbpStringExtensions.ToCamelCase(System.String, Boolean)' var configuration = context.Services.GetConfiguration(); //文件上传大小限制 ConfigureBodyLengthLimit(context); //配置多租户 ConfigureMultiTenancy(); //配置认证 ConfigureAuthentication(context, configuration); //配置本地化 ConfigureLocalization(); //配置缓存 ConfigureCache(configuration); //配置虚拟文件系统 // ConfigureVirtualFileSystem(context); //配置Redis ConfigureRedis(context, configuration); //配置跨域资源共享 //ConfigureCors(context, configuration); //配置Swagger ConfigureSwaggerServices(context, configuration); //null: DTO的属性首字母保持大写 ConfigureJson(context); //应用服务自动转换为控制器 ConfigureConventionalControllers(); //配置异常处理 ConfigureException(); //注册BOLB容器 ConfigureBLOBServices(configuration); //注册大众的二配实际输出文件的容器 //ConfigureBLOBSecSummaryServices(configuration); //注册奔腾的二配实际输出文件的容器 //ConfigureBLOBTSecSummaryServices(configuration); ConfigureHangfire(context, configuration); //context.Services.Configure(options => //{ // options.Map("Volo.Qa:010002", System.Net.HttpStatusCode.Conflict); //}); //context.Services.Configure(options => //{ // options.SendExceptionsDetailsToClients = false; //}); /* Configure(options => { options.Connections.Default.UserName = "user1"; options.Connections.Default.Password = "123123"; options.Connections.Default.HostName = "192.168.0.203"; options.Connections.Default.Port = 5672; }); */ //Configure(options => //{ // options.ClientName = "SettleAccount"; // options.ExchangeName = "TestMessages"; //}); //Configure(options => //{ // options.DefaultTimeout = 864000; //10 days (as seconds) //}); context.Services.Configure(x => { x.ValueLengthLimit = int.MaxValue; x.MultipartBodyLengthLimit = int.MaxValue; x.MemoryBufferThreshold = int.MaxValue; }); } private void ConfigureBodyLengthLimit(ServiceConfigurationContext context) { context.Services.Configure(options => { options.ValueLengthLimit = int.MaxValue; options.MultipartBodyLengthLimit = int.MaxValue; options.MultipartHeadersLengthLimit = int.MaxValue; }); } /// /// 上传文件的容器 /// /// private void ConfigureBLOBServices(IConfiguration cfg) { //Configure(options => //{ // options.Containers.Configure(configuration => // { // configuration.UseFileSystem(fileSystem => // { // var filestreampath = Environment.CurrentDirectory + @"\wwwroot\files"; // if (!Directory.Exists(filestreampath)) // { // Directory.CreateDirectory(filestreampath); // } // fileSystem.BasePath = filestreampath; // }); // }); //}); Configure(options => { options.Containers.ConfigureDefault(container => { container.UseMinio(minio => { minio.EndPoint = cfg.GetValue("MinIO:EndPoint", "localhost:10684"); minio.AccessKey = cfg.GetValue("MinIO:AccessKey", "g0GKnhRGEQHI0uiGBYre"); minio.SecretKey = cfg.GetValue("MinIO:SecretKey", "iKGlLz6UBzci3xrERw5Zz1gI77enT5u9agFemHPv"); minio.BucketName = cfg.GetValue("MinIO:BucketName", "default"); minio.WithSSL = false; }); }); }); } /// /// 大众-存储二配实际输出表 /// /// private void ConfigureBLOBSecSummaryServices(IConfiguration configPath) { Configure(options => { options.Containers.Configure(configuration => { configuration.UseFileSystem(fileSystem => { var filestreampath = Environment.CurrentDirectory + @"\wwwroot\secsummary\files"; if (!Directory.Exists(filestreampath)) { Directory.CreateDirectory(filestreampath); } fileSystem.BasePath = filestreampath; }); }); }); } /// /// 奔腾-二配实际输出打印表的保存路径 /// /// private void ConfigureBLOBTSecSummaryServices(IConfiguration configPath) { Configure(options => { options.Containers.Configure(configuration => { configuration.UseFileSystem(fileSystem => { var filestreampath = Environment.CurrentDirectory + @"\wwwroot\btsecsummary\files"; if (!Directory.Exists(filestreampath)) { Directory.CreateDirectory(filestreampath); } fileSystem.BasePath = filestreampath; }); }); }); } private static void ConfigureJson(ServiceConfigurationContext context) { //null: DTO的属性首字母保持大写 //JsonNamingPolicy.CamelCase; : DTO的属性首字母改为小写 context.Services.Configure(opt => { opt.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; //opt.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter()); }); } private void ConfigureException() { //将错误明细发送给客户端 Configure(options => { options.SendExceptionsDetailsToClients = true; }); Configure(options => { var index = options.Filters.ToList().FindIndex(filter => filter is ServiceFilterAttribute attr && attr.ServiceType.Equals(typeof(AbpExceptionFilter))); if (index > -1) { options.Filters.RemoveAt(index); } options.Filters.Add(typeof(CustomExceptionFilter)); }); } private void ConfigureMultiTenancy() { Configure(options => { options.IsEnabled = true; }); } private void ConfigureConventionalControllers() { Configure(options => { options .ConventionalControllers .Create(typeof(SettleAccountApplicationModule).Assembly, opts => { opts.RootPath = "settleaccount"; }); }); } private void ConfigureCache(IConfiguration configuration) { Configure(options => { options.KeyPrefix = "SettleAccount:"; }); } private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); if (hostingEnvironment.IsDevelopment()) { Configure(options => { options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}SettleAccount.Domain")); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}SettleAccount.Application.Contracts")); options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}SettleAccount.Application")); }); } } private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) { var isAlwaysAllowAuthorization = configuration.GetValue("AuthServer:AlwaysAllowAuthorization"); if (isAlwaysAllowAuthorization) { //绕过授权服务,用于测试 context.Services.AddAlwaysAllowAuthorization(); } else { //context.Services.AddAuthentication("Bearer") // .AddIdentityServerAuthentication(options => // { // options.Authority = configuration["AuthServer:Authority"]; // options.RequireHttpsMetadata = false; // options.ApiName = "SettleAccount"; // }); context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = configuration["AuthServer:Authority"]; options.RequireHttpsMetadata = false; options.Audience = "SettleAccount"; }); } } private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) { var defaultBranchId = configuration["DefaultBranchId"]; context.Services.AddSwaggerGen( options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "Settle Account Service API", Version = "v1" }); options.DocInclusionPredicate((docName, description) => true); //解决相同方法名冲突 options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); options.OperationFilter(defaultBranchId); var xmlapppath = Path.Combine(AppContext.BaseDirectory, "SettleAccount.Application.xml"); if (File.Exists(xmlapppath)) { options.IncludeXmlComments(xmlapppath, true); } xmlapppath = Path.Combine(AppContext.BaseDirectory, "SettleAccount.Application.Contracts.xml"); if (File.Exists(xmlapppath)) { options.IncludeXmlComments(xmlapppath, true); } options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "请输入 JWT Token", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.Http, Scheme = "Bearer" }); options.AddSecurityRequirement(new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme, Id = "Bearer"} }, new string[] { } } }); }); } private void ConfigureLocalization() { Configure(options => { options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); }); } private void ConfigureRedis( ServiceConfigurationContext context, IConfiguration configuration) { var hostingEnvironment = context.Services.GetHostingEnvironment(); //context.Services.AddStackExchangeRedisCache(options => //{ // options.Configuration = configuration["Redis:Configuration"]; //}); //if (!hostingEnvironment.IsDevelopment()) //{ // var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); // context.Services // .AddDataProtection() // .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys"); //} } private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.AddHangfire(config => { config.UseSqlServerStorage(configuration.GetConnectionString("SettleAccountService"), new Hangfire.SqlServer.SqlServerStorageOptions { PrepareSchemaIfNecessary = true }); }); } private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) { context.Services.AddCors(options => { options.AddPolicy(DefaultCorsPolicyName, builder => { builder .WithOrigins( configuration["App:CorsOrigins"] .Split(",", StringSplitOptions.RemoveEmptyEntries) .Select(o => o.RemovePostFix("/")) .ToArray() ) .WithAbpExposedHeaders() .SetIsOriginAllowedToAllowWildcardSubdomains() .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); app.UseCorrelationId(); //app.UseVirtualFiles(); app.UseRouting(); app.UseCors(DefaultCorsPolicyName); app.UseAuthentication(); app.UseAuthorization(); app.UseAbpClaimsMap(); if (MultiTenancyConsts.IsEnabled) { app.UseMultiTenancy(); } app.UseAbpRequestLocalization(); app.UseSwagger(); app.UseSwaggerUI(options => { options.SwaggerEndpoint("/swagger/v1/swagger.json", "Settle Account Service API"); options.DocExpansion(DocExpansion.None); //->修改界面打开时自动折叠 }); new BackgroundJobServerOptions() { WorkerCount = 12, ServerTimeout = TimeSpan.FromSeconds(1200) }; app.UseHangfireServer(); app.UseHangfireDashboard(); app.UseAuditing(); app.UseAbpSerilogEnrichers(); app.UseConfiguredEndpoints(); AsyncHelper.RunSync(async () => { using (var scope = context.ServiceProvider.CreateScope()) { await scope.ServiceProvider .GetRequiredService() .SeedAsync(); } }); } } public class CustomExceptionFilter : IExceptionFilter { private readonly ILogger logger; public CustomExceptionFilter(ILogger logger) { this.logger = logger; } public void OnException(ExceptionContext context) { logger.LogError(new EventId(context.Exception.HResult), context.Exception, context.Exception.Message); var message = context.Exception.InnerException?.InnerException?.Message ?? context.Exception.Message; context.Result = new JsonResult(new { code = 400, message }); context.ExceptionHandled = true; } } }