@@ -177,6 +195,8 @@ else
private string _containertype = "-";
private string _admincontainertype = "";
private string _sitetemplatetype = "-";
+ private string _runtime = "Server";
+ private string _prerender = "Prerendered";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
@@ -340,6 +360,8 @@ else
config.DefaultContainer = _containertype;
config.DefaultAdminContainer = _admincontainertype;
config.SiteTemplate = _sitetemplatetype;
+ config.Runtime = _runtime;
+ config.RenderMode = _runtime + _prerender;
ShowProgressIndicator();
diff --git a/Oqtane.Client/Modules/Admin/SystemInfo/Index.razor b/Oqtane.Client/Modules/Admin/SystemInfo/Index.razor
index 9cd52ff2..f28731dc 100644
--- a/Oqtane.Client/Modules/Admin/SystemInfo/Index.razor
+++ b/Oqtane.Client/Modules/Admin/SystemInfo/Index.razor
@@ -50,24 +50,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
@@ -126,8 +108,6 @@
private string _servertime = string.Empty;
private string _installationid = string.Empty;
- private string _runtime = string.Empty;
- private string _rendermode = string.Empty;
private string _detailederrors = string.Empty;
private string _logginglevel = string.Empty;
private string _swagger = string.Empty;
@@ -146,8 +126,6 @@
_servertime = systeminfo["servertime"];
_installationid = systeminfo["installationid"];
- _runtime = systeminfo["runtime"];
- _rendermode = systeminfo["rendermode"];
_detailederrors = systeminfo["detailederrors"];
_logginglevel = systeminfo["logginglevel"];
_swagger = systeminfo["swagger"];
@@ -160,8 +138,6 @@
try
{
var settings = new Dictionary
();
- settings.Add("runtime", _runtime);
- settings.Add("rendermode", _rendermode);
settings.Add("detailederrors", _detailederrors);
settings.Add("logginglevel", _logginglevel);
settings.Add("swagger", _swagger);
diff --git a/Oqtane.Client/Program.cs b/Oqtane.Client/Program.cs
index f27f0c2e..68bcc7a2 100644
--- a/Oqtane.Client/Program.cs
+++ b/Oqtane.Client/Program.cs
@@ -24,7 +24,6 @@ namespace Oqtane.Client
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
- builder.RootComponents.Add("app");
var httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)};
diff --git a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx
index 74882e86..670a525a 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx
@@ -282,4 +282,19 @@
Select Theme
+
+ Hosting Model
+
+
+ Specifies if the site should be prerendered (for search crawlers, etc...)
+
+
+ Prerender?
+
+
+ The Blazor runtime hosting model
+
+
+ Runtime:
+
\ No newline at end of file
diff --git a/Oqtane.Client/Resources/Modules/Admin/Sites/Add.resx b/Oqtane.Client/Resources/Modules/Admin/Sites/Add.resx
index e0300472..6473d0ff 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Sites/Add.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Sites/Add.resx
@@ -258,4 +258,16 @@
Error loading Database Configuration Control
+
+ Specifies if the site should be prerendered (for search crawlers, etc...)
+
+
+ Prerender?
+
+
+ The Blazor runtime hosting model
+
+
+ Runtime:
+
\ No newline at end of file
diff --git a/Oqtane.Client/Resources/Modules/Admin/SystemInfo/Index.resx b/Oqtane.Client/Resources/Modules/Admin/SystemInfo/Index.resx
index 84c6992b..3b60da81 100644
--- a/Oqtane.Client/Resources/Modules/Admin/SystemInfo/Index.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/SystemInfo/Index.resx
@@ -123,9 +123,6 @@
Framework Version
-
- Blazor Runtime (Server or WebAssembly)
-
Common Language Runtime Version
@@ -141,9 +138,6 @@
Framework Version:
-
- Blazor Runtime:
-
CLR Version:
@@ -165,18 +159,9 @@
An Error Occurred Updating The Configuration
-
- Server
-
-
- ServerPrerendered
-
Configuration Updated. Please Select Restart Application For These Changes To Be Activated.
-
- WebAssembly
-
Installation ID:
diff --git a/Oqtane.Client/Resources/SharedResources.resx b/Oqtane.Client/Resources/SharedResources.resx
index b89dd91d..ce8bc2bb 100644
--- a/Oqtane.Client/Resources/SharedResources.resx
+++ b/Oqtane.Client/Resources/SharedResources.resx
@@ -312,4 +312,10 @@
Not Specified
+
+ Blazor Server
+
+
+ Blazor WebAssembly
+
\ No newline at end of file
diff --git a/Oqtane.Client/UI/SiteRouter.razor b/Oqtane.Client/UI/SiteRouter.razor
index 8f73a00b..82df0175 100644
--- a/Oqtane.Client/UI/SiteRouter.razor
+++ b/Oqtane.Client/UI/SiteRouter.razor
@@ -85,18 +85,18 @@
// parse querystring
var querystring = ParseQueryString(uri.Query);
- // the refresh parameter is used to refresh the PageState
- if (querystring.ContainsKey("refresh"))
+ // reload the client application if there is a forced reload or the user navigated to a site with a different alias
+ if (querystring.ContainsKey("reload") || (!path.ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path)))
{
- refresh = UI.Refresh.Site;
+ NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true);
+ return;
}
else
{
- // reload the client application if the user navigated to a site with a different alias or there is a forced reload
- if ((!path.ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path)) || querystring.ContainsKey("reload"))
+ // the refresh parameter is used to refresh the PageState
+ if (querystring.ContainsKey("refresh"))
{
- NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true);
- return;
+ refresh = UI.Refresh.Site;
}
}
@@ -109,10 +109,10 @@
// process any sync events
var sync = await SyncService.GetSyncAsync(lastsyncdate);
lastsyncdate = sync.SyncDate;
- if (refresh != UI.Refresh.Site && sync.SyncEvents.Any())
+ if (sync.SyncEvents.Any())
{
- // if running on WebAssembly reload the client application if the server application was restarted
- if (runtime == Shared.Runtime.WebAssembly && PageState != null && sync.SyncEvents.Exists(item => item.TenantId == -1))
+ // reload client application if server was restarted or site runtime/rendermode was modified
+ if (PageState != null && sync.SyncEvents.Exists(item => (item.TenantId == -1 || item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId) && item.Reload))
{
NavigationManager.NavigateTo(_absoluteUri, true);
return;
diff --git a/Oqtane.Package/release.cmd b/Oqtane.Package/release.cmd
index bc538a62..620e8117 100644
--- a/Oqtane.Package/release.cmd
+++ b/Oqtane.Package/release.cmd
@@ -17,6 +17,7 @@ del "..\Oqtane.Server\bin\Release\net5.0\publish\appsettings.json"
ren "..\Oqtane.Server\bin\Release\net5.0\publish\appsettings.release.json" "appsettings.json"
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
del "..\Oqtane.Server\bin\Release\net5.0\publish\appsettings.json"
+del "..\Oqtane.Server\bin\Release\net5.0\publish\web.config"
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\upgrade.ps1"
dotnet clean -c Release ..\Oqtane.Updater.sln
dotnet build -c Release ..\Oqtane.Updater.sln
diff --git a/Oqtane.Server/Controllers/InstallationController.cs b/Oqtane.Server/Controllers/InstallationController.cs
index ccf181b8..35e94b6f 100644
--- a/Oqtane.Server/Controllers/InstallationController.cs
+++ b/Oqtane.Server/Controllers/InstallationController.cs
@@ -102,15 +102,7 @@ namespace Oqtane.Controllers
[HttpGet("load")]
public IActionResult Load()
{
- if (_configManager.GetSection("Runtime").Value == "WebAssembly")
- {
- return File(GetAssemblies(), System.Net.Mime.MediaTypeNames.Application.Octet, "oqtane.dll");
- }
- else
- {
- HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
- return null;
- }
+ return File(GetAssemblies(), System.Net.Mime.MediaTypeNames.Application.Octet, "oqtane.dll");
}
private byte[] GetAssemblies()
diff --git a/Oqtane.Server/Controllers/SiteController.cs b/Oqtane.Server/Controllers/SiteController.cs
index b67cc126..6b4d1c7b 100644
--- a/Oqtane.Server/Controllers/SiteController.cs
+++ b/Oqtane.Server/Controllers/SiteController.cs
@@ -84,10 +84,16 @@ namespace Oqtane.Controllers
[Authorize(Roles = RoleNames.Admin)]
public Site Put(int id, [FromBody] Site site)
{
- if (ModelState.IsValid && site.SiteId == _alias.SiteId && site.TenantId == _alias.TenantId && _sites.GetSite(site.SiteId, false) != null)
+ var current = _sites.GetSite(site.SiteId, false);
+ if (ModelState.IsValid && site.SiteId == _alias.SiteId && site.TenantId == _alias.TenantId && current != null)
{
site = _sites.UpdateSite(site);
- _syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, site.SiteId);
+ bool reload = false;
+ if (current.Runtime != site.Runtime || current.RenderMode != site.RenderMode)
+ {
+ reload = true;
+ }
+ _syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, site.SiteId, reload);
_logger.Log(site.SiteId, LogLevel.Information, this, LogFunction.Update, "Site Updated {Site}", site);
}
else
diff --git a/Oqtane.Server/Infrastructure/DatabaseManager.cs b/Oqtane.Server/Infrastructure/DatabaseManager.cs
index c81f63a9..4fb7e6e5 100644
--- a/Oqtane.Server/Infrastructure/DatabaseManager.cs
+++ b/Oqtane.Server/Infrastructure/DatabaseManager.cs
@@ -585,7 +585,9 @@ namespace Oqtane.Infrastructure
DefaultThemeType = (!string.IsNullOrEmpty(install.DefaultTheme)) ? install.DefaultTheme : Constants.DefaultTheme,
DefaultContainerType = (!string.IsNullOrEmpty(install.DefaultContainer)) ? install.DefaultContainer : Constants.DefaultContainer,
AdminContainerType = (!string.IsNullOrEmpty(install.DefaultAdminContainer)) ? install.DefaultAdminContainer : Constants.DefaultAdminContainer,
- SiteTemplateType = install.SiteTemplate
+ SiteTemplateType = install.SiteTemplate,
+ Runtime = (!string.IsNullOrEmpty(install.Runtime)) ? install.Runtime : _configManager.GetSection("Runtime").Value,
+ RenderMode = (!string.IsNullOrEmpty(install.RenderMode)) ? install.RenderMode : _configManager.GetSection("RenderMode").Value
};
site = sites.AddSite(site);
diff --git a/Oqtane.Server/Infrastructure/Interfaces/ISyncManager.cs b/Oqtane.Server/Infrastructure/Interfaces/ISyncManager.cs
index b82e5196..b21d70af 100644
--- a/Oqtane.Server/Infrastructure/Interfaces/ISyncManager.cs
+++ b/Oqtane.Server/Infrastructure/Interfaces/ISyncManager.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using Oqtane.Models;
@@ -8,5 +8,6 @@ namespace Oqtane.Infrastructure
{
List GetSyncEvents(int tenantId, DateTime lastSyncDate);
void AddSyncEvent(int tenantId, string entityName, int entityId);
+ void AddSyncEvent(int tenantId, string entityName, int entityId, bool reload);
}
}
diff --git a/Oqtane.Server/Infrastructure/SyncManager.cs b/Oqtane.Server/Infrastructure/SyncManager.cs
index d70cc456..b4f4c551 100644
--- a/Oqtane.Server/Infrastructure/SyncManager.cs
+++ b/Oqtane.Server/Infrastructure/SyncManager.cs
@@ -22,7 +22,12 @@ namespace Oqtane.Infrastructure
public void AddSyncEvent(int tenantId, string entityName, int entityId)
{
- SyncEvents.Add(new SyncEvent { TenantId = tenantId, EntityName = entityName, EntityId = entityId, ModifiedOn = DateTime.UtcNow });
+ AddSyncEvent(tenantId, entityName, entityId, false);
+ }
+
+ public void AddSyncEvent(int tenantId, string entityName, int entityId, bool reload)
+ {
+ SyncEvents.Add(new SyncEvent { TenantId = tenantId, EntityName = entityName, EntityId = entityId, Reload = reload, ModifiedOn = DateTime.UtcNow });
// trim sync events
SyncEvents.RemoveAll(item => item.ModifiedOn < DateTime.UtcNow.AddHours(-1));
}
diff --git a/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs
index 28ac2164..8379c3e3 100644
--- a/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs
+++ b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs
@@ -1,8 +1,5 @@
-using System.Collections.Generic;
-using System.Linq;
using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Databases.Interfaces;
-using Oqtane.Interfaces;
namespace Oqtane.Migrations
{
diff --git a/Oqtane.Server/Migrations/Tenant/03000001_AddSiteRuntime.cs b/Oqtane.Server/Migrations/Tenant/03000001_AddSiteRuntime.cs
new file mode 100644
index 00000000..90a7237a
--- /dev/null
+++ b/Oqtane.Server/Migrations/Tenant/03000001_AddSiteRuntime.cs
@@ -0,0 +1,33 @@
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Oqtane.Databases.Interfaces;
+using Oqtane.Migrations.EntityBuilders;
+using Oqtane.Repository;
+
+namespace Oqtane.Migrations.Tenant
+{
+ [DbContext(typeof(TenantDBContext))]
+ [Migration("Tenant.03.00.00.01")]
+ public class AddSiteRuntime : MultiDatabaseMigration
+ {
+ public AddSiteRuntime(IDatabase database) : base(database)
+ {
+ }
+
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
+ siteEntityBuilder.AddStringColumn("Runtime", 50, true, true);
+ siteEntityBuilder.UpdateColumn("Runtime", "'Server'");
+ siteEntityBuilder.AddStringColumn("RenderMode", 50, true, true);
+ siteEntityBuilder.UpdateColumn("RenderMode", "'ServerPrerendered'");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
+ siteEntityBuilder.DropColumn("Runtime");
+ siteEntityBuilder.DropColumn("RenderMode");
+ }
+ }
+}
diff --git a/Oqtane.Server/Pages/_Host.cshtml.cs b/Oqtane.Server/Pages/_Host.cshtml.cs
index 499f00ad..6fa559ca 100644
--- a/Oqtane.Server/Pages/_Host.cshtml.cs
+++ b/Oqtane.Server/Pages/_Host.cshtml.cs
@@ -23,14 +23,16 @@ namespace Oqtane.Pages
private readonly ILocalizationManager _localizationManager;
private readonly ILanguageRepository _languages;
private readonly IAntiforgery _antiforgery;
+ private readonly ISiteRepository _sites;
- public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery)
+ public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites)
{
_configuration = configuration;
_tenantManager = tenantManager;
_localizationManager = localizationManager;
_languages = languages;
_antiforgery = antiforgery;
+ _sites = sites;
}
public string AntiForgeryToken = "";
@@ -48,7 +50,7 @@ namespace Oqtane.Pages
Runtime = _configuration.GetSection("Runtime").Value;
}
- if (Runtime != "WebAssembly" && _configuration.GetSection("RenderMode").Exists())
+ if (_configuration.GetSection("RenderMode").Exists())
{
RenderMode = (RenderMode)Enum.Parse(typeof(RenderMode), _configuration.GetSection("RenderMode").Value, true);
}
@@ -67,6 +69,19 @@ namespace Oqtane.Pages
var alias = _tenantManager.GetAlias();
if (alias != null)
{
+ var site = _sites.GetSite(alias.SiteId);
+ if (site != null)
+ {
+ if (!string.IsNullOrEmpty(site.Runtime))
+ {
+ Runtime = site.Runtime;
+ }
+ if (!string.IsNullOrEmpty(site.RenderMode))
+ {
+ RenderMode = (RenderMode)Enum.Parse(typeof(RenderMode), site.RenderMode, true);
+ }
+ }
+
// if culture not specified
if (HttpContext.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName] == null)
{
@@ -142,7 +157,6 @@ namespace Oqtane.Pages
}
}
}
-
private void ProcessResource(Resource resource)
{
switch (resource.ResourceType)
@@ -171,7 +185,6 @@ namespace Oqtane.Pages
break;
}
}
-
private string CrossOrigin(string crossorigin)
{
if (!string.IsNullOrEmpty(crossorigin))
diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs
index 4f5160ec..e82ee135 100644
--- a/Oqtane.Server/Startup.cs
+++ b/Oqtane.Server/Startup.cs
@@ -163,8 +163,8 @@ namespace Oqtane
endpoints.MapFallbackToPage("/_Host");
});
- // create a sync event to identify server application startup
- sync.AddSyncEvent(-1, "Application", -1);
+ // create a global sync event to identify server application startup
+ sync.AddSyncEvent(-1, "Application", -1, true);
}
}
}
diff --git a/Oqtane.Shared/Models/Site.cs b/Oqtane.Shared/Models/Site.cs
index 82a7fc62..5ccf11d0 100644
--- a/Oqtane.Shared/Models/Site.cs
+++ b/Oqtane.Shared/Models/Site.cs
@@ -58,6 +58,16 @@ namespace Oqtane.Models
///
public string SiteGuid { get; set; }
+ ///
+ /// The hosting model for the site (ie. Server or WebAssembly ).
+ ///
+ public string Runtime { get; set; }
+
+ ///
+ /// The render mode for the site (ie. Server, ServerPrerendered, WebAssembly, WebAssemblyPrerendered ).
+ ///
+ public string RenderMode { get; set; }
+
#region IAuditable Properties
///
diff --git a/Oqtane.Shared/Models/Sync.cs b/Oqtane.Shared/Models/Sync.cs
index 9430ab2a..6e58185f 100644
--- a/Oqtane.Shared/Models/Sync.cs
+++ b/Oqtane.Shared/Models/Sync.cs
@@ -14,6 +14,7 @@ namespace Oqtane.Models
public int TenantId { get; set; }
public string EntityName { get; set; }
public int EntityId { get; set; }
+ public bool Reload { get; set; }
public DateTime ModifiedOn { get; set; }
}
}
diff --git a/Oqtane.Shared/Shared/InstallConfig.cs b/Oqtane.Shared/Shared/InstallConfig.cs
index 79a78602..f4e7d053 100644
--- a/Oqtane.Shared/Shared/InstallConfig.cs
+++ b/Oqtane.Shared/Shared/InstallConfig.cs
@@ -17,6 +17,8 @@ namespace Oqtane.Shared
public string DefaultTheme { get; set; }
public string DefaultContainer { get; set; }
public string DefaultAdminContainer { get; set; }
+ public string Runtime { get; set; }
+ public string RenderMode { get; set; }
public bool Register { get; set; }
}
}