diff --git a/Directory.Packages.props b/Directory.Packages.props
index ff913ef39..0c63154f9 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -64,5 +64,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GrandNode.sln b/GrandNode.sln
index 1c8ca9b46..964782589 100644
--- a/GrandNode.sln
+++ b/GrandNode.sln
@@ -137,6 +137,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grand.Module.Api", "src\Mod
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grand.Module.ScheduledTasks", "src\Modules\Grand.Module.ScheduledTasks\Grand.Module.ScheduledTasks.csproj", "{136F1E35-8B20-465C-8D42-30A5A0D0DA1F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.AppHost", "src\Aspire\Aspire.AppHost\Aspire.AppHost.csproj", "{FFA85947-690E-496B-B21E-DB1800F0DCA9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.ServiceDefaults", "src\Aspire\Aspire.ServiceDefaults\Aspire.ServiceDefaults.csproj", "{591950E4-6377-4ECA-A386-8BD3FFE302F1}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -363,6 +367,14 @@ Global
{136F1E35-8B20-465C-8D42-30A5A0D0DA1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{136F1E35-8B20-465C-8D42-30A5A0D0DA1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{136F1E35-8B20-465C-8D42-30A5A0D0DA1F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FFA85947-690E-496B-B21E-DB1800F0DCA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FFA85947-690E-496B-B21E-DB1800F0DCA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FFA85947-690E-496B-B21E-DB1800F0DCA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FFA85947-690E-496B-B21E-DB1800F0DCA9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {591950E4-6377-4ECA-A386-8BD3FFE302F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {591950E4-6377-4ECA-A386-8BD3FFE302F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {591950E4-6377-4ECA-A386-8BD3FFE302F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {591950E4-6377-4ECA-A386-8BD3FFE302F1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Aspire/Aspire.AppHost/Aspire.AppHost.csproj b/src/Aspire/Aspire.AppHost/Aspire.AppHost.csproj
new file mode 100644
index 000000000..b3a26a60f
--- /dev/null
+++ b/src/Aspire/Aspire.AppHost/Aspire.AppHost.csproj
@@ -0,0 +1,23 @@
+
+
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ true
+ bdc1e5b4-4475-44fc-851c-dd576ac2c123
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Aspire/Aspire.AppHost/Program.cs b/src/Aspire/Aspire.AppHost/Program.cs
new file mode 100644
index 000000000..5a1daa4a6
--- /dev/null
+++ b/src/Aspire/Aspire.AppHost/Program.cs
@@ -0,0 +1,17 @@
+
+var builder = DistributedApplication.CreateBuilder(args);
+
+
+var mongo = builder.AddMongoDB("mongo")
+ .WithLifetime(ContainerLifetime.Persistent);
+
+var mongodb = mongo.AddDatabase("Mongodb");
+
+builder
+ .AddProject("grand-web")
+ .WithHttpEndpoint(80)
+ .WithEnvironment("", "")
+ .WithReference(mongodb)
+ .WaitFor(mongodb);
+
+builder.Build().Run();
diff --git a/src/Aspire/Aspire.AppHost/Properties/launchSettings.json b/src/Aspire/Aspire.AppHost/Properties/launchSettings.json
new file mode 100644
index 000000000..43ec3ebbe
--- /dev/null
+++ b/src/Aspire/Aspire.AppHost/Properties/launchSettings.json
@@ -0,0 +1,32 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:17196;http://localhost:15129",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "DOTNET_ENVIRONMENT": "Development",
+ "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21225",
+ "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22257",
+ "ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"
+ }
+ },
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:15129",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "DOTNET_ENVIRONMENT": "Development",
+ "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19032",
+ "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20163",
+ "ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"
+
+ }
+ }
+ }
+}
diff --git a/src/Aspire/Aspire.AppHost/appsettings.Development.json b/src/Aspire/Aspire.AppHost/appsettings.Development.json
new file mode 100644
index 000000000..0c208ae91
--- /dev/null
+++ b/src/Aspire/Aspire.AppHost/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/src/Aspire/Aspire.AppHost/appsettings.json b/src/Aspire/Aspire.AppHost/appsettings.json
new file mode 100644
index 000000000..31c092aa4
--- /dev/null
+++ b/src/Aspire/Aspire.AppHost/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "Aspire.Hosting.Dcp": "Warning"
+ }
+ }
+}
diff --git a/src/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj b/src/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj
new file mode 100644
index 000000000..f6cb4c09d
--- /dev/null
+++ b/src/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net9.0
+ enable
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Aspire/Aspire.ServiceDefaults/Extensions.cs b/src/Aspire/Aspire.ServiceDefaults/Extensions.cs
new file mode 100644
index 000000000..d5cfd5122
--- /dev/null
+++ b/src/Aspire/Aspire.ServiceDefaults/Extensions.cs
@@ -0,0 +1,89 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.HealthChecks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.ServiceDiscovery;
+using OpenTelemetry;
+using OpenTelemetry.Metrics;
+using OpenTelemetry.Trace;
+
+namespace Microsoft.Extensions.Hosting;
+
+// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
+// This project should be referenced by each service project in your solution.
+// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
+public static class Extensions
+{
+ public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder
+ {
+ builder.ConfigureOpenTelemetry();
+
+ builder.Services.AddServiceDiscovery();
+
+ builder.Services.ConfigureHttpClientDefaults(http =>
+ {
+ // Turn on resilience by default
+ http.AddStandardResilienceHandler();
+
+ // Turn on service discovery by default
+ http.AddServiceDiscovery();
+ });
+
+ // Uncomment the following to restrict the allowed schemes for service discovery.
+ // builder.Services.Configure(options =>
+ // {
+ // options.AllowedSchemes = ["https"];
+ // });
+
+ return builder;
+ }
+
+ public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) where TBuilder : IHostApplicationBuilder
+ {
+ builder.Logging.AddOpenTelemetry(logging =>
+ {
+ logging.IncludeFormattedMessage = true;
+ logging.IncludeScopes = true;
+ });
+
+ builder.Services.AddOpenTelemetry()
+ .WithMetrics(metrics =>
+ {
+ metrics.AddAspNetCoreInstrumentation()
+ .AddHttpClientInstrumentation()
+ .AddRuntimeInstrumentation();
+ })
+ .WithTracing(tracing =>
+ {
+ tracing.AddSource(builder.Environment.ApplicationName)
+ .AddAspNetCoreInstrumentation()
+ // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
+ //.AddGrpcClientInstrumentation()
+ .AddHttpClientInstrumentation();
+ });
+
+ builder.AddOpenTelemetryExporters();
+
+ return builder;
+ }
+
+ private static TBuilder AddOpenTelemetryExporters(this TBuilder builder) where TBuilder : IHostApplicationBuilder
+ {
+ var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
+
+ if (useOtlpExporter)
+ {
+ builder.Services.AddOpenTelemetry().UseOtlpExporter();
+ }
+
+ // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
+ //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
+ //{
+ // builder.Services.AddOpenTelemetry()
+ // .UseAzureMonitor();
+ //}
+
+ return builder;
+ }
+}
diff --git a/src/Core/Grand.Infrastructure/Configuration/DatabaseConfig.cs b/src/Core/Grand.Infrastructure/Configuration/DatabaseConfig.cs
index c2396e529..6bb260554 100644
--- a/src/Core/Grand.Infrastructure/Configuration/DatabaseConfig.cs
+++ b/src/Core/Grand.Infrastructure/Configuration/DatabaseConfig.cs
@@ -16,11 +16,4 @@ public class DatabaseConfig
/// Gets or sets a value indicating whether use LiteDB database (only for installation process)
///
public string LiteDbConnectionString { get; set; }
-
- ///
- /// Gets or sets a value indicating whether use connection string for database (only for installed databases)
- ///
- public string ConnectionString { get; set; }
-
- public int DbProvider { get; set; }
}
\ No newline at end of file
diff --git a/src/Core/Grand.Infrastructure/Configuration/PerformanceConfig.cs b/src/Core/Grand.Infrastructure/Configuration/PerformanceConfig.cs
index 6597c5aac..b95260ea8 100644
--- a/src/Core/Grand.Infrastructure/Configuration/PerformanceConfig.cs
+++ b/src/Core/Grand.Infrastructure/Configuration/PerformanceConfig.cs
@@ -10,11 +10,6 @@ public class PerformanceConfig
///
public bool UseResponseCompression { get; set; }
- ///
- /// Gets or sets a value indicating whether ignore DbVersionCheckMiddleware
- ///
- public bool IgnoreDbVersionCheckMiddleware { get; set; }
-
///
/// Gets or sets a value indicating whether ignore IgnoreUsePoweredByMiddleware
///
diff --git a/src/Core/Grand.Infrastructure/StartupBase.cs b/src/Core/Grand.Infrastructure/StartupBase.cs
index 70e0d350a..8d05f49f7 100644
--- a/src/Core/Grand.Infrastructure/StartupBase.cs
+++ b/src/Core/Grand.Infrastructure/StartupBase.cs
@@ -36,11 +36,18 @@ public static class StartupBase
///
private static void InitDatabase(IServiceCollection services, IConfiguration configuration)
{
- var dbConfig = services.StartupConfig(configuration.GetSection("Database"));
- if (!string.IsNullOrEmpty(dbConfig.ConnectionString))
+ var connectionString = configuration["ConnectionStrings:Mongodb"];
+ var providerString = configuration["ConnectionStrings:Provider"];
+ var providerInt = 0;
+ if (!string.IsNullOrEmpty(providerString))
+ {
+ _ = int.TryParse(providerString, out providerInt);
+ }
+
+ if (!string.IsNullOrEmpty(connectionString))
DataSettingsManager.Instance.LoadDataSettings(new DataSettings {
- ConnectionString = dbConfig.ConnectionString,
- DbProvider = (DbProvider)dbConfig.DbProvider
+ ConnectionString = connectionString,
+ DbProvider = (DbProvider)providerInt,
});
}
diff --git a/src/Modules/Grand.Module.Installer/Controllers/InstallController.cs b/src/Modules/Grand.Module.Installer/Controllers/InstallController.cs
index 5ab7da3b6..32de67750 100644
--- a/src/Modules/Grand.Module.Installer/Controllers/InstallController.cs
+++ b/src/Modules/Grand.Module.Installer/Controllers/InstallController.cs
@@ -2,13 +2,13 @@
using Grand.Infrastructure.Caching;
using Grand.Infrastructure.Configuration;
using Grand.Infrastructure.Plugins;
-using Grand.Module.Installer.Filters;
using Grand.Module.Installer.Interfaces;
using Grand.Module.Installer.Models;
using Grand.SharedKernel.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@@ -16,7 +16,6 @@
namespace Grand.Module.Installer.Controllers;
-[DatabaseConfigured]
public class InstallController : Controller
{
@@ -25,6 +24,7 @@ public class InstallController : Controller
private readonly ICacheBase _cacheBase;
private readonly IHostApplicationLifetime _applicationLifetime;
private readonly DatabaseConfig _dbConfig;
+ private readonly IConfiguration _configuration;
private readonly ILogger _logger;
///
@@ -40,11 +40,13 @@ public InstallController(
ICacheBase cacheBase,
IHostApplicationLifetime applicationLifetime,
DatabaseConfig dbConfig,
+ IConfiguration configuration,
ILogger logger)
{
_cacheBase = cacheBase;
_applicationLifetime = applicationLifetime;
_dbConfig = dbConfig;
+ _configuration = configuration;
_logger = logger;
}
@@ -70,9 +72,10 @@ private InstallModel PrepareModel(InstallModel? model)
model ??= new InstallModel {
AdminEmail = "admin@yourstore.com",
InstallSampleData = false,
- DatabaseConnectionString = "",
AdminPassword = "",
- ConfirmPassword = ""
+ ConfirmPassword = "",
+ DatabaseConnectionString = _configuration["ConnectionStrings:Mongodb"],
+ ConnectionInfo = !string.IsNullOrEmpty(_configuration["ConnectionStrings:Mongodb"]),
};
model.AvailableProviders = Enum.GetValues(typeof(DbProvider)).Cast().Select(v => new SelectListItem {
diff --git a/src/Modules/Grand.Module.Installer/Filters/DatabaseConfiguredAttribute.cs b/src/Modules/Grand.Module.Installer/Filters/DatabaseConfiguredAttribute.cs
deleted file mode 100644
index d4319211c..000000000
--- a/src/Modules/Grand.Module.Installer/Filters/DatabaseConfiguredAttribute.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Grand.Data;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.Filters;
-
-namespace Grand.Module.Installer.Filters;
-
-public class DatabaseConfiguredAttribute : Attribute, IAsyncActionFilter
-{
- public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
- {
- if (!DataSettingsManager.DatabaseIsInstalled())
- {
- await next();
- }
- else
- {
- context.Result = new NotFoundResult();
- }
- }
-}
diff --git a/src/Modules/Grand.Module.Installer/Startup/EndpointProvider.cs b/src/Modules/Grand.Module.Installer/Startup/EndpointProvider.cs
new file mode 100644
index 000000000..9cbe4d7f7
--- /dev/null
+++ b/src/Modules/Grand.Module.Installer/Startup/EndpointProvider.cs
@@ -0,0 +1,15 @@
+using Grand.Infrastructure.Endpoints;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+
+namespace Grand.Module.Installer.Startup;
+
+public class EndpointProvider : IEndpointProvider
+{
+ public int Priority => int.MinValue;
+
+ public void RegisterEndpoint(IEndpointRouteBuilder endpointRouteBuilder)
+ {
+ endpointRouteBuilder.MapControllerRoute("Install", "install", new { controller = "Install", action = "Index" });
+ }
+}
diff --git a/src/Modules/Grand.Module.Installer/Startup/StartupApplication.cs b/src/Modules/Grand.Module.Installer/Startup/StartupApplication.cs
index 132744ee9..94a44092a 100644
--- a/src/Modules/Grand.Module.Installer/Startup/StartupApplication.cs
+++ b/src/Modules/Grand.Module.Installer/Startup/StartupApplication.cs
@@ -1,5 +1,4 @@
-using Grand.Data;
-using Grand.Infrastructure;
+using Grand.Infrastructure;
using Grand.Module.Installer.Interfaces;
using Grand.Module.Installer.Services;
using Microsoft.AspNetCore.Builder;
@@ -25,13 +24,8 @@ public void Configure(WebApplication application, IWebHostEnvironment webHostEnv
private void RegisterInstallService(IServiceCollection serviceCollection)
{
- var databaseInstalled = DataSettingsManager.DatabaseIsInstalled();
- if (!databaseInstalled)
- {
- //installation service
- serviceCollection.AddScoped();
- serviceCollection.AddScoped();
- serviceCollection.AddTransient();
- }
+ serviceCollection.AddScoped();
+ serviceCollection.AddScoped();
+ serviceCollection.AddTransient();
}
}
\ No newline at end of file
diff --git a/src/Modules/Grand.Module.Migration/Migrations/MigrationProcess.cs b/src/Modules/Grand.Module.Migration/Migrations/MigrationProcess.cs
index 145c023e4..dfe9c79bd 100644
--- a/src/Modules/Grand.Module.Migration/Migrations/MigrationProcess.cs
+++ b/src/Modules/Grand.Module.Migration/Migrations/MigrationProcess.cs
@@ -57,6 +57,8 @@ public virtual void RunMigrationProcess()
{
var migrationsDb = GetMigrationDb();
var version = _repositoryVersion.Table.FirstOrDefault();
+ if(version == null)
+ return;
var majorVersion = string.IsNullOrEmpty(version?.InstalledVersion) ? int.Parse(version?.DataBaseVersion.Split('.')[0]!) : int.Parse(version?.InstalledVersion.Split('.')[0]!);
var minorVersion = string.IsNullOrEmpty(version?.InstalledVersion) ? int.Parse(version?.DataBaseVersion.Split('.')[1]!) : int.Parse(version?.InstalledVersion.Split('.')[1]!);
var migrationManager = new MigrationManager();
diff --git a/src/Web/Grand.Web.Common/Middleware/DbVersionCheckMiddleware.cs b/src/Web/Grand.Web.Common/Middleware/DbVersionCheckMiddleware.cs
deleted file mode 100644
index 1913628b6..000000000
--- a/src/Web/Grand.Web.Common/Middleware/DbVersionCheckMiddleware.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using Grand.Data;
-using Grand.Domain.Common;
-using Grand.Infrastructure;
-using Grand.Infrastructure.Caching;
-using Grand.Infrastructure.Caching.Constants;
-using Microsoft.AspNetCore.Http;
-
-namespace Grand.Web.Common.Middleware;
-
-public class DbVersionCheckMiddleware
-{
- private readonly RequestDelegate _next;
-
- public DbVersionCheckMiddleware(RequestDelegate next)
- {
- _next = next;
- }
-
- public async Task Invoke(
- HttpContext context,
- ICacheBase cacheBase,
- IRepository repository)
- {
- if (context?.Request == null) return;
-
- var version = cacheBase.Get(CacheKey.GRAND_NODE_VERSION, () => repository.Table.FirstOrDefault());
- if (version == null)
- {
- await context.Response.WriteAsync("The database does not exist.");
- return;
- }
-
- if (!version.DataBaseVersion.Equals(GrandVersion.SupportedDBVersion))
- await context.Response.WriteAsync("The database version is not supported in this software version. " +
- $"Supported version: {GrandVersion.SupportedDBVersion} , your version: {version.DataBaseVersion}");
- else
- await _next(context);
- }
-}
\ No newline at end of file
diff --git a/src/Web/Grand.Web.Common/Middleware/InstallUrlMiddleware.cs b/src/Web/Grand.Web.Common/Middleware/InstallUrlMiddleware.cs
index 16fc3d7db..13552c30f 100644
--- a/src/Web/Grand.Web.Common/Middleware/InstallUrlMiddleware.cs
+++ b/src/Web/Grand.Web.Common/Middleware/InstallUrlMiddleware.cs
@@ -1,4 +1,10 @@
-using Grand.Data;
+#nullable enable
+
+using Grand.Data;
+using Grand.Domain.Common;
+using Grand.Infrastructure;
+using Grand.Infrastructure.Caching;
+using Grand.Infrastructure.Caching.Constants;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.DependencyInjection;
@@ -11,52 +17,86 @@ public class InstallUrlMiddleware
#region Fields
private readonly RequestDelegate _next;
+ private readonly ICacheBase _cacheBase;
+ private const string InstallUrl = "/install";
#endregion
#region Ctor
- public InstallUrlMiddleware(RequestDelegate next)
+ public InstallUrlMiddleware(RequestDelegate next, ICacheBase cacheBase)
{
_next = next;
+ _cacheBase = cacheBase;
}
#endregion
#region Methods
- ///
- /// Invoke middleware actions
- ///
- /// HTTP context
- /// Task
public async Task InvokeAsync(HttpContext context)
{
- //whether database is installed
if (!DataSettingsManager.DatabaseIsInstalled())
{
- var featureManager = context.RequestServices.GetRequiredService();
- var isInstallerModuleEnabled = await featureManager.IsEnabledAsync("Grand.Module.Installer");
- if (!isInstallerModuleEnabled)
- {
- // Return a response indicating the installer module is not enabled
- context.Response.StatusCode = StatusCodes.Status403Forbidden;
- await context.Response.WriteAsync("The installation module is not enabled.");
- return;
- }
-
- const string installUrl = "/install";
- if (!context.Request.GetEncodedPathAndQuery().StartsWith(installUrl, StringComparison.OrdinalIgnoreCase))
- {
- //redirect
- context.Response.Redirect(installUrl);
- return;
- }
+ await HandleInstallationAsync(context);
+ return;
+ }
+
+ var version = GetDatabaseVersion(context);
+
+ if (version == null)
+ {
+ await HandleInstallationAsync(context);
+ return;
+ }
+
+ if (!version.DataBaseVersion.Equals(GrandVersion.SupportedDBVersion))
+ {
+ await context.Response.WriteAsync($"The database version is not supported in this software version. Supported version: {GrandVersion.SupportedDBVersion}, your version: {version.DataBaseVersion}");
+ return;
+ }
+
+ if (IsInstallUrl(context.Request))
+ {
+ context.Response.Redirect("/");
+ return;
}
- //or call the next middleware in the request pipeline
+ // Call the next middleware in the pipeline
await _next(context);
}
+ private async Task HandleInstallationAsync(HttpContext context)
+ {
+ var featureManager = context.RequestServices.GetRequiredService();
+ var isInstallerModuleEnabled = await featureManager.IsEnabledAsync("Grand.Module.Installer");
+
+ if (!isInstallerModuleEnabled)
+ {
+ context.Response.StatusCode = StatusCodes.Status403Forbidden;
+ await context.Response.WriteAsync("The installation module is not enabled.");
+ return;
+ }
+
+ if (!IsInstallUrl(context.Request))
+ {
+ context.Response.Redirect(InstallUrl);
+ }
+ }
+
+ private GrandNodeVersion? GetDatabaseVersion(HttpContext context)
+ {
+ return _cacheBase.Get(CacheKey.GRAND_NODE_VERSION, () =>
+ {
+ var repository = context.RequestServices.GetRequiredService>();
+ return repository.Table.FirstOrDefault();
+ }, int.MaxValue);
+ }
+
+ private bool IsInstallUrl(HttpRequest request)
+ {
+ return request.GetEncodedPathAndQuery().StartsWith(InstallUrl, StringComparison.OrdinalIgnoreCase);
+ }
+
#endregion
-}
\ No newline at end of file
+}
diff --git a/src/Web/Grand.Web.Common/Middleware/WorkContextMiddleware.cs b/src/Web/Grand.Web.Common/Middleware/WorkContextMiddleware.cs
index ea200818b..06750a594 100644
--- a/src/Web/Grand.Web.Common/Middleware/WorkContextMiddleware.cs
+++ b/src/Web/Grand.Web.Common/Middleware/WorkContextMiddleware.cs
@@ -10,7 +10,7 @@ public class WorkContextMiddleware
private readonly RequestDelegate _next;
- private readonly List skipRoutePattern = ["/scalar/{documentName}", "/openapi/{documentName}.json"];
+ private readonly List skipRoutePattern = ["/scalar/{documentName}", "/openapi/{documentName}.json", "install"];
#endregion
diff --git a/src/Web/Grand.Web.Common/Startup/DbCheckStartup.cs b/src/Web/Grand.Web.Common/Startup/DbCheckStartup.cs
deleted file mode 100644
index d14c22645..000000000
--- a/src/Web/Grand.Web.Common/Startup/DbCheckStartup.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using Grand.Data;
-using Grand.Infrastructure;
-using Grand.Infrastructure.Configuration;
-using Grand.Web.Common.Middleware;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace Grand.Web.Common.Startup;
-
-public class DbCheckStartup : IStartupApplication
-{
- public int Priority => 0;
- public bool BeforeConfigure => false;
-
- public void Configure(WebApplication application, IWebHostEnvironment webHostEnvironment)
- {
- if (!DataSettingsManager.DatabaseIsInstalled())
- return;
-
- var performanceConfig = application.Services.GetRequiredService();
-
- if (!performanceConfig.IgnoreDbVersionCheckMiddleware)
- application.UseMiddleware();
- }
-
- public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
- {
- }
-}
\ No newline at end of file
diff --git a/src/Web/Grand.Web/App_Data/appsettings.json b/src/Web/Grand.Web/App_Data/appsettings.json
index c46438c4b..8beaa9493 100644
--- a/src/Web/Grand.Web/App_Data/appsettings.json
+++ b/src/Web/Grand.Web/App_Data/appsettings.json
@@ -21,16 +21,17 @@
//Gets or sets the value to enable a middleware for logging additional information about CurrentCustomer and CurrentStore
"EnableContextLoggingMiddleware": true
},
+ //only for advanced users, allow to set ConnectionString for MongoDb
+ "ConnectionStrings": {
+ "Mongodb": ""
+ },
"Database": {
//This setting is required to use LiteDB database
"UseLiteDb": false,
//LiteDB database as a singleton service in the application
"Singleton": true,
//Init connection string - it's required only for the installation process!
- "LiteDbConnectionString": "Filename=App_Data/database.db",
- //only for advanced users, allow to set ConnectionString for MongoDb
- "ConnectionString": "",
- "DbProvider": 0
+ "LiteDbConnectionString": "Filename=App_Data/database.db"
},
"Security": {
//Use a reverse proxy server - more information you can find at: https://docs.microsoft.com/en-US/aspnet/core/host-and-deploy/linux-nginx
@@ -104,8 +105,6 @@
//Indicates whether to compress response (gzip by default)
//You may want to disable it, for example, If you have an active IIS Dynamic Compression Module configured at the server level
"UseResponseCompression": false,
- //Indicates whether to ignore DbVersionCheckMiddleware
- "IgnoreDbVersionCheckMiddleware": false,
//Indicates whether to ignore UsePoweredByMiddleware
"IgnoreUsePoweredByMiddleware": false
},
diff --git a/src/Web/Grand.Web/Grand.Web.csproj b/src/Web/Grand.Web/Grand.Web.csproj
index e14340768..2dc8e420b 100644
--- a/src/Web/Grand.Web/Grand.Web.csproj
+++ b/src/Web/Grand.Web/Grand.Web.csproj
@@ -16,6 +16,7 @@
Linux
+
diff --git a/src/Web/Grand.Web/Program.cs b/src/Web/Grand.Web/Program.cs
index d0bcaada7..fcce538dd 100644
--- a/src/Web/Grand.Web/Program.cs
+++ b/src/Web/Grand.Web/Program.cs
@@ -1,4 +1,4 @@
-using Grand.Web.Common.Extensions;
+using Grand.Web.Common.Extensions;
using Grand.Web.Common.Startup;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
@@ -6,6 +6,8 @@
var builder = WebApplication.CreateBuilder(args);
+builder.AddServiceDefaults();
+
builder.Host.UseDefaultServiceProvider((_, options) =>
{
options.ValidateScopes = false;