diff --git a/Oqtane.Client/UI/ModuleInstance.razor b/Oqtane.Client/UI/ModuleInstance.razor
index e9a634d3..0fda480f 100644
--- a/Oqtane.Client/UI/ModuleInstance.razor
+++ b/Oqtane.Client/UI/ModuleInstance.razor
@@ -10,11 +10,11 @@
@((MarkupString)_comment)
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static)
{
-
+
}
else
{
-
+
}
}
@if (PageState.ModuleId == -1)
@@ -32,6 +32,7 @@
private bool _prerender;
private string _comment;
+ private PageState _pageState;
protected override void OnParametersSet()
{
@@ -48,11 +49,12 @@
}
_comment += " -->";
+ _pageState = PageState.Clone();
if (PageState.RenderMode == RenderModes.Static && ModuleState.RenderMode == RenderModes.Interactive)
{
// trim PageState to mitigate page bloat caused by Blazor serializing/encrypting state when crossing render mode boundaries
- // please note that this performance optimization results in the PageState.Pages property not being available for use in Interactive components
- PageState.Site.Pages = new List
();
+ // please note that this performance optimization results in the PageState.Pages property not being available for use in downstream Interactive components
+ _pageState.Site.Pages = new List();
}
}
diff --git a/Oqtane.Client/UI/PageState.cs b/Oqtane.Client/UI/PageState.cs
index a038a81e..91cf158c 100644
--- a/Oqtane.Client/UI/PageState.cs
+++ b/Oqtane.Client/UI/PageState.cs
@@ -37,5 +37,34 @@ namespace Oqtane.UI
{
get { return Site?.Languages; }
}
+
+ public PageState Clone()
+ {
+ return new PageState
+ {
+ Alias = Alias,
+ Site = Site,
+ Page = Page,
+ Modules = Modules,
+ User = User,
+ Uri = Uri,
+ Route = Route,
+ QueryString = QueryString,
+ UrlParameters = UrlParameters,
+ ModuleId = ModuleId,
+ Action = Action,
+ EditMode = EditMode,
+ LastSyncDate = LastSyncDate,
+ RenderMode = RenderMode,
+ Runtime = Runtime,
+ VisitorId = VisitorId,
+ RemoteIPAddress = RemoteIPAddress,
+ ReturnUrl = ReturnUrl,
+ IsInternalNavigation = IsInternalNavigation,
+ RenderId = RenderId,
+ Refresh = Refresh,
+ AllowCookies = AllowCookies
+ };
+ }
}
}
diff --git a/Oqtane.Client/UI/Pane.razor b/Oqtane.Client/UI/Pane.razor
index 70226c2e..633cd4fd 100644
--- a/Oqtane.Client/UI/Pane.razor
+++ b/Oqtane.Client/UI/Pane.razor
@@ -29,7 +29,7 @@ else
RenderFragment DynamicComponent { get; set; }
protected override void OnParametersSet()
- {
+ {
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList) && PageState.Action == Constants.DefaultAction)
{
_useadminborder = true;
@@ -45,12 +45,6 @@ else
{
foreach (Module module in PageState.Modules)
{
- // set renderid - this allows the framework to determine which components should be rendered when PageState changes
- if (module.RenderId != PageState.RenderId)
- {
- module.RenderId = PageState.RenderId;
- }
-
var pane = module.Pane;
if (module.ModuleId == PageState.ModuleId && PageState.Action != Constants.DefaultAction)
{
@@ -101,7 +95,7 @@ else
if (authorized)
{
- CreateComponent(builder, module, module.PageModuleId);
+ CreateComponent(builder, module);
}
}
}
@@ -112,7 +106,7 @@ else
// check if user is authorized to view module
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
{
- CreateComponent(builder, module, -1);
+ CreateComponent(builder, module);
}
}
}
@@ -121,14 +115,11 @@ else
};
}
- private void CreateComponent(RenderTreeBuilder builder, Module module, int key)
+ private void CreateComponent(RenderTreeBuilder builder, Module module)
{
builder.OpenComponent(0, typeof(ContainerBuilder));
builder.AddAttribute(1, "ModuleState", module);
- if (key != -1)
- {
- builder.SetKey(module.PageModuleId);
- }
+ builder.SetKey(module.PageModuleId);
builder.CloseComponent();
}
}
diff --git a/Oqtane.Client/UI/RenderModeBoundary.razor b/Oqtane.Client/UI/RenderModeBoundary.razor
index 2c451f29..dbaac7f5 100644
--- a/Oqtane.Client/UI/RenderModeBoundary.razor
+++ b/Oqtane.Client/UI/RenderModeBoundary.razor
@@ -4,8 +4,8 @@
@inject ILogService LoggingService
@inherits ErrorBoundary
-
-
+
+
@if (CurrentException is null)
{
@if (ModuleType != null)
diff --git a/Oqtane.Client/UI/Routes.razor b/Oqtane.Client/UI/Routes.razor
index 20dc0a09..6081966c 100644
--- a/Oqtane.Client/UI/Routes.razor
+++ b/Oqtane.Client/UI/Routes.razor
@@ -48,12 +48,18 @@
private bool _initialized = false;
private bool _installed = false;
- private string _display = "display: none;";
+ private string _display = "";
private PageState _pageState { get; set; }
protected override async Task OnParametersSetAsync()
{
+ if (PageState != null && PageState.RenderMode == RenderModes.Interactive && PageState.Site.Prerender)
+ {
+ // prevents flash on initial interactive page load when using prerendering
+ _display = "display: none;";
+ }
+
SiteState.AntiForgeryToken = AntiForgeryToken;
SiteState.AuthorizationToken = AuthorizationToken;
SiteState.Platform = Platform;
@@ -61,7 +67,7 @@
if (Runtime == Runtimes.Hybrid)
{
- var installation = await InstallationService.IsInstalled();
+ var installation = await InstallationService.IsInstalled();
_installed = installation.Success;
if (installation.Alias != null)
{
@@ -73,8 +79,8 @@
if (PageState != null)
{
_pageState = PageState;
- SiteState.Alias = PageState.Alias;
- SiteState.RemoteIPAddress = (PageState != null) ? PageState.RemoteIPAddress : "";
+ SiteState.Alias = _pageState.Alias;
+ SiteState.RemoteIPAddress = _pageState.RemoteIPAddress;
_installed = true;
}
}
@@ -85,9 +91,7 @@
{
if (firstRender)
{
- // prevents flash on initial interactive page load
_display = "";
- StateHasChanged();
}
}
diff --git a/Oqtane.Client/UI/SiteRouter.razor b/Oqtane.Client/UI/SiteRouter.razor
index 3c3c81fe..a345a7f0 100644
--- a/Oqtane.Client/UI/SiteRouter.razor
+++ b/Oqtane.Client/UI/SiteRouter.razor
@@ -71,7 +71,7 @@
{
if (PageState == null || PageState.Refresh)
{
- await Refresh();
+ await Refresh(false);
}
}
@@ -79,7 +79,7 @@
{
_absoluteUri = args.Location;
_isInternalNavigation = true;
- await Refresh();
+ await Refresh(true);
}
Task IHandleAfterRender.OnAfterRenderAsync()
@@ -93,7 +93,7 @@
}
[SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")]
- private async Task Refresh()
+ private async Task Refresh(bool locationChanged)
{
Site site = null;
Page page = null;
@@ -103,6 +103,7 @@
var refresh = false;
var lastsyncdate = DateTime.MinValue;
var visitorId = -1;
+ var renderid = Guid.Empty;
_error = "";
Route route = new Route(_absoluteUri, SiteState.Alias.Path);
@@ -288,11 +289,21 @@
modules = PageState.Modules;
}
+ // renderid allows the framework to determine which module components should be rendered on a page
+ if (PageState == null || locationChanged)
+ {
+ renderid = Guid.NewGuid();
+ }
+ else
+ {
+ renderid = PageState.RenderId;
+ }
+
// load additional metadata for current page
page = ProcessPage(page, site, user, SiteState.Alias, action);
// load additional metadata for modules
- (page, modules) = ProcessModules(site, page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
+ (page, modules) = ProcessModules(site, page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias, renderid);
//cookie consent
var _allowCookies = PageState?.AllowCookies;
@@ -324,7 +335,7 @@
RemoteIPAddress = SiteState.RemoteIPAddress,
ReturnUrl = returnurl,
IsInternalNavigation = _isInternalNavigation,
- RenderId = Guid.NewGuid(),
+ RenderId = renderid,
Refresh = false,
AllowCookies = _allowCookies.GetValueOrDefault(true)
};
@@ -447,7 +458,7 @@
return page;
}
- private (Page Page, List Modules) ProcessModules(Site site, Page page, List modules, int moduleid, string action, string defaultcontainertype, Alias alias)
+ private (Page Page, List Modules) ProcessModules(Site site, Page page, List modules, int moduleid, string action, string defaultcontainertype, Alias alias, Guid renderid)
{
var paneindex = new Dictionary();
@@ -592,6 +603,8 @@
{
module.ContainerType = defaultcontainertype;
}
+
+ module.RenderId = renderid;
}
foreach (Module module in modules.Where(item => item.PageId == page.PageId))