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.
iot/projects/Infrastructure/Web/BaseStartup.cs

295 lines
12 KiB

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.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<bool>("UseMiniProfiler", false);
}
public virtual void ConfigureServices(IServiceCollection services)
{
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<FormOptions>(o =>
{
o.ValueCountLimit = int.MaxValue;
o.MultipartBodyLengthLimit = long.MaxValue;
});
this.ConfigureOptions(services);
EfDbContext.OnModelCreatingAction = this.OnModelCreating;
services.AddScoped<DbContext, EfDbContext>();
this._useSqlite = this._cfg.GetSection("AppSettings").GetValue<string>("database") == "sqlite";
if (_useSqlite)
{
_connectionString = this._cfg.GetConnectionString("database.sqlite.connection");
services.AddDbContext<EfDbContext>(options => options.UseSqlite(_connectionString));
}
else
{
_connectionString = this._cfg.GetConnectionString("database.mysql.connection");
services.AddDbContext<EfDbContext>(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<RequestLocalizationOptions>(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<ITicketStore, DistributedCacheTicketStore>();
services.AddTransient(typeof(IRepository<>), typeof(EfRepository<>));
services.AddTransient<IEncryptionService, EncryptionService>();
services.AddTransient<IJwtHelper, JwtHelper>();
services.AddTransient<IExcelReader, ExcelReader>();
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<IEventPublisher, EventPublisher>();
}
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<bool>("UseCookieSessionStore");
if (!useCookieSessionStore)
{
opts.SessionStore = services.BuildServiceProvider().GetService<ITicketStore>();
}
opts.Events = new CookieAuthenticationEvents
{
//OnRedirectToLogin = RedirectToLogin(),
OnValidatePrincipal = ValidatePrincipal
};
});
}
public virtual void AddSwagger(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc(this._cfg.GetValue<string>("openapi.name", "v1"), new OpenApiInfo
{
Title = this._cfg.GetValue<string>("openapi.title", "web api"),
Version = this._cfg.GetValue<string>("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.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseStatusCodePagesWithReExecute("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors(_origins);
var localizationOption = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
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<DbContext>();
var configuration = services.GetService<IConfiguration>();
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<BasePageHub>(endpoints);
}
protected virtual void UseSignalR<T>(IEndpointRouteBuilder endpoints) where T : Hub
{
endpoints.MapHub<T>("/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;
}
}
}