optimize startup
This commit is contained in:
@ -2,14 +2,105 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Oqtane.Components;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.UI;
|
||||
using OqtaneSSR.Extensions;
|
||||
|
||||
namespace Oqtane.Extensions
|
||||
{
|
||||
public static class ApplicationBuilderExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseOqtane(this IApplicationBuilder app, IConfigurationRoot configuration, IWebHostEnvironment environment, ICorsService corsService, ICorsPolicyProvider corsPolicyProvider, ISyncManager sync)
|
||||
{
|
||||
ServiceActivator.Configure(app.ApplicationServices);
|
||||
|
||||
if (environment.IsDevelopment())
|
||||
{
|
||||
app.UseWebAssemblyDebugging();
|
||||
app.UseForwardedHeaders();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseForwardedHeaders();
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
// allow oqtane localization middleware
|
||||
app.UseOqtaneLocalization();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
OnPrepareResponse = (ctx) =>
|
||||
{
|
||||
// static asset caching
|
||||
var cachecontrol = configuration.GetSection("CacheControl");
|
||||
if (!string.IsNullOrEmpty(cachecontrol.Value))
|
||||
{
|
||||
ctx.Context.Response.Headers.Append(HeaderNames.CacheControl, cachecontrol.Value);
|
||||
}
|
||||
// CORS headers for .NET MAUI clients
|
||||
var policy = corsPolicyProvider.GetPolicyAsync(ctx.Context, Constants.MauiCorsPolicy)
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
corsService.ApplyResult(corsService.EvaluatePolicy(ctx.Context, policy), ctx.Context.Response);
|
||||
}
|
||||
});
|
||||
app.UseExceptionMiddleWare();
|
||||
app.UseTenantResolution();
|
||||
app.UseJwtAuthorization();
|
||||
app.UseRouting();
|
||||
app.UseCors();
|
||||
app.UseOutputCache();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.UseAntiforgery();
|
||||
|
||||
// execute any IServerStartup logic
|
||||
app.ConfigureOqtaneAssemblies(environment);
|
||||
|
||||
if (configuration.GetSection("UseSwagger").Value != "false")
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/" + Constants.Version + "/swagger.json", Constants.PackageId + " " + Constants.Version); });
|
||||
}
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
endpoints.MapRazorPages();
|
||||
});
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode()
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(SiteRouter).Assembly);
|
||||
});
|
||||
|
||||
// simulate the fallback routing approach of traditional Blazor - allowing the custom SiteRouter to handle all routing concerns
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapFallback();
|
||||
});
|
||||
|
||||
// create a global sync event to identify server application startup
|
||||
sync.AddSyncEvent(-1, -1, EntityNames.Host, -1, SyncEventActions.Reload);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
public static IApplicationBuilder ConfigureOqtaneAssemblies(this IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
var startUps = AppDomain.CurrentDomain
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.IO;
|
||||
@ -11,12 +12,17 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Oqtane.Extensions;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Interfaces;
|
||||
using Oqtane.Managers;
|
||||
@ -31,10 +37,126 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class OqtaneServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddOqtane(this IServiceCollection services, string[] installedCultures)
|
||||
public static IServiceCollection AddOqtane(this IServiceCollection services, IConfigurationRoot configuration, IWebHostEnvironment environment)
|
||||
{
|
||||
// process forwarded headers on load balancers and proxy servers
|
||||
services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
|
||||
// register localization services
|
||||
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||
|
||||
services.AddOptions<List<Oqtane.Models.Database>>().Bind(configuration.GetSection(SettingKeys.AvailableDatabasesSection));
|
||||
|
||||
// register scoped core services
|
||||
services.AddScoped<IAuthorizationHandler, PermissionHandler>()
|
||||
.AddOqtaneServerScopedServices();
|
||||
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
|
||||
// setup HttpClient for server side in a client side compatible fashion ( with auth cookie )
|
||||
services.AddHttpClients();
|
||||
|
||||
// register singleton scoped core services
|
||||
services.AddSingleton(configuration)
|
||||
.AddOqtaneSingletonServices();
|
||||
|
||||
// install any modules or themes ( this needs to occur BEFORE the assemblies are loaded into the app domain )
|
||||
InstallationManager.InstallPackages(environment.WebRootPath, environment.ContentRootPath);
|
||||
|
||||
// register transient scoped core services
|
||||
services.AddOqtaneTransientServices();
|
||||
|
||||
// load the external assemblies into the app domain, install services
|
||||
services.AddOqtaneAssemblies();
|
||||
services.AddOqtaneDbContext();
|
||||
|
||||
services.AddAntiforgery(options =>
|
||||
{
|
||||
options.HeaderName = Constants.AntiForgeryTokenHeaderName;
|
||||
options.Cookie.Name = Constants.AntiForgeryTokenCookieName;
|
||||
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
|
||||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
||||
options.Cookie.HttpOnly = true;
|
||||
});
|
||||
|
||||
services.AddIdentityCore<IdentityUser>(options => { })
|
||||
.AddEntityFrameworkStores<TenantDBContext>()
|
||||
.AddSignInManager()
|
||||
.AddDefaultTokenProviders()
|
||||
.AddClaimsPrincipalFactory<ClaimsPrincipalFactory<IdentityUser>>(); // role claims
|
||||
|
||||
services.ConfigureOqtaneIdentityOptions(configuration);
|
||||
|
||||
services.AddCascadingAuthenticationState();
|
||||
services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
|
||||
services.AddAuthorization();
|
||||
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultScheme = Constants.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie(Constants.AuthenticationScheme)
|
||||
.AddOpenIdConnect(AuthenticationProviderTypes.OpenIDConnect, options => { })
|
||||
.AddOAuth(AuthenticationProviderTypes.OAuth2, options => { });
|
||||
|
||||
services.ConfigureOqtaneCookieOptions();
|
||||
services.ConfigureOqtaneAuthenticationOptions(configuration);
|
||||
|
||||
services.AddOqtaneSiteOptions()
|
||||
.WithSiteIdentity()
|
||||
.WithSiteAuthentication();
|
||||
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(Constants.MauiCorsPolicy,
|
||||
policy =>
|
||||
{
|
||||
// allow .NET MAUI client cross origin calls
|
||||
policy.WithOrigins("https://0.0.0.1", "http://0.0.0.1", "app://0.0.0.1")
|
||||
.AllowAnyHeader().AllowAnyMethod().AllowCredentials();
|
||||
});
|
||||
});
|
||||
|
||||
services.AddOutputCache();
|
||||
|
||||
services.AddMvc(options =>
|
||||
{
|
||||
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
|
||||
})
|
||||
.AddOqtaneApplicationParts() // register any Controllers from custom modules
|
||||
.ConfigureOqtaneMvc(); // any additional configuration from IStartup classes
|
||||
|
||||
services.AddRazorPages();
|
||||
|
||||
services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents(options =>
|
||||
{
|
||||
if (environment.IsDevelopment())
|
||||
{
|
||||
options.DetailedErrors = true;
|
||||
}
|
||||
}).AddHubOptions(options =>
|
||||
{
|
||||
options.MaximumReceiveMessageSize = null; // no limit (for large amounts of data ie. textarea components)
|
||||
})
|
||||
.AddInteractiveWebAssemblyComponents();
|
||||
|
||||
services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.CustomSchemaIds(type => type.ToString()); // Handle SchemaId already used for different type
|
||||
});
|
||||
services.TryAddSwagger(configuration);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddOqtaneAssemblies(this IServiceCollection services)
|
||||
{
|
||||
LoadAssemblies();
|
||||
LoadSatelliteAssemblies(installedCultures);
|
||||
LoadSatelliteAssemblies();
|
||||
services.AddOqtaneServices();
|
||||
|
||||
return services;
|
||||
@ -53,7 +175,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
return new OqtaneSiteOptionsBuilder(services);
|
||||
}
|
||||
|
||||
internal static IServiceCollection AddOqtaneSingletonServices(this IServiceCollection services)
|
||||
public static IServiceCollection AddOqtaneSingletonServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IInstallationManager, InstallationManager>();
|
||||
services.AddSingleton<ISyncManager, SyncManager>();
|
||||
@ -66,7 +188,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
return services;
|
||||
}
|
||||
|
||||
internal static IServiceCollection AddOqtaneServerScopedServices(this IServiceCollection services)
|
||||
public static IServiceCollection AddOqtaneServerScopedServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<Oqtane.Shared.SiteState>();
|
||||
services.AddScoped<IInstallationService, InstallationService>();
|
||||
@ -112,7 +234,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
return services;
|
||||
}
|
||||
|
||||
internal static IServiceCollection AddOqtaneTransientServices(this IServiceCollection services)
|
||||
public static IServiceCollection AddOqtaneTransientServices(this IServiceCollection services)
|
||||
{
|
||||
// services
|
||||
services.AddTransient<ISiteService, ServerSiteService>();
|
||||
@ -242,7 +364,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
return services;
|
||||
}
|
||||
|
||||
internal static IServiceCollection AddHttpClients(this IServiceCollection services)
|
||||
public static IServiceCollection AddHttpClients(this IServiceCollection services)
|
||||
{
|
||||
if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
|
||||
{
|
||||
@ -285,9 +407,9 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
return services;
|
||||
}
|
||||
|
||||
internal static IServiceCollection TryAddSwagger(this IServiceCollection services, bool useSwagger)
|
||||
public static IServiceCollection TryAddSwagger(this IServiceCollection services, IConfigurationRoot configuration)
|
||||
{
|
||||
if (useSwagger)
|
||||
if (configuration.GetSection("UseSwagger").Value != "false")
|
||||
{
|
||||
services.AddSwaggerGen(c =>
|
||||
{
|
||||
@ -386,10 +508,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadSatelliteAssemblies(string[] installedCultures)
|
||||
private static void LoadSatelliteAssemblies()
|
||||
{
|
||||
AssemblyLoadContext.Default.Resolving += ResolveDependencies;
|
||||
|
||||
var installedCultures = LocalizationManager.GetSatelliteAssemblyCultures();
|
||||
foreach (var file in Directory.EnumerateFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"*{Constants.SatelliteAssemblyExtension}", SearchOption.AllDirectories))
|
||||
{
|
||||
var code = Path.GetFileName(Path.GetDirectoryName(file));
|
||||
|
@ -45,6 +45,12 @@ namespace Oqtane.Infrastructure
|
||||
}
|
||||
|
||||
public string[] GetInstalledCultures()
|
||||
{
|
||||
return GetSatelliteAssemblyCultures();
|
||||
}
|
||||
|
||||
// method is static as it is called during startup
|
||||
public static string[] GetSatelliteAssemblyCultures()
|
||||
{
|
||||
var cultures = new List<string>();
|
||||
foreach (var file in Directory.EnumerateFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"*{Constants.SatelliteAssemblyExtension}", SearchOption.AllDirectories))
|
||||
|
@ -1,260 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Oqtane.Extensions;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Security;
|
||||
using Oqtane.Shared;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Oqtane.Components;
|
||||
using Oqtane.UI;
|
||||
using OqtaneSSR.Extensions;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Oqtane.Providers;
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Oqtane
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
private readonly bool _useSwagger;
|
||||
private readonly IWebHostEnvironment _env;
|
||||
private readonly string[] _installedCultures;
|
||||
private string _configureServicesErrors;
|
||||
private readonly IConfigurationRoot _configuration;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
|
||||
public IConfigurationRoot Configuration { get; }
|
||||
|
||||
public Startup(IWebHostEnvironment env, ILocalizationManager localizationManager)
|
||||
public Startup(IWebHostEnvironment environment)
|
||||
{
|
||||
AppDomain.CurrentDomain.SetData(Constants.DataDirectory, Path.Combine(environment.ContentRootPath, "Data"));
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.SetBasePath(environment.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", false, true)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true)
|
||||
.AddJsonFile($"appsettings.{environment.EnvironmentName}.json", true, true)
|
||||
.AddEnvironmentVariables();
|
||||
|
||||
Configuration = builder.Build();
|
||||
|
||||
_installedCultures = localizationManager.GetInstalledCultures();
|
||||
|
||||
//add possibility to switch off swagger on production.
|
||||
_useSwagger = Configuration.GetSection("UseSwagger").Value != "false";
|
||||
|
||||
AppDomain.CurrentDomain.SetData(Constants.DataDirectory, Path.Combine(env.ContentRootPath, "Data"));
|
||||
|
||||
_env = env;
|
||||
_configuration = builder.Build();
|
||||
_environment = environment;
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// process forwarded headers on load balancers and proxy servers
|
||||
services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
|
||||
// register localization services
|
||||
services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||
|
||||
services.AddOptions<List<Models.Database>>().Bind(Configuration.GetSection(SettingKeys.AvailableDatabasesSection));
|
||||
|
||||
// register scoped core services
|
||||
services.AddScoped<IAuthorizationHandler, PermissionHandler>()
|
||||
.AddOqtaneServerScopedServices();
|
||||
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
|
||||
// setup HttpClient for server side in a client side compatible fashion ( with auth cookie )
|
||||
services.AddHttpClients();
|
||||
|
||||
// register singleton scoped core services
|
||||
services.AddSingleton(Configuration)
|
||||
.AddOqtaneSingletonServices();
|
||||
|
||||
// install any modules or themes ( this needs to occur BEFORE the assemblies are loaded into the app domain )
|
||||
_configureServicesErrors += InstallationManager.InstallPackages(_env.WebRootPath, _env.ContentRootPath);
|
||||
|
||||
// register transient scoped core services
|
||||
services.AddOqtaneTransientServices();
|
||||
|
||||
// load the external assemblies into the app domain, install services
|
||||
services.AddOqtane(_installedCultures);
|
||||
services.AddOqtaneDbContext();
|
||||
|
||||
services.AddAntiforgery(options =>
|
||||
{
|
||||
options.HeaderName = Constants.AntiForgeryTokenHeaderName;
|
||||
options.Cookie.Name = Constants.AntiForgeryTokenCookieName;
|
||||
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
|
||||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
||||
options.Cookie.HttpOnly = true;
|
||||
});
|
||||
|
||||
services.AddIdentityCore<IdentityUser>(options => { })
|
||||
.AddEntityFrameworkStores<TenantDBContext>()
|
||||
.AddSignInManager()
|
||||
.AddDefaultTokenProviders()
|
||||
.AddClaimsPrincipalFactory<ClaimsPrincipalFactory<IdentityUser>>(); // role claims
|
||||
|
||||
services.ConfigureOqtaneIdentityOptions(Configuration);
|
||||
|
||||
services.AddCascadingAuthenticationState();
|
||||
services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
|
||||
services.AddAuthorization();
|
||||
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultScheme = Constants.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie(Constants.AuthenticationScheme)
|
||||
.AddOpenIdConnect(AuthenticationProviderTypes.OpenIDConnect, options => { })
|
||||
.AddOAuth(AuthenticationProviderTypes.OAuth2, options => { });
|
||||
|
||||
services.ConfigureOqtaneCookieOptions();
|
||||
services.ConfigureOqtaneAuthenticationOptions(Configuration);
|
||||
|
||||
services.AddOqtaneSiteOptions()
|
||||
.WithSiteIdentity()
|
||||
.WithSiteAuthentication();
|
||||
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(Constants.MauiCorsPolicy,
|
||||
policy =>
|
||||
{
|
||||
// allow .NET MAUI client cross origin calls
|
||||
policy.WithOrigins("https://0.0.0.1", "http://0.0.0.1", "app://0.0.0.1")
|
||||
.AllowAnyHeader().AllowAnyMethod().AllowCredentials();
|
||||
});
|
||||
});
|
||||
|
||||
services.AddOutputCache();
|
||||
|
||||
services.AddMvc(options =>
|
||||
{
|
||||
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
|
||||
})
|
||||
.AddOqtaneApplicationParts() // register any Controllers from custom modules
|
||||
.ConfigureOqtaneMvc(); // any additional configuration from IStartup classes
|
||||
|
||||
services.AddRazorPages();
|
||||
|
||||
services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents(options =>
|
||||
{
|
||||
if (_env.IsDevelopment())
|
||||
{
|
||||
options.DetailedErrors = true;
|
||||
}
|
||||
}).AddHubOptions(options =>
|
||||
{
|
||||
options.MaximumReceiveMessageSize = null; // no limit (for large amounts of data ie. textarea components)
|
||||
})
|
||||
.AddInteractiveWebAssemblyComponents();
|
||||
|
||||
services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.CustomSchemaIds(type => type.ToString()); // Handle SchemaId already used for different type
|
||||
});
|
||||
services.TryAddSwagger(_useSwagger);
|
||||
services.AddOqtane(_configuration, _environment);
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISyncManager sync, ICorsService corsService, ICorsPolicyProvider corsPolicyProvider, ILogger<Startup> logger)
|
||||
public void Configure(IApplicationBuilder app, IConfigurationRoot configuration, IWebHostEnvironment environment, ICorsService corsService, ICorsPolicyProvider corsPolicyProvider, ISyncManager sync)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_configureServicesErrors))
|
||||
{
|
||||
logger.LogError(_configureServicesErrors);
|
||||
}
|
||||
|
||||
ServiceActivator.Configure(app.ApplicationServices);
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseWebAssemblyDebugging();
|
||||
app.UseForwardedHeaders();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseForwardedHeaders();
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
// allow oqtane localization middleware
|
||||
app.UseOqtaneLocalization();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
OnPrepareResponse = (ctx) =>
|
||||
{
|
||||
// static asset caching
|
||||
var cachecontrol = Configuration.GetSection("CacheControl");
|
||||
if (!string.IsNullOrEmpty(cachecontrol.Value))
|
||||
{
|
||||
ctx.Context.Response.Headers.Append(HeaderNames.CacheControl, cachecontrol.Value);
|
||||
}
|
||||
// CORS headers for .NET MAUI clients
|
||||
var policy = corsPolicyProvider.GetPolicyAsync(ctx.Context, Constants.MauiCorsPolicy)
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
corsService.ApplyResult(corsService.EvaluatePolicy(ctx.Context, policy), ctx.Context.Response);
|
||||
}
|
||||
});
|
||||
app.UseExceptionMiddleWare();
|
||||
app.UseTenantResolution();
|
||||
app.UseJwtAuthorization();
|
||||
app.UseRouting();
|
||||
app.UseCors();
|
||||
app.UseOutputCache();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.UseAntiforgery();
|
||||
|
||||
// execute any IServerStartup logic
|
||||
app.ConfigureOqtaneAssemblies(env);
|
||||
|
||||
if (_useSwagger)
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/" + Constants.Version + "/swagger.json", Constants.PackageId + " " + Constants.Version); });
|
||||
}
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
endpoints.MapRazorPages();
|
||||
});
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode()
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(SiteRouter).Assembly);
|
||||
});
|
||||
|
||||
// simulate the fallback routing approach of traditional Blazor - allowing the custom SiteRouter to handle all routing concerns
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapFallback();
|
||||
});
|
||||
|
||||
// create a global sync event to identify server application startup
|
||||
sync.AddSyncEvent(-1, -1, EntityNames.Host, -1, SyncEventActions.Reload);
|
||||
app.UseOqtane(configuration, environment, corsService, corsPolicyProvider, sync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user