You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

499 lines
19 KiB

using System;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.InkML;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using NUglify.Helpers;
using Serilog.Formatting.Json;
using StackExchange.Redis;
using Swashbuckle.AspNetCore.SwaggerGen;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling;
using Volo.Abp.AutoMapper;
using Volo.Abp.Caching;
using Volo.Abp.Content;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Guids;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Timing;
using Win_in.Sfs.Shared.Application;
using Win_in.Sfs.Shared.Application.Contracts.ExportAndImport;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Shared.Host;
public abstract class ModuleBase<T> : AbpModule where T : AbpModule
{
static ModuleBase()
{
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var cfg = context.Services.GetConfiguration();
ServiceConfigurationContext.SetConsoleTitleOfWebApp(Assembly.GetEntryAssembly().GetName().Name);
LimitedResultRequestDto.MaxMaxResultCount = 100000;
//接口请求限制
context.Services.Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = int.MaxValue;
});
context.Services.Configure<FormOptions>(x =>
{
x.ValueLengthLimit = int.MaxValue;
x.MultipartBodyLengthLimit = int.MaxValue;
});
//context.Services.AddAgileConfig();
PreConfigureServices(context);
ConfigureAntiForgery();
ConfigureLocalizationServices();
ConfigureAuthentication();
ConfigureDistributedCache();
ConfigureDatabase(context, cfg);
ConfigureHttpClientProxies();
ConfigureAutoMapper();
ConfigureLocalizationServices();
ConfigureAutoApiControllers();
ConfigureSwaggerServices();
ConfigureAddCors();
Configure();
SetFormLimit();
ConfigureExceptionHanding();
}
private void ConfigureDatabase(ServiceConfigurationContext context, IConfiguration cfg)
{
var db = cfg.GetValue("Database", "SQLite");
SequentialGuidType? sequentialGuidType = null;
if (db == "MySQL" || db == "PostgreSql")
{
sequentialGuidType = SequentialGuidType.SequentialAsString;
}
else if (db == "SQLServer")
{
sequentialGuidType = SequentialGuidType.SequentialAtEnd;
}
else if (db == "Oracle")
{
sequentialGuidType = SequentialGuidType.SequentialAsBinary;
}
context.Services.Configure<AbpSequentialGuidGeneratorOptions>(o => o.DefaultSequentialGuidType = sequentialGuidType);
Configure<AbpDbContextOptions>(options =>
{
if (db == "MySQL")
{
options.UseMySQL();
}
else if (db == "SQLServer")
{
options.UseSqlServer();
}
else if (db == "Oracle")
{
options.UseOracle();
}
else if (db == "PostgreSql")
{
options.UseNpgsql();
}
else
{
options.UseSqlite();
}
});
}
public override async Task ConfigureServicesAsync(ServiceConfigurationContext context)
{
await base.ConfigureServicesAsync(context).ConfigureAwait(false);
}
public virtual void CreateDatabase<TEfCoreDbContext>(ApplicationInitializationContext context) where TEfCoreDbContext : IEfCoreDbContext
{
//Console.WriteLine($"应用版本:{Assembly.GetEntryAssembly().GetFileVersion()}");
////if (!context.GetEnvironment().IsDevelopment())
////{
//// Console.WriteLine($"生产模式不执行数据库初始化");
//// return;
////}
//using var scope = context.ServiceProvider.CreateScope();
//var contextName = typeof(TEfCoreDbContext).Name;
////var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
////using var uow = uowManager.Begin();
//var provider = scope.ServiceProvider.GetRequiredService<IDbContextProvider<TEfCoreDbContext>>();
////using var dbContext = provider.GetDbContextAsync().Result;
//using var dbContext = scope.ServiceProvider.GetRequiredService(typeof(TEfCoreDbContext)) as DbContext;
//dbContext.Database.SetCommandTimeout(TimeSpan.FromMinutes(10));
//var dbCreator = dbContext.GetService<IRelationalDatabaseCreator>() as RelationalDatabaseCreator;
//var sql = dbCreator.GenerateCreateScript();
//sql = dbContext.Database.ProviderName.Contains("SqlServer") ? Regex.Replace(sql, ";\\s+GO\\s", " ") : sql;
//var md5 = sql.Md5();
//var path = Path.Combine(Directory.GetCurrentDirectory(), "scripts");
//Directory.CreateDirectory(path);
//using var sw = File.CreateText(Path.Combine(path, $"db.{dbContext.Database.ProviderName}.{contextName}.sql"));
//sw.Write(sql);
//Console.WriteLine($"{contextName} 初始化开始");
//Console.WriteLine($"ConnectionString:{dbContext.Database.GetConnectionString()}");
////创建数据库
//if (!dbCreator.Exists())
//{
// dbCreator.Create();
// var createSql = "CREATE TABLE EFDbContext(Id varchar(255) NOT NULL,Hash varchar(255) NOT NULL,PRIMARY KEY (Id));";
// dbContext.Database.ExecuteSqlRaw(createSql);
//}
//// 查询当前DbContext是否已经初始化
//using var conn = dbContext.Database.GetDbConnection();
//var cmd = conn.CreateCommand();
//conn.Open();
//cmd.CommandText = $"SELECT Hash FROM EFDbContext where Id='{contextName}'";
//var hash = cmd.ExecuteScalar();
////conn.Close();
////conn.Dispose();
//if (hash == null)
//{
// try
// {
// //dbContext.Database.BeginTransaction();
// dbContext.Database.ExecuteSqlRaw(sql);
// dbContext.Database.ExecuteSqlRaw($"INSERT INTO EFDbContext VALUES ('{contextName}', '{md5}');");
// context.ServiceProvider
// .GetRequiredService<IDataSeeder>()
// .SeedAsync()
// .Wait();
// //dbContext.Database.CommitTransaction();
// Console.WriteLine($"{contextName} 初始化成功");
// }
// catch (Exception ex)
// {
// //dbContext.Database.RollbackTransaction();
// var message = $"{contextName} 初始化失败:{ex.Message}";
// Console.WriteLine(message);
// Console.WriteLine(ex.ToString());
// throw new Exception(message, ex);
// }
// finally
// {
// Console.WriteLine($"{contextName} 初始化结束");
// }
//}
//else
//{
// Console.WriteLine($"{contextName} 数据库结构{(hash.ToString() == md5 ? "正常" : "已过时")}");
//}
//uow.CompleteAsync();
//conn.Close();
//conn.Dispose();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
//
base.OnApplicationInitialization(context);
var app = context.GetApplicationBuilder();
app.UseDeveloperExceptionPage();
app.UseAbpRequestLocalization();
app.UseCorrelationId();
app.UseStaticFiles();
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseJwtTokenMiddleware();
app.UseUnitOfWork();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
var apiDescriptionGroups = context.ServiceProvider.GetRequiredService<IApiDescriptionGroupCollectionProvider>().ApiDescriptionGroups.Items;
foreach (var description in apiDescriptionGroups)
{
if (description.GroupName is not null)
{
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName);
}
else
{
options.SwaggerEndpoint($"/swagger/Default/swagger.json", "Default");
}
}
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseConfiguredEndpoints();
context.ServiceProvider.InitSettings();
UseMultiTenancy(context);
}
protected virtual void Configure()
{
//todo 解决时间
// ServiceConfigurationContext.Services.AddTransient<IJsonSerializer,ConvertAbpJson>();
}
protected virtual void ConfigureAddCors()
{
var origins = ServiceConfigurationContext.Services.GetConfiguration().GetSection("App:CorsOrigins").Get<string[]>() ?? Array.Empty<string>();
Console.WriteLine($"CORS Origins:{string.Concat(origins)}");
ServiceConfigurationContext.Services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder =>
{
builder.SetIsOriginAllowed(_ => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
});
});
}
protected virtual void ConfigureAntiForgery()
{
Configure<AbpAntiForgeryOptions>(options =>
{
options.TokenCookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
options.TokenCookie.Expiration = TimeSpan.FromDays(365);
options.AutoValidateIgnoredHttpMethods.Add("POST");
});
}
protected virtual void ConfigureAuditing()
{
}
protected virtual void ConfigureAuthentication()
{
var configuration = ServiceConfigurationContext.Services.GetConfiguration();
ServiceConfigurationContext.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
options.Audience = configuration["AuthServer:Audience"];
});
var isAlwaysAllowAuthorization = configuration.GetValue<bool>("AlwaysAllowAuthorization");
if (isAlwaysAllowAuthorization)
{
//绕过授权服务,用于测试
ServiceConfigurationContext.Services.AddAlwaysAllowAuthorization();
}
}
protected virtual void ConfigureAutoApiControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
AppDomain.CurrentDomain.GetAssemblies()
.Where(assembly => assembly.FullName.StartsWith("Win_in.Sfs"))
.ForEach(assembly => options.ConventionalControllers.Create(assembly));
});
}
protected virtual void ConfigureAutoMapper()
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<T>();
});
}
protected virtual void ConfigureBundles()
{
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(
BasicThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/global-styles.css");
}
);
});
}
protected virtual void ConfigureDbContext(IConfiguration configuration)
{
Configure<AbpDbContextOptions>(options =>
{
options.UseDatabase(configuration);
});
}
protected virtual void ConfigureDistributedCache()
{
var evn = ServiceConfigurationContext.Services.GetHostingEnvironment();
var cfg = ServiceConfigurationContext.Services.GetConfiguration();
Configure<AbpDistributedCacheOptions>(options => { options.KeyPrefix = cfg["Redis:KeyPrefix"]; });
if (!evn.IsDevelopment())
{
var redis = ConnectionMultiplexer.Connect(cfg["Redis:Configuration"]);
ServiceConfigurationContext.Services
.AddDataProtection()
.PersistKeysToStackExchangeRedis(redis, $"{Assembly.GetEntryAssembly().GetName().Name}-Protection-Keys");
}
}
protected virtual void ConfigureExceptionHandling()
{
Configure<AbpExceptionHandlingOptions>(options =>
{
options.SendExceptionsDetailsToClients = true; //向前端返回完整错误日志
});
}
protected virtual void ConfigureHttpClientProxies()
{
}
protected virtual void ConfigureLocalizationServices()
{
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
});
}
protected virtual void ConfigureSwaggerServices()
{
var services = ServiceConfigurationContext.Services;
var cfg = ServiceConfigurationContext.Services.GetConfiguration();
var name = Assembly.GetEntryAssembly().GetName().Name;
var urlBase = cfg["AuthServer:Authority"].EnsureEndsWith('/');
services.AddSingleton<IExportImportService, ClosedXmlExportImportService>();
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, SwaggerConfigureOptions>();
services.AddSwaggerGen(options =>
{
var schemaFactory = () => new OpenApiSchema
{
Type = "string",
Format = "binary"
};
options.MapType<RemoteStreamContent>(schemaFactory);
options.MapType<IRemoteStreamContent>(schemaFactory);
//
options.DocumentFilter<SwaggerFilter>();
options.OperationFilter<SwaggerFilter>();
options.SchemaFilter<SwaggerFilter>();
options.AddSecurityDefinition(nameof(SecuritySchemeType.Http), new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference {
Type = ReferenceType.SecurityScheme,
Id = nameof(SecuritySchemeType.Http)
}
},
Array.Empty<string>()
}
});
options.SwaggerDoc("v1", new OpenApiInfo { Title = $"{name} API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
options.DocInclusionPredicate((docName, api) => api.GroupName == null || api.GroupName == docName);
AppDomain.CurrentDomain.GetAssemblies()
.Where(o => o.GetName().Name.StartsWith(nameof(Win_in)) && o.GetName().Name.EndsWith(".Application"))
.Select(o => Path.Combine(Path.GetDirectoryName(o.Location), $"{Path.GetFileNameWithoutExtension(o.Location)}.xml"))
.Where(o => File.Exists(o))
.ForEach(o => options.IncludeXmlComments(o));
});
}
protected virtual void SetFormLimit()
{
ServiceConfigurationContext.Services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue; // 5000 items max
options.ValueLengthLimit = 1024 * 1024 * 1000; // 100MB max len form data
});
}
protected virtual void UseMultiTenancy(ApplicationInitializationContext context)
{
if (Convert.ToBoolean(context.GetConfiguration().GetValue("IsMultiTenancy", false)))
{
context.GetApplicationBuilder().UseMultiTenancy();
}
}
private void ConfigureExceptionHanding()
{
Configure<AbpExceptionHandlingOptions>(options =>
{
options.SendExceptionsDetailsToClients = true;
});
}
/// <summary>
/// 为了处理abp的时间存入redis 在win环境读取出来报错
/// </summary>
public class ConvertAbpJson : IJsonSerializer
{
public T Deserialize<T>(string jsonString, bool camelCase = true)
{
return System.Text.Json.JsonSerializer.Deserialize<T>(jsonString, GetOptions(camelCase));
}
public object Deserialize(Type type, string jsonString, bool camelCase = true)
{
return System.Text.Json.JsonSerializer.Deserialize(jsonString, type, GetOptions(camelCase));
}
public string Serialize(object obj, bool camelCase = true, bool indented = false)
{
return System.Text.Json.JsonSerializer.Serialize(obj, GetOptions(camelCase, indented));
}
private System.Text.Json.JsonSerializerOptions GetOptions(bool camelCase = true, bool indented = false)
{
return new System.Text.Json.JsonSerializerOptions
{
PropertyNameCaseInsensitive = camelCase,
WriteIndented = indented,
ReferenceHandler = ReferenceHandler.IgnoreCycles
};
}
}
}