|  |  |  | @ -22,201 +22,201 @@ | 
		
	
		
			
				|  |  |  |  | @DynamicComponent | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | @code { | 
		
	
		
			
				|  |  |  |  | 	private string _absoluteUri; | 
		
	
		
			
				|  |  |  |  | 	private bool _navigationInterceptionEnabled; | 
		
	
		
			
				|  |  |  |  | 	private PageState _pagestate; | 
		
	
		
			
				|  |  |  |  | 	private string _error = ""; | 
		
	
		
			
				|  |  |  |  |     private string _absoluteUri; | 
		
	
		
			
				|  |  |  |  |     private bool _navigationInterceptionEnabled; | 
		
	
		
			
				|  |  |  |  |     private PageState _pagestate; | 
		
	
		
			
				|  |  |  |  |     private string _error = ""; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	[Parameter] | 
		
	
		
			
				|  |  |  |  | 	public string Runtime { get; set; } | 
		
	
		
			
				|  |  |  |  |     [Parameter] | 
		
	
		
			
				|  |  |  |  |     public string Runtime { get; set; } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	[Parameter] | 
		
	
		
			
				|  |  |  |  | 	public string RenderMode { get; set; } | 
		
	
		
			
				|  |  |  |  |     [Parameter] | 
		
	
		
			
				|  |  |  |  |     public string RenderMode { get; set; } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	[Parameter] | 
		
	
		
			
				|  |  |  |  | 	public int VisitorId { get; set; } | 
		
	
		
			
				|  |  |  |  |     [Parameter] | 
		
	
		
			
				|  |  |  |  |     public int VisitorId { get; set; } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	[CascadingParameter] | 
		
	
		
			
				|  |  |  |  | 	PageState PageState { get; set; } | 
		
	
		
			
				|  |  |  |  |     [CascadingParameter] | 
		
	
		
			
				|  |  |  |  |     PageState PageState { get; set; } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	[Parameter] | 
		
	
		
			
				|  |  |  |  | 	public Action<PageState> OnStateChange { get; set; } | 
		
	
		
			
				|  |  |  |  |     [Parameter] | 
		
	
		
			
				|  |  |  |  |     public Action<PageState> OnStateChange { get; set; } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	private RenderFragment DynamicComponent { get; set; } | 
		
	
		
			
				|  |  |  |  |     private RenderFragment DynamicComponent { get; set; } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	protected override void OnInitialized() | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_absoluteUri = NavigationManager.Uri; | 
		
	
		
			
				|  |  |  |  | 		NavigationManager.LocationChanged += LocationChanged; | 
		
	
		
			
				|  |  |  |  |     protected override void OnInitialized() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         _absoluteUri = NavigationManager.Uri; | 
		
	
		
			
				|  |  |  |  |         NavigationManager.LocationChanged += LocationChanged; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		DynamicComponent = builder => | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (PageState != null) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				builder.OpenComponent(0, Type.GetType(Constants.PageComponent)); | 
		
	
		
			
				|  |  |  |  | 				builder.CloseComponent(); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		}; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |         DynamicComponent = builder => | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (PageState != null) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 builder.OpenComponent(0, Type.GetType(Constants.PageComponent)); | 
		
	
		
			
				|  |  |  |  |                 builder.CloseComponent(); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         }; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	public void Dispose() | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		NavigationManager.LocationChanged -= LocationChanged; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |     public void Dispose() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         NavigationManager.LocationChanged -= LocationChanged; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	protected override async Task OnParametersSetAsync() | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (PageState == null) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			await Refresh(); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |     protected override async Task OnParametersSetAsync() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (PageState == null) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             await Refresh(); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	[SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")] | 
		
	
		
			
				|  |  |  |  | 	private async Task Refresh() | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		Site site; | 
		
	
		
			
				|  |  |  |  | 		Page page; | 
		
	
		
			
				|  |  |  |  | 		User user = null; | 
		
	
		
			
				|  |  |  |  | 		var editmode = false; | 
		
	
		
			
				|  |  |  |  | 		var refresh = false; | 
		
	
		
			
				|  |  |  |  | 		var lastsyncdate = DateTime.UtcNow.AddHours(-1); | 
		
	
		
			
				|  |  |  |  | 		var runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), Runtime); | 
		
	
		
			
				|  |  |  |  | 		_error = ""; | 
		
	
		
			
				|  |  |  |  |     [SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")] | 
		
	
		
			
				|  |  |  |  |     private async Task Refresh() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         Site site; | 
		
	
		
			
				|  |  |  |  |         Page page; | 
		
	
		
			
				|  |  |  |  |         User user = null; | 
		
	
		
			
				|  |  |  |  |         var editmode = false; | 
		
	
		
			
				|  |  |  |  |         var refresh = false; | 
		
	
		
			
				|  |  |  |  |         var lastsyncdate = DateTime.UtcNow.AddHours(-1); | 
		
	
		
			
				|  |  |  |  |         var runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), Runtime); | 
		
	
		
			
				|  |  |  |  |         _error = ""; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		Route route = new Route(_absoluteUri, SiteState.Alias.Path); | 
		
	
		
			
				|  |  |  |  | 		int moduleid = (int.TryParse(route.ModuleId, out moduleid)) ? moduleid : -1; | 
		
	
		
			
				|  |  |  |  | 		var action = (!string.IsNullOrEmpty(route.Action)) ? route.Action : Constants.DefaultAction;  | 
		
	
		
			
				|  |  |  |  | 		var querystring = ParseQueryString(route.Query); | 
		
	
		
			
				|  |  |  |  | 		var returnurl = ""; | 
		
	
		
			
				|  |  |  |  | 		if (querystring.ContainsKey("returnurl")) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			returnurl = WebUtility.UrlDecode(querystring["returnurl"]); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |         Route route = new Route(_absoluteUri, SiteState.Alias.Path); | 
		
	
		
			
				|  |  |  |  |         int moduleid = (int.TryParse(route.ModuleId, out moduleid)) ? moduleid : -1; | 
		
	
		
			
				|  |  |  |  |         var action = (!string.IsNullOrEmpty(route.Action)) ? route.Action : Constants.DefaultAction;  | 
		
	
		
			
				|  |  |  |  |         var querystring = ParseQueryString(route.Query); | 
		
	
		
			
				|  |  |  |  |         var returnurl = ""; | 
		
	
		
			
				|  |  |  |  |         if (querystring.ContainsKey("returnurl")) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             returnurl = WebUtility.UrlDecode(querystring["returnurl"]); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		// reload the client application from the server if there is a forced reload or the user navigated to a site with a different alias  | 
		
	
		
			
				|  |  |  |  | 		if (querystring.ContainsKey("reload") || (!NavigationManager.ToBaseRelativePath(_absoluteUri).ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path))) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (querystring.ContainsKey("reload") && querystring["reload"] == "post") | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				// post back so that the cookies are set correctly - required on any change to the principal  | 
		
	
		
			
				|  |  |  |  | 				var interop = new Interop(JSRuntime); | 
		
	
		
			
				|  |  |  |  | 				var fields = new { returnurl = "/" + NavigationManager.ToBaseRelativePath(_absoluteUri) }; | 
		
	
		
			
				|  |  |  |  | 				string url = Utilities.TenantUrl(SiteState.Alias, "/pages/external/"); | 
		
	
		
			
				|  |  |  |  | 				await interop.SubmitForm(url, fields); | 
		
	
		
			
				|  |  |  |  | 				return; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			else | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true); | 
		
	
		
			
				|  |  |  |  | 				return;				 | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |         // reload the client application from the server if there is a forced reload or the user navigated to a site with a different alias  | 
		
	
		
			
				|  |  |  |  |         if (querystring.ContainsKey("reload") || (!NavigationManager.ToBaseRelativePath(_absoluteUri).ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path))) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (querystring.ContainsKey("reload") && querystring["reload"] == "post") | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 // post back so that the cookies are set correctly - required on any change to the principal  | 
		
	
		
			
				|  |  |  |  |                 var interop = new Interop(JSRuntime); | 
		
	
		
			
				|  |  |  |  |                 var fields = new { returnurl = "/" + NavigationManager.ToBaseRelativePath(_absoluteUri) }; | 
		
	
		
			
				|  |  |  |  |                 string url = Utilities.TenantUrl(SiteState.Alias, "/pages/external/"); | 
		
	
		
			
				|  |  |  |  |                 await interop.SubmitForm(url, fields); | 
		
	
		
			
				|  |  |  |  |                 return; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             else | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true); | 
		
	
		
			
				|  |  |  |  |                 return;				 | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		// the refresh parameter is used to refresh the client-side PageState | 
		
	
		
			
				|  |  |  |  | 		if (querystring.ContainsKey("refresh")) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			refresh = true; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |         // the refresh parameter is used to refresh the client-side PageState | 
		
	
		
			
				|  |  |  |  |         if (querystring.ContainsKey("refresh")) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             refresh = true; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (PageState != null) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			editmode = PageState.EditMode; | 
		
	
		
			
				|  |  |  |  | 			lastsyncdate = PageState.LastSyncDate; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		if (PageState?.Page.Path != route.PagePath) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			editmode = false; // reset edit mode when navigating to different page | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |         if (PageState != null) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             editmode = PageState.EditMode; | 
		
	
		
			
				|  |  |  |  |             lastsyncdate = PageState.LastSyncDate; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         if (PageState?.Page.Path != route.PagePath) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             editmode = false; // reset edit mode when navigating to different page | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		// get user | 
		
	
		
			
				|  |  |  |  | 		if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); | 
		
	
		
			
				|  |  |  |  | 			if (authState.User.Identity.IsAuthenticated) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				user = await UserService.GetUserAsync(authState.User.Identity.Name, SiteState.Alias.SiteId); | 
		
	
		
			
				|  |  |  |  | 				if (user != null) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					user.IsAuthenticated = authState.User.Identity.IsAuthenticated; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		else | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			user = PageState.User; | 
		
	
		
			
				|  |  |  |  | 		}        | 
		
	
		
			
				|  |  |  |  |         // get user | 
		
	
		
			
				|  |  |  |  |         if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); | 
		
	
		
			
				|  |  |  |  |             if (authState.User.Identity.IsAuthenticated) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 user = await UserService.GetUserAsync(authState.User.Identity.Name, SiteState.Alias.SiteId); | 
		
	
		
			
				|  |  |  |  |                 if (user != null) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     user.IsAuthenticated = authState.User.Identity.IsAuthenticated; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             user = PageState.User; | 
		
	
		
			
				|  |  |  |  |         }        | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		// process any sync events | 
		
	
		
			
				|  |  |  |  | 		var sync = await SyncService.GetSyncAsync(lastsyncdate); | 
		
	
		
			
				|  |  |  |  | 		lastsyncdate = sync.SyncDate; | 
		
	
		
			
				|  |  |  |  | 		if (sync.SyncEvents.Any()) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			// reload client application if server was restarted or site runtime/rendermode was modified | 
		
	
		
			
				|  |  |  |  | 			if (PageState != null && sync.SyncEvents.Exists(item => (item.Action == SyncEventActions.Reload))) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				NavigationManager.NavigateTo(_absoluteUri, true); | 
		
	
		
			
				|  |  |  |  | 				return; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			// when site information has changed the PageState needs to be refreshed | 
		
	
		
			
				|  |  |  |  | 			if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId)) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				refresh = true; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			// when user information has changed the PageState needs to be refreshed as the list of pages/modules may have changed | 
		
	
		
			
				|  |  |  |  | 			if (user != null && sync.SyncEvents.Exists(item => item.EntityName == EntityNames.User && item.EntityId == user.UserId)) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				refresh = true; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |         // process any sync events | 
		
	
		
			
				|  |  |  |  |         var sync = await SyncService.GetSyncAsync(lastsyncdate); | 
		
	
		
			
				|  |  |  |  |         lastsyncdate = sync.SyncDate; | 
		
	
		
			
				|  |  |  |  |         if (sync.SyncEvents.Any()) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             // reload client application if server was restarted or site runtime/rendermode was modified | 
		
	
		
			
				|  |  |  |  |             if (PageState != null && sync.SyncEvents.Exists(item => (item.Action == SyncEventActions.Reload))) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 NavigationManager.NavigateTo(_absoluteUri, true); | 
		
	
		
			
				|  |  |  |  |                 return; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             // when site information has changed the PageState needs to be refreshed | 
		
	
		
			
				|  |  |  |  |             if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId)) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 refresh = true; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             // when user information has changed the PageState needs to be refreshed as the list of pages/modules may have changed | 
		
	
		
			
				|  |  |  |  |             if (user != null && sync.SyncEvents.Exists(item => item.EntityName == EntityNames.User && item.EntityId == user.UserId)) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 refresh = true; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			site = await SiteService.GetSiteAsync(SiteState.Alias.SiteId); | 
		
	
		
			
				|  |  |  |  | 			refresh = true; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		else | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			site = PageState.Site; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |         if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             site = await SiteService.GetSiteAsync(SiteState.Alias.SiteId); | 
		
	
		
			
				|  |  |  |  |             refresh = true; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             site = PageState.Site; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (site != null) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (PageState == null || refresh || PageState.Page.Path != route.PagePath) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				page = site.Pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase)); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			else | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				page = PageState.Page; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |         if (site != null) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (PageState == null || refresh || PageState.Page.Path != route.PagePath) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 page = site.Pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase)); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             else | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 page = PageState.Page; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (page == null && route.PagePath == "") // naked path refers to site home page | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				if (site.HomePageId != null) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					page = site.Pages.FirstOrDefault(item => item.PageId == site.HomePageId); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				if (page == null) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					// fallback to use the first page in the collection | 
		
	
		
			
				|  |  |  |  | 					page = site.Pages.FirstOrDefault(); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |             if (page == null && route.PagePath == "") // naked path refers to site home page | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 if (site.HomePageId != null) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     page = site.Pages.FirstOrDefault(item => item.PageId == site.HomePageId); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 if (page == null) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     // fallback to use the first page in the collection | 
		
	
		
			
				|  |  |  |  |                     page = site.Pages.FirstOrDefault(); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (page != null) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				// check if user is authorized to view page | 
		
	
		
			
				|  |  |  |  | 				if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList)) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					// load additional metadata for current page | 
		
	
		
			
				|  |  |  |  | 					page = await ProcessPage(page, site, user); | 
		
	
		
			
				|  |  |  |  |             if (page != null) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 // check if user is authorized to view page | 
		
	
		
			
				|  |  |  |  |                 if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList)) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     // load additional metadata for current page | 
		
	
		
			
				|  |  |  |  |                     page = await ProcessPage(page, site, user, SiteState.Alias); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					// load additional metadata for modules | 
		
	
		
			
				|  |  |  |  | 					(page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType); | 
		
	
		
			
				|  |  |  |  |                     // load additional metadata for modules | 
		
	
		
			
				|  |  |  |  |                     (page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					// populate page state (which acts as a client-side cache for subsequent requests) | 
		
	
		
			
				|  |  |  |  | 					_pagestate = new PageState | 
		
	
		
			
				|  |  |  |  |                     // populate page state (which acts as a client-side cache for subsequent requests) | 
		
	
		
			
				|  |  |  |  |                     _pagestate = new PageState | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         Alias = SiteState.Alias, | 
		
	
		
			
				|  |  |  |  |                         Site = site, | 
		
	
	
		
			
				
					
					|  |  |  | @ -236,295 +236,311 @@ | 
		
	
		
			
				|  |  |  |  | 						ReturnUrl = returnurl | 
		
	
		
			
				|  |  |  |  |                     }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					OnStateChange?.Invoke(_pagestate); | 
		
	
		
			
				|  |  |  |  | 					await ScrollToFragment(_pagestate.Uri); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			else // page not found | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				// look for url mapping | 
		
	
		
			
				|  |  |  |  | 				var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.PagePath); | 
		
	
		
			
				|  |  |  |  | 				if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl)) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl; | 
		
	
		
			
				|  |  |  |  | 					NavigationManager.NavigateTo(url, false); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				else // not mapped | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					if (user == null) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						// redirect to login page if user not logged in as they may need to be authenticated | 
		
	
		
			
				|  |  |  |  | 						NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery))); | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 					else | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						if (route.PagePath != "404") | 
		
	
		
			
				|  |  |  |  | 						{ | 
		
	
		
			
				|  |  |  |  | 							// redirect to 404 page | 
		
	
		
			
				|  |  |  |  | 							NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "404", "")); | 
		
	
		
			
				|  |  |  |  | 						} | 
		
	
		
			
				|  |  |  |  | 						else | 
		
	
		
			
				|  |  |  |  | 						{ | 
		
	
		
			
				|  |  |  |  | 							// redirect to home page as a fallback | 
		
	
		
			
				|  |  |  |  | 							NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "", "")); | 
		
	
		
			
				|  |  |  |  | 						} | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		else | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			// site does not exist | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |                     OnStateChange?.Invoke(_pagestate); | 
		
	
		
			
				|  |  |  |  |                     await ScrollToFragment(_pagestate.Uri); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             else // page not found | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 // look for url mapping | 
		
	
		
			
				|  |  |  |  |                 var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.PagePath); | 
		
	
		
			
				|  |  |  |  |                 if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl)) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl; | 
		
	
		
			
				|  |  |  |  |                     NavigationManager.NavigateTo(url, false); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 else // not mapped | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     if (user == null) | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         // redirect to login page if user not logged in as they may need to be authenticated | 
		
	
		
			
				|  |  |  |  |                         NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery))); | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     else | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         if (route.PagePath != "404") | 
		
	
		
			
				|  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |                             // redirect to 404 page | 
		
	
		
			
				|  |  |  |  |                             NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "404", "")); | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                         else | 
		
	
		
			
				|  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |                             // redirect to home page as a fallback | 
		
	
		
			
				|  |  |  |  |                             NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "", "")); | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             // site does not exist | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	private async void LocationChanged(object sender, LocationChangedEventArgs args) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_absoluteUri = args.Location; | 
		
	
		
			
				|  |  |  |  | 		await Refresh(); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |     private async void LocationChanged(object sender, LocationChangedEventArgs args) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         _absoluteUri = args.Location; | 
		
	
		
			
				|  |  |  |  |         await Refresh(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	Task IHandleAfterRender.OnAfterRenderAsync() | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (!_navigationInterceptionEnabled) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			_navigationInterceptionEnabled = true; | 
		
	
		
			
				|  |  |  |  | 			return NavigationInterception.EnableNavigationInterceptionAsync(); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		return Task.CompletedTask; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |     Task IHandleAfterRender.OnAfterRenderAsync() | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (!_navigationInterceptionEnabled) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             _navigationInterceptionEnabled = true; | 
		
	
		
			
				|  |  |  |  |             return NavigationInterception.EnableNavigationInterceptionAsync(); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         return Task.CompletedTask; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	private Dictionary<string, string> ParseQueryString(string query) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		Dictionary<string, string> querystring = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // case insensistive keys | 
		
	
		
			
				|  |  |  |  | 		if (!string.IsNullOrEmpty(query)) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (query.StartsWith("?")) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				query = query.Substring(1); // ignore "?" | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			foreach (string kvp in query.Split('&', StringSplitOptions.RemoveEmptyEntries)) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				if (kvp != "") | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					if (kvp.Contains("=")) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						string[] pair = kvp.Split('='); | 
		
	
		
			
				|  |  |  |  | 						if (!querystring.ContainsKey(pair[0])) | 
		
	
		
			
				|  |  |  |  | 						{ | 
		
	
		
			
				|  |  |  |  | 							querystring.Add(pair[0], pair[1]); | 
		
	
		
			
				|  |  |  |  | 						} | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 					else | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						if (!querystring.ContainsKey(kvp)) | 
		
	
		
			
				|  |  |  |  | 						{ | 
		
	
		
			
				|  |  |  |  | 							querystring.Add(kvp, "true"); // default parameter when no value is provided | 
		
	
		
			
				|  |  |  |  | 						} | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		return querystring; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |     private Dictionary<string, string> ParseQueryString(string query) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         Dictionary<string, string> querystring = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // case insensistive keys | 
		
	
		
			
				|  |  |  |  |         if (!string.IsNullOrEmpty(query)) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (query.StartsWith("?")) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 query = query.Substring(1); // ignore "?" | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             foreach (string kvp in query.Split('&', StringSplitOptions.RemoveEmptyEntries)) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 if (kvp != "") | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     if (kvp.Contains("=")) | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         string[] pair = kvp.Split('='); | 
		
	
		
			
				|  |  |  |  |                         if (!querystring.ContainsKey(pair[0])) | 
		
	
		
			
				|  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |                             querystring.Add(pair[0], pair[1]); | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     else | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         if (!querystring.ContainsKey(kvp)) | 
		
	
		
			
				|  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |                             querystring.Add(kvp, "true"); // default parameter when no value is provided | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         return querystring; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	private async Task<Page> ProcessPage(Page page, Site site, User user) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		try | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (page.IsPersonalizable && user != null) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				// load the personalized page | 
		
	
		
			
				|  |  |  |  | 				page = await PageService.GetPageAsync(page.PageId, user.UserId); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |     private async Task<Page> ProcessPage(Page page, Site site, User user, Alias alias) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         try | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (page.IsPersonalizable && user != null) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 // load the personalized page | 
		
	
		
			
				|  |  |  |  |                 page = await PageService.GetPageAsync(page.PageId, user.UserId); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (string.IsNullOrEmpty(page.ThemeType)) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				page.ThemeType = site.DefaultThemeType; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |             if (string.IsNullOrEmpty(page.ThemeType)) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 page.ThemeType = site.DefaultThemeType; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			page.Panes = new List<string>(); | 
		
	
		
			
				|  |  |  |  | 			page.Resources = new List<Resource>(); | 
		
	
		
			
				|  |  |  |  |             page.Panes = new List<string>(); | 
		
	
		
			
				|  |  |  |  |             page.Resources = new List<Resource>(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			string panes = ""; | 
		
	
		
			
				|  |  |  |  | 			Type themetype = Type.GetType(page.ThemeType); | 
		
	
		
			
				|  |  |  |  | 			if (themetype == null) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				// fallback | 
		
	
		
			
				|  |  |  |  | 				page.ThemeType = Constants.DefaultTheme; | 
		
	
		
			
				|  |  |  |  | 				themetype = Type.GetType(Constants.DefaultTheme); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			if (themetype != null) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				var themeobject = Activator.CreateInstance(themetype) as IThemeControl; | 
		
	
		
			
				|  |  |  |  | 				if (themeobject != null) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					if (!string.IsNullOrEmpty(themeobject.Panes)) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						panes = themeobject.Panes; | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 					page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			if (!string.IsNullOrEmpty(panes)) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				page.Panes = panes.Replace(";", ",").Split(',', StringSplitOptions.RemoveEmptyEntries).ToList(); | 
		
	
		
			
				|  |  |  |  | 				if (!page.Panes.Contains(PaneNames.Default) && !page.Panes.Contains(PaneNames.Admin)) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					_error = "The Current Theme Does Not Contain A Default Or Admin Pane"; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			else | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				page.Panes.Add(PaneNames.Admin); | 
		
	
		
			
				|  |  |  |  | 				_error = "The Current Theme Does Not Contain Any Panes"; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		catch | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			// error loading theme or layout | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |             // get theme resources | 
		
	
		
			
				|  |  |  |  |             var theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == page.ThemeType)); | 
		
	
		
			
				|  |  |  |  |             if (theme != null) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 page.Resources = ManagePageResources(page.Resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName)); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		return page; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |             string panes = ""; | 
		
	
		
			
				|  |  |  |  |             Type themetype = Type.GetType(page.ThemeType); | 
		
	
		
			
				|  |  |  |  |             if (themetype == null) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 // fallback | 
		
	
		
			
				|  |  |  |  |                 page.ThemeType = Constants.DefaultTheme; | 
		
	
		
			
				|  |  |  |  |                 themetype = Type.GetType(Constants.DefaultTheme); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             if (themetype != null) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 var themeobject = Activator.CreateInstance(themetype) as IThemeControl; | 
		
	
		
			
				|  |  |  |  |                 if (themeobject != null) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     if (!string.IsNullOrEmpty(themeobject.Panes)) | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         panes = themeobject.Panes; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page, alias, "Themes", themetype.Namespace); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             if (!string.IsNullOrEmpty(panes)) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 page.Panes = panes.Replace(";", ",").Split(',', StringSplitOptions.RemoveEmptyEntries).ToList(); | 
		
	
		
			
				|  |  |  |  |                 if (!page.Panes.Contains(PaneNames.Default) && !page.Panes.Contains(PaneNames.Admin)) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     _error = "The Current Theme Does Not Contain A Default Or Admin Pane"; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             else | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 page.Panes.Add(PaneNames.Admin); | 
		
	
		
			
				|  |  |  |  |                 _error = "The Current Theme Does Not Contain Any Panes"; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         catch | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             // error loading theme or layout | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	private (Page Page, List<Module> Modules) ProcessModules(Page page, List<Module> modules, int moduleid, string action, string defaultcontainertype) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		var paneindex = new Dictionary<string, int>(); | 
		
	
		
			
				|  |  |  |  | 		foreach (Module module in modules) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			// initialize module control properties | 
		
	
		
			
				|  |  |  |  | 			module.SecurityAccessLevel = SecurityAccessLevel.Host; | 
		
	
		
			
				|  |  |  |  | 			module.ControlTitle = ""; | 
		
	
		
			
				|  |  |  |  | 			module.Actions = ""; | 
		
	
		
			
				|  |  |  |  | 			module.UseAdminContainer = false; | 
		
	
		
			
				|  |  |  |  | 			module.PaneModuleIndex = -1; | 
		
	
		
			
				|  |  |  |  | 			module.PaneModuleCount = 0; | 
		
	
		
			
				|  |  |  |  |         return page; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if ((module.PageId == page.PageId || module.ModuleId == moduleid)) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				var typename = Constants.ErrorModule; | 
		
	
		
			
				|  |  |  |  | 				if (module.ModuleDefinition != null && (module.ModuleDefinition.Runtimes == "" || module.ModuleDefinition.Runtimes.Contains(Runtime))) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					typename = module.ModuleDefinition.ControlTypeTemplate; | 
		
	
		
			
				|  |  |  |  |     private (Page Page, List<Module> Modules) ProcessModules(Page page, List<Module> modules, int moduleid, string action, string defaultcontainertype, Alias alias) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         var paneindex = new Dictionary<string, int>(); | 
		
	
		
			
				|  |  |  |  |         foreach (Module module in modules) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             // initialize module control properties | 
		
	
		
			
				|  |  |  |  |             module.SecurityAccessLevel = SecurityAccessLevel.Host; | 
		
	
		
			
				|  |  |  |  |             module.ControlTitle = ""; | 
		
	
		
			
				|  |  |  |  |             module.Actions = ""; | 
		
	
		
			
				|  |  |  |  |             module.UseAdminContainer = false; | 
		
	
		
			
				|  |  |  |  |             module.PaneModuleIndex = -1; | 
		
	
		
			
				|  |  |  |  |             module.PaneModuleCount = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					// handle default action | 
		
	
		
			
				|  |  |  |  | 					if (action == Constants.DefaultAction && !string.IsNullOrEmpty(module.ModuleDefinition.DefaultAction)) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						action = module.ModuleDefinition.DefaultAction; | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  |             if ((module.PageId == page.PageId || module.ModuleId == moduleid)) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 var typename = Constants.ErrorModule; | 
		
	
		
			
				|  |  |  |  |                 if (module.ModuleDefinition != null && (module.ModuleDefinition.Runtimes == "" || module.ModuleDefinition.Runtimes.Contains(Runtime))) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     typename = module.ModuleDefinition.ControlTypeTemplate; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					// check if the module defines custom action routes | 
		
	
		
			
				|  |  |  |  | 					if (module.ModuleDefinition.ControlTypeRoutes != "") | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						foreach (string route in module.ModuleDefinition.ControlTypeRoutes.Split(';', StringSplitOptions.RemoveEmptyEntries)) | 
		
	
		
			
				|  |  |  |  | 						{ | 
		
	
		
			
				|  |  |  |  | 							if (route.StartsWith(action + "=")) | 
		
	
		
			
				|  |  |  |  | 							{ | 
		
	
		
			
				|  |  |  |  | 								typename = route.Replace(action + "=", ""); | 
		
	
		
			
				|  |  |  |  | 							} | 
		
	
		
			
				|  |  |  |  | 						} | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |                     // handle default action | 
		
	
		
			
				|  |  |  |  |                     if (action == Constants.DefaultAction && !string.IsNullOrEmpty(module.ModuleDefinition.DefaultAction)) | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         action = module.ModuleDefinition.DefaultAction; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				// ensure component exists and implements IModuleControl | 
		
	
		
			
				|  |  |  |  | 				module.ModuleType = ""; | 
		
	
		
			
				|  |  |  |  | 				if (Constants.DefaultModuleActions.Contains(action, StringComparer.OrdinalIgnoreCase)) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, action); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				else | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					typename = typename.Replace(Constants.ActionToken, action); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				Type moduletype = Type.GetType(typename, false, true); // case insensitive | 
		
	
		
			
				|  |  |  |  | 				if (moduletype != null && moduletype.GetInterfaces().Contains(typeof(IModuleControl))) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					module.ModuleType = Utilities.GetFullTypeName(moduletype.AssemblyQualifiedName); // get actual type name | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |                     // check if the module defines custom action routes | 
		
	
		
			
				|  |  |  |  |                     if (module.ModuleDefinition.ControlTypeRoutes != "") | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         foreach (string route in module.ModuleDefinition.ControlTypeRoutes.Split(';', StringSplitOptions.RemoveEmptyEntries)) | 
		
	
		
			
				|  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |                             if (route.StartsWith(action + "=")) | 
		
	
		
			
				|  |  |  |  |                             { | 
		
	
		
			
				|  |  |  |  |                                 typename = route.Replace(action + "=", ""); | 
		
	
		
			
				|  |  |  |  |                             } | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				// get additional metadata from IModuleControl interface | 
		
	
		
			
				|  |  |  |  | 				if (moduletype != null && module.ModuleType != "") | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					// retrieve module component resources | 
		
	
		
			
				|  |  |  |  | 					var moduleobject = Activator.CreateInstance(moduletype) as IModuleControl; | 
		
	
		
			
				|  |  |  |  | 					page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module); | 
		
	
		
			
				|  |  |  |  | 					if (action.ToLower() == "settings" && module.ModuleDefinition != null) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						// settings components are embedded within a framework settings module | 
		
	
		
			
				|  |  |  |  | 						moduletype = Type.GetType(module.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, action), false, true); | 
		
	
		
			
				|  |  |  |  | 						if (moduletype != null) | 
		
	
		
			
				|  |  |  |  | 						{ | 
		
	
		
			
				|  |  |  |  | 							moduleobject = Activator.CreateInstance(moduletype) as IModuleControl; | 
		
	
		
			
				|  |  |  |  | 							page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module); | 
		
	
		
			
				|  |  |  |  | 						} | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  |                     // get module resources | 
		
	
		
			
				|  |  |  |  |                     page.Resources = ManagePageResources(page.Resources, module.ModuleDefinition.Resources, ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName)); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					// additional metadata needed for admin components | 
		
	
		
			
				|  |  |  |  | 					if (module.ModuleId == moduleid && action != "") | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						module.SecurityAccessLevel = moduleobject.SecurityAccessLevel; | 
		
	
		
			
				|  |  |  |  | 						module.ControlTitle = moduleobject.Title; | 
		
	
		
			
				|  |  |  |  | 						module.Actions = moduleobject.Actions; | 
		
	
		
			
				|  |  |  |  | 						module.UseAdminContainer = moduleobject.UseAdminContainer; | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |                 // ensure component exists and implements IModuleControl | 
		
	
		
			
				|  |  |  |  |                 module.ModuleType = ""; | 
		
	
		
			
				|  |  |  |  |                 if (Constants.DefaultModuleActions.Contains(action, StringComparer.OrdinalIgnoreCase)) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, action); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 else | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     typename = typename.Replace(Constants.ActionToken, action); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 Type moduletype = Type.GetType(typename, false, true); // case insensitive | 
		
	
		
			
				|  |  |  |  |                 if (moduletype != null && moduletype.GetInterfaces().Contains(typeof(IModuleControl))) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     module.ModuleType = Utilities.GetFullTypeName(moduletype.AssemblyQualifiedName); // get actual type name | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				// validate that module's pane exists in current page | 
		
	
		
			
				|  |  |  |  | 				if (page.Panes.FindIndex(item => item.Equals(module.Pane, StringComparison.OrdinalIgnoreCase)) == -1) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					// fallback to default pane if it exists | 
		
	
		
			
				|  |  |  |  | 					if (page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						module.Pane = PaneNames.Default; | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 					else // otherwise admin pane (legacy) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						module.Pane = PaneNames.Admin;						 | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |                 // get additional metadata from IModuleControl interface | 
		
	
		
			
				|  |  |  |  |                 if (moduletype != null && module.ModuleType != "") | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     // retrieve module component resources | 
		
	
		
			
				|  |  |  |  |                     var moduleobject = Activator.CreateInstance(moduletype) as IModuleControl; | 
		
	
		
			
				|  |  |  |  |                     page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules",  moduletype.Namespace); | 
		
	
		
			
				|  |  |  |  |                     if (action.ToLower() == "settings" && module.ModuleDefinition != null) | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         // settings components are embedded within a framework settings module | 
		
	
		
			
				|  |  |  |  |                         moduletype = Type.GetType(module.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, action), false, true); | 
		
	
		
			
				|  |  |  |  |                         if (moduletype != null) | 
		
	
		
			
				|  |  |  |  |                         { | 
		
	
		
			
				|  |  |  |  |                             moduleobject = Activator.CreateInstance(moduletype) as IModuleControl; | 
		
	
		
			
				|  |  |  |  |                             page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace); | 
		
	
		
			
				|  |  |  |  |                         } | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				// calculate module position within pane | 
		
	
		
			
				|  |  |  |  | 				if (paneindex.ContainsKey(module.Pane.ToLower())) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					paneindex[module.Pane.ToLower()] += 1; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				else | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					paneindex.Add(module.Pane.ToLower(), 0); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |                     // additional metadata needed for admin components | 
		
	
		
			
				|  |  |  |  |                     if (module.ModuleId == moduleid && action != "") | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         module.SecurityAccessLevel = moduleobject.SecurityAccessLevel; | 
		
	
		
			
				|  |  |  |  |                         module.ControlTitle = moduleobject.Title; | 
		
	
		
			
				|  |  |  |  |                         module.Actions = moduleobject.Actions; | 
		
	
		
			
				|  |  |  |  |                         module.UseAdminContainer = moduleobject.UseAdminContainer; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				module.PaneModuleIndex = paneindex[module.Pane.ToLower()]; | 
		
	
		
			
				|  |  |  |  |                 // validate that module's pane exists in current page | 
		
	
		
			
				|  |  |  |  |                 if (page.Panes.FindIndex(item => item.Equals(module.Pane, StringComparison.OrdinalIgnoreCase)) == -1) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     // fallback to default pane if it exists | 
		
	
		
			
				|  |  |  |  |                     if (page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1) | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         module.Pane = PaneNames.Default; | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                     else // otherwise admin pane (legacy) | 
		
	
		
			
				|  |  |  |  |                     { | 
		
	
		
			
				|  |  |  |  |                         module.Pane = PaneNames.Admin;						 | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				// container fallback | 
		
	
		
			
				|  |  |  |  | 				if (string.IsNullOrEmpty(module.ContainerType)) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					module.ContainerType = defaultcontainertype; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |                 // calculate module position within pane | 
		
	
		
			
				|  |  |  |  |                 if (paneindex.ContainsKey(module.Pane.ToLower())) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     paneindex[module.Pane.ToLower()] += 1; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 else | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     paneindex.Add(module.Pane.ToLower(), 0); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		foreach (Module module in modules.Where(item => item.PageId == page.PageId)) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (paneindex.ContainsKey(module.Pane.ToLower())) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				module.PaneModuleCount = paneindex[module.Pane.ToLower()] + 1; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |                 module.PaneModuleIndex = paneindex[module.Pane.ToLower()]; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		return (page, modules); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |                 // container fallback | 
		
	
		
			
				|  |  |  |  |                 if (string.IsNullOrEmpty(module.ContainerType)) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     module.ContainerType = defaultcontainertype; | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	private List<Resource> ManagePageResources(List<Resource> pageresources, List<Resource> resources, ResourceLevel level) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (resources != null) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			foreach (var resource in resources) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				// ensure resource does not exist already | 
		
	
		
			
				|  |  |  |  | 				if (pageresources.Find(item => item.Url == resource.Url) == null) | 
		
	
		
			
				|  |  |  |  | 				{ | 
		
	
		
			
				|  |  |  |  | 					resource.Level = level; | 
		
	
		
			
				|  |  |  |  |         foreach (Module module in modules.Where(item => item.PageId == page.PageId)) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             if (paneindex.ContainsKey(module.Pane.ToLower())) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 module.PaneModuleCount = paneindex[module.Pane.ToLower()] + 1; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         return (page, modules); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private List<Resource> ManagePageResources(List<Resource> pageresources, List<Resource> resources, ResourceLevel level, Alias alias, string type, string name) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         if (resources != null) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |             foreach (var resource in resources) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |                 if (!resource.Url.Contains("://") && resource.Url.StartsWith("~/")) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     // create local path | 
		
	
		
			
				|  |  |  |  |                     resource.Url = resource.Url.Replace("~", alias.BaseUrl + "/" + type + "/" + name); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |                 // ensure resource does not exist already | 
		
	
		
			
				|  |  |  |  |                 if (pageresources.Find(item => item.Url == resource.Url) == null) | 
		
	
		
			
				|  |  |  |  |                 { | 
		
	
		
			
				|  |  |  |  |                     resource.Level = level; | 
		
	
		
			
				|  |  |  |  | 					pageresources.Add(resource); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
	
		
			
				
					
					|  |  |  | 
 |