using Hangfire; using Hangfire.MemoryStorage; using Infrastructure.Data; using Infrastructure.Events; using Infrastructure.Jwt; using Infrastructure.Office; using Infrastructure.Security; using Infrastructure.UI; using Infrastructure.Web.Authentication.Cookies; using Infrastructure.Web.Mvc.ModelBinding.Metadata; using Infrastructure.Web.SignalR; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System; using System.Globalization; using System.Linq; using System.Reflection; using System.Text.Encodings.Web; using System.Text.Unicode; using System.Threading.Tasks; namespace Infrastructure.Web { public class BaseStartup { private readonly IConfiguration _cfg; private readonly IWebHostEnvironment _env; private readonly bool _useMiniProfiler; private string _connectionString; private bool _useSqlite; private readonly string _origins = "AllowAllHeaders"; public BaseStartup(IConfiguration configuration, IWebHostEnvironment env) { this._cfg = configuration; this._env = env; this._useMiniProfiler = this._cfg.GetValue("UseMiniProfiler", false); } public virtual void ConfigureServices(IServiceCollection services) { if (!this._env.IsDevelopment()) { services.AddResponseCompression(options => { options.Providers.Add(); options.Providers.Add(); }); } services.AddSingleton(_cfg as IConfigurationRoot); services.AddCors(options => options.AddPolicy(_origins, builder => { builder.SetIsOriginAllowed(o => true) .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); })); services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All)); services.Configure(o => { o.ValueCountLimit = int.MaxValue; o.MultipartBodyLengthLimit = long.MaxValue; }); this.ConfigureOptions(services); EfDbContext.OnModelCreatingAction = this.OnModelCreating; services.AddScoped(); this._useSqlite = this._cfg.GetSection("AppSettings").GetValue("database") == "sqlite"; if (_useSqlite) { _connectionString = this._cfg.GetConnectionString("database.sqlite.connection"); services.AddDbContext(options => options.UseSqlite(_connectionString)); } else { _connectionString = this._cfg.GetConnectionString("database.mysql.connection"); services.AddDbContext(options => options.UseMySql(_connectionString)); } //https://github.com/aspnet/Entropy/blob/master/samples/Localization.StarterWeb/Startup.cs services.AddLocalization(options => options.ResourcesPath = null); //https://yetawf.com/BlogEntry/Title/AdditionalMetadataAttribute%20Anyone/?BlogEntry=1005 services.AddMvc(o => o.ModelMetadataDetailsProviders.Add(new AdditionalMetadataProvider())) .SetCompatibilityVersion(CompatibilityVersion.Latest) .AddNewtonsoftJson() .AddControllersAsServices() .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) .AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => { var localizer = factory.Create("Resources.Resource", Assembly.GetEntryAssembly().FullName); return localizer; }; }); services.AddControllers().AddNewtonsoftJson(o => { o.SerializerSettings.ContractResolver = new DefaultContractResolver(); o.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); services.Configure(o => { var supportedCultures = new[] { new CultureInfo("zh-CN"), new CultureInfo("en-US") }; o.DefaultRequestCulture = new RequestCulture(culture: "zh-CN", uiCulture: "zh-CN"); o.SupportedCultures = supportedCultures; o.SupportedUICultures = supportedCultures; }); this.AddAuthentication(services); this.AddSwagger(services); services.AddDistributedMemoryCache(); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; }); services.AddHttpClient(); services.AddSignalR(o => o.EnableDetailedErrors = true) .AddJsonProtocol(options => { //options.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver(); }); this.UseScheduler(services); services.AddMemoryCache(); services.AddHttpContextAccessor(); services.AddSingleton(); services.AddTransient(typeof(IRepository<>), typeof(EfRepository<>)); services.AddTransient(); services.AddTransient(); services.AddTransient(); AppDomain.CurrentDomain.GetAssemblies().SelectMany(o => o.GetTypes()) .Where(t => t.GetInterfaces().Any(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEventHander<>))) .ToList() .ForEach(t => { t.GetInterfaces().Where(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEventHander<>)).ToList().ForEach(o => { services.AddTransient(o, t); }); }); services.AddSingleton(); } public virtual void UseScheduler(IServiceCollection services) { services.AddHangfire(x => x.UseMemoryStorage()); } public virtual void ConfigureOptions(IServiceCollection services) { services.ConfigureOptions(new FileConfigureOptions(this._env)); } public virtual void AddAuthentication(IServiceCollection services) { services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, opts => { opts.Cookie.Name = this.GetType().FullName; opts.LoginPath = "/Account/Login"; opts.LogoutPath = "/Account/Logout"; opts.AccessDeniedPath = "/Account/AccessDenied"; //不配置SessionStore则存储到cookie var useCookieSessionStore = this._cfg.GetSection("AppSettings").GetValue("UseCookieSessionStore"); if (!useCookieSessionStore) { opts.SessionStore = services.BuildServiceProvider().GetService(); } opts.Events = new CookieAuthenticationEvents { //OnRedirectToLogin = RedirectToLogin(), OnValidatePrincipal = ValidatePrincipal }; }); } public virtual void AddSwagger(IServiceCollection services) { services.AddSwaggerGen(c => { c.SwaggerDoc(this._cfg.GetValue("openapi.name", "v1"), new OpenApiInfo { Title = this._cfg.GetValue("openapi.title", "web api"), Version = this._cfg.GetValue("openapi.version", "1.0") }); c.EnableAnnotations(); }); } public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) { if (app == null) { throw new ArgumentNullException(nameof(app)); } if (!env.IsDevelopment()) { app.UseResponseCompression(); } if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); app.UseStatusCodePagesWithReExecute("/Error"); } app.UseStaticFiles(); app.UseRouting(); app.UseCors(_origins); var localizationOption = app.ApplicationServices.GetService>(); app.UseRequestLocalization(localizationOption.Value); app.UseSession(); this.UseAuthentication(app); this.UseSwagger(app); this.UseScheduler(app); app.UseEndpoints(endpoints => { this.UseSignalR(endpoints); endpoints.MapControllerRoute( name: "areas", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); using var scope = app.ApplicationServices.CreateScope(); var services = scope.ServiceProvider; var context = services.GetService(); var configuration = services.GetService(); if (context.Database.EnsureCreated()) { this.Seed(context, services, configuration); } } public virtual void UseAuthentication(IApplicationBuilder app) { app.UseAuthentication(); app.UseAuthorization(); } public virtual void UseSwagger(IApplicationBuilder app) { app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1"); }); } public virtual void UseScheduler(IApplicationBuilder app) { app.UseHangfireDashboard(); app.UseHangfireServer(); } public virtual void UseSignalR(IEndpointRouteBuilder endpoints) { this.UseSignalR(endpoints); } protected virtual void UseSignalR(IEndpointRouteBuilder endpoints) where T : Hub { endpoints.MapHub("/hub", o => { o.ApplicationMaxBufferSize = long.MaxValue; o.TransportMaxBufferSize = long.MaxValue; }); } public virtual void OnModelCreating(ModelBuilder modelBuilder) { } public virtual void Seed(DbContext dbContext, IServiceProvider serviceProvider, IConfiguration configuration) { } public virtual Task ValidatePrincipal(CookieValidatePrincipalContext arg) { return Task.CompletedTask; } } }