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

503 lines
19 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Reflection;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using ce.autofac.extension;
using IdentityServer4.AccessTokenValidation;
using Infrastructure;
using Infrastructure.Cache;
using Infrastructure.CloudSdk.minio;
using Infrastructure.CloudSdk.mqttmessagecenter;
using Infrastructure.Extensions.AutofacManager;
using Infrastructure.Helpers;
using Infrastructure.Middleware;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using Npgsql;
using OpenAuth.App;
using OpenAuth.App.BaseApp.ImMsgManager;
using OpenAuth.App.HostedService;
using OpenAuth.App.ServiceApp;
using OpenAuth.Repository;
using OpenAuth.WebApi.Model;
using OpenAuth.WebApi.Model.mqtt;
using OpenAuth.WebApi.Model.RabbitMQService;
using OpenAuth.WebApi.SystemTask;
using SqlSugar;
using Swashbuckle.AspNetCore.SwaggerUI;
using Yitter.IdGenerator;
namespace OpenAuth.WebApi
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public Startup(ConfigurationManager configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
SQLitePCL.Batteries_V2.Init();
services.AddHttpContextAccessor();
services.AddSingleton<MqttClientManager>();
services.AddSingleton<EncryptionHelper>();
// minio client
services.AddSingleton(_ => new MinioService());
#region log4net
//在startup中需要强制创建log4net
//var loggerFactory = LoggerFactory.Create(builder => { builder.AddLog4Net(); });
//ILogger logger = loggerFactory.CreateLogger<Startup>();
services.AddLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
loggingBuilder.AddLog4Net();
});
#endregion
#region identityServer
var identityServer =
((ConfigurationSection)Configuration.GetSection("AppSetting:IdentityServerUrl")).Value;
if (!string.IsNullOrEmpty(identityServer))
{
services.AddAuthorization();
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = identityServer;
options.RequireHttpsMetadata = false; // 指定是否为HTTPS
options.Audience = "openauthapi";
});
}
#endregion
#region MiniProfiler
// 添加MiniProfiler服务
//services.AddMiniProfiler(options =>
//{
// // 设定访问分析结果URL的路由基地址
// options.RouteBasePath = "/profiler";
// options.ColorScheme = StackExchange.Profiling.ColorScheme.Auto;
// options.PopupRenderPosition = StackExchange.Profiling.RenderPosition.BottomLeft;
// options.PopupShowTimeWithChildren = true;
// options.PopupShowTrivial = true;
// options.SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter();
// // options.IgnoredPaths.Add("/swagger/");
//}).AddEntityFramework(); //显示SQL语句及耗时
#endregion
#region swagger
//添加swagger
services.AddSwaggerGen(option =>
{
#region 注释
//foreach (var controller in GetControllers())
//{
// var groupname = GetSwaggerGroupName(controller);
// option.SwaggerDoc(groupname, new OpenApiInfo
// {
// Version = "v1",
// Title = groupname,
// Description = "by hopetry"
// });
//}
//foreach (var name in Directory.GetFiles(AppContext.BaseDirectory, "*.*",
// SearchOption.AllDirectories).Where(f => Path.GetExtension(f).ToLower() == ".xml"))
//{
// option.IncludeXmlComments(name, includeControllerXmlComments: true);
//}
#endregion
option.CustomSchemaIds(type => type.FullName);
option.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "低空态势感知平台 API",
Description = "by hopetry"
});
//option.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "OpenAuth.WebApi.xml"), true);
option.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "OpenAuth.WebApi.xml"), true);
option.OperationFilter<GlobalHttpHeaderOperationFilter>(); // 添加httpHeader参数
});
//services.AddSwaggerGen(option =>
//{
// option.CustomSchemaIds(type => type.FullName);
// option.SwaggerDoc("v1", new OpenApiInfo
// {
// Version = "v1",
// Title = "无人值守 WebAPI",
// Description = "by HopetryTech"
// });
// option.CustomOperationIds(apiDesc =>
// {
// var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor;
// return controllerAction.ControllerName + "-" + controllerAction.ActionName;
// });
// option.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "OpenAuth.WebApi.xml"), true);
// option.OperationFilter<GlobalHttpHeaderOperationFilter>(); // 添加httpHeader参数
//});
#endregion
#region mqtt
services.AddSingleton<MqttMessageCenter>();
services.AddSingleton<IMqttMessageHandler, ThingRequestHandler>();
services.AddSingleton<IMqttMessageHandler, ThingServiceHandler>();
services.AddSingleton<IMqttMessageHandler, ThingOsdHandler>();
services.AddSingleton<IMqttMessageHandler, ThingEventHandler>();
//services.AddSingleton<IMqttMessageHandler, ThingDrcHandler>();
services.AddSingleton<IMqttMessageHandler, ThingStatusHandler>();
services.AddHostedService<MqttHostedService>();
#endregion
services.AddHostedService<DelayedExecutionService>();
#region rabbitmq
services.AddSingleton<RabbitMqListenerService>();
services.AddHostedService(sp => sp.GetRequiredService<RabbitMqListenerService>());
#endregion
#region AppSetting
services.Configure<AppSetting>(Configuration.GetSection("AppSetting"));
#endregion
#region 限制文件大小
services.Configure<KestrelServerOptions>(options => { options.Limits.MaxRequestBodySize = long.MaxValue; });
services.Configure<FormOptions>(x =>
{
x.ValueLengthLimit = int.MaxValue;
x.MultipartBodyLengthLimit = long.MaxValue;
x.MemoryBufferThreshold = int.MaxValue;
});
#endregion
#region Controllers
services.AddControllers(option =>
{
option.Filters.Add<OpenAuthFilter>();
//option.Filters.Add<TransactionFilter>();
//option.Filters.Add<GlobalExceptionFilter>();
})
.ConfigureApiBehaviorOptions(options =>
{
// 禁用自动模态验证
// options.SuppressModelStateInvalidFilter = true;
//启动WebAPI自动模态验证处理返回值
options.InvalidModelStateResponseFactory = context =>
{
var problems = new CustomBadRequest(context);
return new BadRequestObjectResult(problems);
};
}).AddNewtonsoftJson(options =>
{
//忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
//不使用驼峰样式的key
//options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
});
#endregion
#region MemoryCache
services.AddMemoryCache();
services.AddSingleton<RedisCacheContext>();
#endregion
#region Cors
services.AddCors(options =>
{
//options.AddPolicy("CorsPolicy",
// builder => builder.SetIsOriginAllowed(origin => true)
// .AllowAnyMethod()
// .AllowAnyHeader()
// .AllowCredentials()
// );
options.AddPolicy("SignalR",
builder => builder.SetIsOriginAllowed(origin => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
//options.AddPolicy("CorsPolicy",
// builder => builder.AllowAnyOrigin()
// .AllowAnyMethod()
// .AllowAnyHeader());
});
#endregion
#region SqlSugar
////没有直接 using SqlSugar因为如果引用命名空间的话会和Microsoft的一个GetTypeInfo存在二义性所以就直接这么使用了
services.AddScoped<ISqlSugarClient>(s =>
{
StaticConfig.CustomSnowFlakeFunc = () => { return YitIdHelper.NextId(); };
var sqlSugar = new SqlSugarClient(new ConnectionConfig()
{
DbType = DbType.PostgreSQL,
ConnectionString = Configuration.GetConnectionString("OpenAuthDBContext"),
IsAutoCloseConnection = true,
MoreSettings = new ConnMoreSettings()
{
PgSqlIsAutoToLower = false,
PgSqlIsAutoToLowerCodeFirst = false
}
},
//var sqlSugar = new SqlSugarClient(new ConnectionConfig()
//{
// DbType = SqlSugar.DbType.Kdbndp,
// ConnectionString = Configuration.GetConnectionString("OpenAuthDBContext"),
// IsAutoCloseConnection = true,
// MoreSettings = new SqlSugar.ConnMoreSettings()
// {
// //PgSqlIsAutoToLower = false,
// //PgSqlIsAutoToLowerCodeFirst = false,
// IsAutoToUpper = false,
// DatabaseModel = DbType.PostgreSQL
// }
//},
db =>
{
NpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite();
//单例参数配置,所有上下文生效
db.Aop.OnLogExecuting = (sql, pars) =>
{
//获取原生SQL推荐 5.1.4.63 性能OK
//UtilMethods.GetNativeSql(sql, pars);
//获取无参数化SQL 影响性能只适合调试
//Console.WriteLine(UtilMethods.GetSqlString(DbType.PostgreSQL, sql, pars));
//Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
//LogHelper.LogInformation(sql + "\r\n" +db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
//Console.WriteLine();
};
});
return sqlSugar;
});
services.AddScoped<ISugarUnitOfWork<SugarDbContext>>(s =>
new SugarUnitOfWork<SugarDbContext>(s.GetService<ISqlSugarClient>()));
#endregion
#region HttpClient
services.AddHttpClient();
#endregion
#region DataProtection
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(Configuration["DataProtection"]));
#endregion
#region Quartz
services.AddHostedService<QuartzService>();
#endregion
#region SignalR
services.AddSignalR();
#endregion
}
public void ConfigureContainer(ContainerBuilder builder)
{
AutofacExt.InitAutofac(builder);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
//public void Configure(IApplicationBuilder app, IHostEnvironment env, ILogger<Startup> loggerFactory)
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
//loggerFactory.AddLog4Net();
IocManager.Instance.Container = app.ApplicationServices.GetAutofacRoot();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMiniProfiler();
//可以访问根目录下面的静态文件
var staticfile = new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(AppContext.BaseDirectory),
OnPrepareResponse = (ctx) =>
{
//可以在这里为静态文件添加其他http头信息默认添加跨域信息
ctx.Context.Response.Headers["Access-Control-Allow-Origin"] = "*";
},
ContentTypeProvider = new FileExtensionContentTypeProvider(
new Dictionary<string, string>
{
{ ".amr", "audio/AMR" },
{ ".mp3", "audio/mpeg" },
{ ".mp4", "video/mp4" },
{ ".apk", "application/vnd.android.package-archive" },
{ ".cpg", "application/vnd.android.package-archive" },
{ ".dbf", "application/vnd.android.package-archive" },
{ ".shp", "application/vnd.android.package-archive" },
{ ".shx", "application/vnd.android.package-archive" },
{ ".zip", "application/zip" },
{ ".jpeg", "image/jpeg" },
{ ".jpg", "image/jpg" },
{ ".png", "image/png" },
{ ".docx", "application/msword" },
{ ".doc", "application/msword" },
{ ".txt", "application/octet-stream" },
{ ".xlsx", "application/octet-stream" },
{ ".xls", "application/vnd.ms-excel" },
{ ".pdf", "application/pdf" },
{ ".js","application/javascript" },
{ ".cjs","application/javascript" },
{ ".pt", "application/octet-stream" },
})
};
app.UseStaticFiles(staticfile);
//todo:测试可以允许任意跨域,正式环境要加权限
app.UseRouting();
app.UseCors("SignalR");
app.UseAuthentication();
// 启用日志追踪记录和异常友好提示
app.UseLogMiddleware();
//配置ServiceProvider
AutofacContainerModule.ConfigServiceProvider(app.ApplicationServices);
//app.UseSwagger();
app.UseSwagger(options =>
{
options.PreSerializeFilters.Add((swagger, httpReq) =>
{
if (httpReq.Headers.ContainsKey("X-Request-Uri"))
{
var index = httpReq.Headers["X-Request-Uri"].ToString().IndexOf("/swagger/");
if (index > 0)
{
var serverUrl = $"{httpReq.Headers["X-Request-Uri"].ToString().Substring(0, index)}/";
swagger.Servers = new List<OpenApiServer> { new OpenApiServer { Url = serverUrl } };
}
}
});
});
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
//foreach (var controller in GetControllers())
//{
// var groupname = GetSwaggerGroupName(controller);
// c.SwaggerEndpoint($"{groupname}/swagger.json", groupname);
//}
c.SwaggerEndpoint("v1/swagger.json", "V1 Docs");
c.DocExpansion(DocExpansion.List); //默认展开列表
c.OAuthClientId("OpenAuth.WebApi"); //oauth客户端名称
c.OAuthAppName("开源版webapi认证"); // 描述
});
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("v1/swagger.json", "V1 Docs");
c.DocExpansion(DocExpansion.None);
c.OAuthClientId("OpenAuth.WebApi"); //oauth客户端名称
c.OAuthAppName("开源版webapi认证"); // 描述
});
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatsHub>("/chathub").RequireCors("SignalR"); // 配置 SignalR Hub 的路由
endpoints.MapControllers();
//endpoints.MapHub<ChatsHub>("/chathub"); // 配置 SignalR Hub 的路由
// endpoints.MapControllers().RequireCors("CorsPolicy");
});
}
/// <summary>
/// 获取控制器对应的swagger分组值
/// </summary>
private string GetSwaggerGroupName(Type controller)
{
var groupname = controller.Name.Replace("Controller", "");
var apisetting = controller.GetCustomAttribute(typeof(ApiExplorerSettingsAttribute));
if (apisetting != null)
{
groupname = ((ApiExplorerSettingsAttribute)apisetting).GroupName;
}
return groupname;
}
/// <summary>
/// 获取所有的控制器
/// </summary>
private List<Type> GetControllers()
{
Assembly asm = Assembly.GetExecutingAssembly();
var controlleractionlist = asm.GetTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type))
.OrderBy(x => x.Name).ToList();
return controlleractionlist;
}
}
}