Tracks when a person is viewed.
Inheritance: ITransaction
Exemple #1
0
        /// <summary>
        /// Loads all of the configured blocks for the current page into the control tree
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit( EventArgs e )
        {
            // Add the ScriptManager to each page
            _scriptManager = ScriptManager.GetCurrent( this.Page );

            if ( _scriptManager == null )
            {
                _scriptManager = new AjaxControlToolkit.ToolkitScriptManager { ID = "sManager" };
                Page.Trace.Warn( "Adding script manager" );
                Page.Form.Controls.AddAt( 0, _scriptManager );
            }

            // enable history on the ScriptManager
            _scriptManager.EnableHistory = true;

            // TODO: Delete this line, only used for testing
            _scriptManager.AsyncPostBackTimeout = 180;

            // wire up navigation event
            _scriptManager.Navigate += new EventHandler<HistoryEventArgs>( scriptManager_Navigate );

            // add ckeditor (doesn't like to be added during an async postback)
            _scriptManager.Scripts.Add( new ScriptReference( ResolveRockUrl( "~/Scripts/ckeditor/ckeditor.js", true ) ) );

            // Add library and UI bundles during init, that way theme developers will only
            // need to worry about registering any custom scripts or script bundles they need
            _scriptManager.Scripts.Add( new ScriptReference( "~/Bundles/WebFormsJs" ) );
            _scriptManager.Scripts.Add( new ScriptReference( "~/Scripts/Bundles/RockLibs" ) );
            _scriptManager.Scripts.Add( new ScriptReference( "~/Scripts/Bundles/RockUi" ) );
            _scriptManager.Scripts.Add( new ScriptReference( "~/Scripts/Bundles/RockValidation" ) );

            // add Google Maps API (doesn't like to be added during an async postback )
            var googleAPIKey = GlobalAttributesCache.Read().GetValue( "GoogleAPIKey" );
            string keyParameter = string.IsNullOrWhiteSpace(googleAPIKey) ? "" : string.Format("key={0}&", googleAPIKey);
            _scriptManager.Scripts.Add( new ScriptReference( string.Format( "https://maps.googleapis.com/maps/api/js?{0}sensor=false&libraries=drawing", keyParameter ) ) );

            // Recurse the page controls to find the rock page title and zone controls
            Page.Trace.Warn( "Recursing layout to find zones" );
            Zones = new Dictionary<string, KeyValuePair<string, Zone>>();
            FindRockControls( this.Controls );

            // Add a Rock version meta tag
            Page.Trace.Warn( "Adding Rock metatag" );
            string version = typeof( Rock.Web.UI.RockPage ).Assembly.GetName().Version.ToString();
            HtmlMeta rockVersion = new HtmlMeta();
            rockVersion.Attributes.Add( "name", "generator" );
            rockVersion.Attributes.Add( "content", string.Format( "Rock v{0}", version ) );
            AddMetaTag( this.Page, rockVersion );

            // If the logout parameter was entered, delete the user's forms authentication cookie and redirect them
            // back to the same page.
            Page.Trace.Warn( "Checking for logout request" );
            if ( PageParameter( "logout" ) != string.Empty )
            {
                if ( CurrentUser != null )
                {
                    var transaction = new Rock.Transactions.UserLastActivityTransaction();
                    transaction.UserId = CurrentUser.Id;
                    transaction.LastActivityDate = RockDateTime.Now;
                    transaction.IsOnLine = false;
                    Rock.Transactions.RockQueue.TransactionQueue.Enqueue( transaction );
                }

                FormsAuthentication.SignOut();

                // After logging out check to see if an anonymous user is allowed to view the current page.  If so
                // redirect back to the current page, otherwise redirect to the site's default page
                if ( _pageCache != null )
                {
                    if ( _pageCache.IsAuthorized( Authorization.VIEW, null ) )
                    {
                        // Remove the 'logout' queryparam before redirecting
                        var pageReference = new PageReference( PageReference.PageId, PageReference.RouteId, PageReference.Parameters );
                        foreach ( string key in PageReference.QueryString )
                        {
                            if ( !key.Equals( "logout", StringComparison.OrdinalIgnoreCase ) )
                            {
                                pageReference.Parameters.Add( key, PageReference.QueryString[key] );
                            }
                        }
                        Response.Redirect( pageReference.BuildUrl(), false );
                        Context.ApplicationInstance.CompleteRequest();
                    }
                    else
                    {
                        _pageCache.Layout.Site.RedirectToDefaultPage();
                    }
                    return;
                }
                else
                {
                    CurrentPerson = null;
                    CurrentUser = null;
                }
            }

            var rockContext = new RockContext();

            // If the impersonated query key was included then set the current person
            Page.Trace.Warn( "Checking for person impersanation" );
            string impersonatedPersonKey = PageParameter( "rckipid" );
            if ( !String.IsNullOrEmpty( impersonatedPersonKey ) )
            {
                Rock.Model.PersonService personService = new Model.PersonService( rockContext );
                Rock.Model.Person impersonatedPerson = personService.GetByEncryptedKey( impersonatedPersonKey );
                if ( impersonatedPerson != null )
                {
                    Rock.Security.Authorization.SetAuthCookie( "rckipid=" + impersonatedPerson.EncryptedKey, false, true );
                    CurrentUser = impersonatedPerson.GetImpersonatedUser();
                }
            }

            // Get current user/person info
            Page.Trace.Warn( "Getting CurrentUser" );
            Rock.Model.UserLogin user = CurrentUser;

            // If there is a logged in user, see if it has an associated Person Record.  If so, set the UserName to
            // the person's full name (which is then cached in the Session state for future page requests)
            if ( user != null )
            {
                Page.Trace.Warn( "Setting CurrentPerson" );
                UserName = user.UserName;
                int? personId = user.PersonId;

                if ( personId.HasValue )
                {
                    string personNameKey = "PersonName_" + personId.Value.ToString();
                    if ( Session[personNameKey] != null )
                    {
                        UserName = Session[personNameKey].ToString();
                    }
                    else
                    {
                        Rock.Model.PersonService personService = new Model.PersonService( rockContext );
                        Rock.Model.Person person = personService.Get( personId.Value );
                        if ( person != null )
                        {
                            UserName = person.FullName;
                            CurrentPerson = person;
                        }

                        Session[personNameKey] = UserName;
                    }
                }
            }

            // If a PageInstance exists
            if ( _pageCache != null )
            {
                BrowserTitle = _pageCache.BrowserTitle;
                PageTitle = _pageCache.PageTitle;
                PageIcon = _pageCache.IconCssClass;

                // If there's a master page, update it's reference to Current Page
                if ( this.Master is RockMasterPage )
                {
                    ( (RockMasterPage)this.Master ).SetPage( _pageCache );
                }

                // check if page should have been loaded via ssl
                Page.Trace.Warn( "Checking for SSL request" );
                if ( !Request.IsSecureConnection && _pageCache.RequiresEncryption )
                {
                    string redirectUrl = Request.Url.ToString().Replace( "http:", "https:" );
                    Response.Redirect( redirectUrl, false );
                    Context.ApplicationInstance.CompleteRequest();
                    return;
                }

                // Verify that the current user is allowed to view the page.
                Page.Trace.Warn( "Checking if user is authorized" );
                if ( !_pageCache.IsAuthorized( Authorization.VIEW, CurrentPerson ) )
                {
                    if ( user == null )
                    {
                        // If not authorized, and the user hasn't logged in yet, redirect to the login page
                        Page.Trace.Warn( "Redirecting to login page" );

                        var site = _pageCache.Layout.Site;
                        if ( site.LoginPageId.HasValue )
                        {
                            site.RedirectToLoginPage( true );
                        }
                        else
                        {
                            FormsAuthentication.RedirectToLoginPage();
                        }
                    }
                    else
                    {
                        // If not authorized, and the user has logged in, redirect to error page
                        Page.Trace.Warn( "Redirecting to error page" );

                        Response.Redirect( "~/error.aspx?type=security", false );
                        Context.ApplicationInstance.CompleteRequest();
                    }
                }
                else
                {
                    // Set current models (context)
                    Page.Trace.Warn( "Checking for Context" );
                    ModelContext = new Dictionary<string, Data.KeyEntity>();
                    try
                    {

                        // first search cookies, but pageContext can replace it
                        GetCookieContext( GetContextCookieName( false ) );      // Site
                        GetCookieContext( GetContextCookieName( true ) );       // Page (will replace any site values)

                        foreach ( var pageContext in _pageCache.PageContexts )
                        {
                            int? contextId = PageParameter( pageContext.Value ).AsIntegerOrNull();
                            if ( contextId.HasValue )
                            {
                                ModelContext.AddOrReplace( pageContext.Key, new Data.KeyEntity( contextId.Value ) );
                            }
                        }

                        char[] delim = new char[1] { ',' };
                        foreach ( string param in PageParameter( "context", true ).Split( delim, StringSplitOptions.RemoveEmptyEntries ) )
                        {
                            string contextItem = Rock.Security.Encryption.DecryptString( param );
                            string[] parts = contextItem.Split( '|' );
                            if ( parts.Length == 2 )
                            {
                                ModelContext.AddOrReplace( parts[0], new Data.KeyEntity( parts[1] ) );
                            }
                        }

                    }
                    catch
                    {
                        // intentionally ignore exception
                    }

                    // set viewstate on/off
                    this.EnableViewState = _pageCache.EnableViewState;

                    // Cache object used for block output caching
                    Page.Trace.Warn( "Getting memory cache" );
                    ObjectCache cache = MemoryCache.Default;

                    Page.Trace.Warn( "Checking if user can administer" );
                    bool canAdministratePage = _pageCache.IsAuthorized( Authorization.ADMINISTRATE, CurrentPerson );

                    // Create a javascript object to store information about the current page for client side scripts to use
                    Page.Trace.Warn( "Creating JS objects" );
                    string script = string.Format( @"
            Rock.settings.initialize({{
            siteId: {0},
            layoutId: {1},
            pageId: {2},
            layout: '{3}',
            baseUrl: '{4}'
            }});",
                        _pageCache.Layout.SiteId, _pageCache.LayoutId, _pageCache.Id, _pageCache.Layout.FileName, ResolveUrl( "~" ) );
                    ScriptManager.RegisterStartupScript( this.Page, this.GetType(), "rock-js-object", script, true );

                    AddTriggerPanel();

                    // Add config elements
                    if ( _pageCache.IncludeAdminFooter )
                    {
                        Page.Trace.Warn( "Adding popup controls (footer elements)" );
                        AddPopupControls();

                        Page.Trace.Warn( "Adding zone elements" );
                        AddZoneElements( canAdministratePage );
                    }

                    // Initialize the list of breadcrumbs for the current page (and blocks on the page)
                    Page.Trace.Warn( "Setting breadcrumbs" );
                    PageReference.BreadCrumbs = new List<BreadCrumb>();

                    // If the page is configured to display in the breadcrumbs...
                    string bcName = _pageCache.BreadCrumbText;
                    if ( bcName != string.Empty )
                    {
                        PageReference.BreadCrumbs.Add( new BreadCrumb( bcName, PageReference.BuildUrl() ) );
                    }

                    // Add the Google Analytics Code script if a code was specified for the site
                    if ( !string.IsNullOrWhiteSpace( _pageCache.Layout.Site.GoogleAnalyticsCode ) )
                    {
                        AddGoogleAnalytics( _pageCache.Layout.Site.GoogleAnalyticsCode );
                    }

                    // Flag indicating if user has rights to administer one or more of the blocks on page
                    bool canAdministrateBlock = false;

                    // Load the blocks and insert them into page zones
                    Page.Trace.Warn( "Loading Blocks" );
                    foreach ( Rock.Web.Cache.BlockCache block in _pageCache.Blocks )
                    {
                        Page.Trace.Warn( string.Format( "\tLoading '{0}' block", block.Name ) );

                        // Get current user's permissions for the block instance
                        Page.Trace.Warn( "\tChecking permission" );
                        bool canAdministrate = block.IsAuthorized( Authorization.ADMINISTRATE, CurrentPerson );
                        bool canEdit = block.IsAuthorized( Authorization.EDIT, CurrentPerson );
                        bool canView = block.IsAuthorized( Authorization.VIEW, CurrentPerson );

                        if ( canAdministrate || canEdit )
                        {
                            canAdministrateBlock = true;
                        }

                        // Make sure user has access to view block instance
                        if ( canAdministrate || canEdit || canView )
                        {
                            // Create block wrapper control (implements INamingContainer so child control IDs are unique for
                            // each block instance
                            Page.Trace.Warn( "\tAdding block wrapper html" );

                            HtmlGenericContainer blockWrapper = new HtmlGenericContainer( "div" );
                            blockWrapper.ID = string.Format( "bid_{0}", block.Id );
                            blockWrapper.Attributes.Add( "data-zone-location", block.BlockLocation.ToString() );
                            blockWrapper.ClientIDMode = ClientIDMode.Static;
                            FindZone( block.Zone ).Controls.Add( blockWrapper );

                            string blockTypeCss = block.BlockType != null ? block.BlockType.Name : "";
                            var parts = blockTypeCss.Split( new char[] { '>' } );
                            if ( parts.Length > 1 )
                            {
                                blockTypeCss = parts[parts.Length - 1].Trim();
                            }
                            blockTypeCss = blockTypeCss.Replace( ' ', '-' ).ToLower();

                            blockWrapper.Attributes.Add( "class", "block-instance " + blockTypeCss +
                                ( string.IsNullOrWhiteSpace( block.CssClass ) ? "" : " " + block.CssClass.Trim() ) +
                                ( canAdministrate || canEdit ? " can-configure " : "" ) );

                            // Check to see if block is configured to use a "Cache Duration'
                            string blockCacheKey = string.Format( "Rock:BlockOutput:{0}", block.Id );
                            if ( block.OutputCacheDuration > 0 && cache.Contains( blockCacheKey ) )
                            {
                                // If the current block exists in our custom output cache, add the cached output instead of adding the control
                                blockWrapper.Controls.Add( new LiteralControl( cache[blockCacheKey] as string ) );
                            }
                            else
                            {
                                // Load the control and add to the control tree
                                Page.Trace.Warn( "\tLoading control" );
                                Control control;

                                try
                                {
                                    control = TemplateControl.LoadControl( block.BlockType.Path );
                                    control.ClientIDMode = ClientIDMode.AutoID;
                                }
                                catch ( Exception ex )
                                {
                                    NotificationBox nbBlockLoad = new NotificationBox();
                                    nbBlockLoad.ID = string.Format( "nbBlockLoad_{0}", block.Id );
                                    nbBlockLoad.CssClass = "system-error";
                                    nbBlockLoad.NotificationBoxType = NotificationBoxType.Danger;
                                    nbBlockLoad.Text = string.Format( "Error Loading Block: {0}", block.Name );
                                    nbBlockLoad.Details = string.Format( "{0}<pre>{1}</pre>", ex.Message, ex.StackTrace );
                                    nbBlockLoad.Dismissable = true;
                                    control = nbBlockLoad;

                                    if ( this.IsPostBack )
                                    {
                                        // throw an error on PostBack so that the ErrorPage gets shown (vs nothing happening)
                                        throw ex;
                                    }
                                }

                                RockBlock blockControl = null;

                                // Check to see if the control was a PartialCachingControl or not
                                Page.Trace.Warn( "\tChecking block for partial caching" );
                                if ( control is RockBlock )
                                    blockControl = control as RockBlock;
                                else
                                {
                                    if ( control is PartialCachingControl && ( (PartialCachingControl)control ).CachedControl != null )
                                    {
                                        blockControl = (RockBlock)( (PartialCachingControl)control ).CachedControl;
                                    }
                                }

                                // If the current control is a block, set it's properties
                                if ( blockControl != null )
                                {
                                    Page.Trace.Warn( "\tSetting block properties" );

                                    blockControl.SetBlock( block );

                                    // Add any breadcrumbs to current page reference that the block creates
                                    Page.Trace.Warn( "\tAdding any breadcrumbs from block" );
                                    if ( block.BlockLocation == BlockLocation.Page )
                                    {
                                        blockControl.GetBreadCrumbs( PageReference ).ForEach( c => PageReference.BreadCrumbs.Add( c ) );
                                    }

                                    // If the blocktype's security actions have not yet been loaded, load them now
                                    if ( !block.BlockType.CheckedSecurityActions )
                                    {
                                        Page.Trace.Warn( "\tAdding additional security actions for blcok" );
                                        block.BlockType.SecurityActions = new Dictionary<string, string>();
                                        foreach ( var action in blockControl.GetSecurityActionAttributes() )
                                        {
                                            if ( block.BlockType.SecurityActions.ContainsKey( action.Key ) )
                                            {
                                                block.BlockType.SecurityActions[action.Key] = action.Value;
                                            }
                                            else
                                            {
                                                block.BlockType.SecurityActions.Add( action.Key, action.Value );
                                            }
                                        }
                                        block.BlockType.CheckedSecurityActions = true;
                                    }

                                    // If the block's AttributeProperty values have not yet been verified verify them.
                                    // (This provides a mechanism for block developers to define the needed block
                                    //  attributes in code and have them automatically added to the database)
                                    Page.Trace.Warn( "\tChecking if block attributes need refresh" );
                                    if ( !block.BlockType.IsInstancePropertiesVerified )
                                    {
                                        Page.Trace.Warn( "\tCreating block attributes" );
                                        blockControl.CreateAttributes( rockContext );
                                        block.BlockType.IsInstancePropertiesVerified = true;
                                    }

                                    // Add the block configuration scripts and icons if user is authorized
                                    if ( _pageCache.IncludeAdminFooter )
                                    {
                                        Page.Trace.Warn( "\tAdding block configuration tools" );
                                        AddBlockConfig( blockWrapper, blockControl, block, canAdministrate, canEdit );
                                    }
                                }

                                Page.Trace.Warn( "\tAdding block to control tree" );
                                HtmlGenericContainer blockContent = new HtmlGenericContainer( "div" );
                                blockContent.Attributes.Add( "class", "block-content" );
                                blockWrapper.Controls.Add( blockContent );

                                // Add the block
                                blockContent.Controls.Add( control );
                            }
                        }
                    }

                    // Make the last crumb for this page the active one
                    Page.Trace.Warn( "Setting active breadcrumb" );
                    if ( PageReference.BreadCrumbs.Any() )
                    {
                        PageReference.BreadCrumbs.Last().Active = true;
                    }

                    Page.Trace.Warn( "Getting parent page references" );
                    var pageReferences = PageReference.GetParentPageReferences( this, _pageCache, PageReference );
                    pageReferences.Add( PageReference );
                    PageReference.SavePageReferences( pageReferences );

                    // Update breadcrumbs
                    Page.Trace.Warn( "Updating breadcrumbs" );
                    BreadCrumbs = new List<BreadCrumb>();
                    foreach ( var pageReference in pageReferences )
                    {
                        pageReference.BreadCrumbs.ForEach( c => BreadCrumbs.Add( c ) );
                    }

                    // Add the page admin footer if the user is authorized to edit the page
                    if ( _pageCache.IncludeAdminFooter && ( canAdministratePage || canAdministrateBlock ) )
                    {
                        // Add the page admin script
                        AddScriptLink( Page, "~/Scripts/Bundles/RockAdmin", false );

                        Page.Trace.Warn( "Adding admin footer to page" );
                        HtmlGenericControl adminFooter = new HtmlGenericControl( "div" );
                        adminFooter.ID = "cms-admin-footer";
                        adminFooter.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                        this.Form.Controls.Add( adminFooter );

                        phLoadTime = new PlaceHolder();
                        adminFooter.Controls.Add( phLoadTime );

                        HtmlGenericControl buttonBar = new HtmlGenericControl( "div" );
                        adminFooter.Controls.Add( buttonBar );
                        buttonBar.Attributes.Add( "class", "button-bar" );

                        // RockBlock Config
                        HtmlGenericControl aBlockConfig = new HtmlGenericControl( "a" );
                        buttonBar.Controls.Add( aBlockConfig );
                        aBlockConfig.Attributes.Add( "class", "btn block-config" );
                        aBlockConfig.Attributes.Add( "href", "javascript: Rock.admin.pageAdmin.showBlockConfig();" );
                        aBlockConfig.Attributes.Add( "Title", "Block Configuration" );
                        HtmlGenericControl iBlockConfig = new HtmlGenericControl( "i" );
                        aBlockConfig.Controls.Add( iBlockConfig );
                        iBlockConfig.Attributes.Add( "class", "fa fa-th-large" );

                        if ( canAdministratePage )
                        {
                            // RockPage Properties
                            HtmlGenericControl aAttributes = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aAttributes );
                            aAttributes.ID = "aPageProperties";
                            aAttributes.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                            aAttributes.Attributes.Add( "class", "btn properties" );
                            aAttributes.Attributes.Add( "height", "500px" );
                            aAttributes.Attributes.Add( "href", "javascript: Rock.controls.modal.show($(this), '" + ResolveUrl( string.Format( "~/PageProperties/{0}?t=Page Properties", _pageCache.Id ) ) + "')" );
                            aAttributes.Attributes.Add( "Title", "Page Properties" );
                            HtmlGenericControl iAttributes = new HtmlGenericControl( "i" );
                            aAttributes.Controls.Add( iAttributes );
                            iAttributes.Attributes.Add( "class", "fa fa-cog" );

                            // Child Pages
                            HtmlGenericControl aChildPages = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aChildPages );
                            aChildPages.ID = "aChildPages";
                            aChildPages.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                            aChildPages.Attributes.Add( "class", "btn page-child-pages" );
                            aChildPages.Attributes.Add( "height", "500px" );
                            aChildPages.Attributes.Add( "href", "javascript: Rock.controls.modal.show($(this), '" + ResolveUrl( string.Format( "~/pages/{0}?t=Child Pages&pb=&sb=Done", _pageCache.Id ) ) + "')" );
                            aChildPages.Attributes.Add( "Title", "Child Pages" );
                            HtmlGenericControl iChildPages = new HtmlGenericControl( "i" );
                            aChildPages.Controls.Add( iChildPages );
                            iChildPages.Attributes.Add( "class", "fa fa-sitemap" );

                            // RockPage Zones
                            HtmlGenericControl aPageZones = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aPageZones );
                            aPageZones.Attributes.Add( "class", "btn page-zones" );
                            aPageZones.Attributes.Add( "href", "javascript: Rock.admin.pageAdmin.showPageZones();" );
                            aPageZones.Attributes.Add( "Title", "Page Zones" );
                            HtmlGenericControl iPageZones = new HtmlGenericControl( "i" );
                            aPageZones.Controls.Add( iPageZones );
                            iPageZones.Attributes.Add( "class", "fa fa-columns" );

                            // RockPage Security
                            HtmlGenericControl aPageSecurity = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aPageSecurity );
                            aPageSecurity.ID = "aPageSecurity";
                            aPageSecurity.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                            aPageSecurity.Attributes.Add( "class", "btn page-security" );
                            aPageSecurity.Attributes.Add( "height", "500px" );
                            aPageSecurity.Attributes.Add( "href", "javascript: Rock.controls.modal.show($(this), '" + ResolveUrl( string.Format( "~/Secure/{0}/{1}?t=Page Security&pb=&sb=Done",
                                EntityTypeCache.Read( typeof( Rock.Model.Page ) ).Id, _pageCache.Id ) ) + "')" );
                            aPageSecurity.Attributes.Add( "Title", "Page Security" );
                            HtmlGenericControl iPageSecurity = new HtmlGenericControl( "i" );
                            aPageSecurity.Controls.Add( iPageSecurity );
                            iPageSecurity.Attributes.Add( "class", "fa fa-lock" );

                            // System Info
                            HtmlGenericControl aSystemInfo = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aSystemInfo );
                            aSystemInfo.ID = "aSystemInfo";
                            aSystemInfo.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                            aSystemInfo.Attributes.Add( "class", "btn system-info" );
                            aSystemInfo.Attributes.Add( "height", "500px" );
                            aSystemInfo.Attributes.Add( "href", "javascript: Rock.controls.modal.show($(this), '" + ResolveUrl( "~/SystemInfo?t=System Information&pb=&sb=Done" ) + "')" );
                            aSystemInfo.Attributes.Add( "Title", "Rock Information" );
                            HtmlGenericControl iSystemInfo = new HtmlGenericControl( "i" );
                            aSystemInfo.Controls.Add( iSystemInfo );
                            iSystemInfo.Attributes.Add( "class", "fa fa-info-circle" );
                        }
                    }

                    // Check to see if page output should be cached.  The RockRouteHandler
                    // saves the PageCacheData information for the current page to memorycache
                    // so it should always exist
                    if ( _pageCache.OutputCacheDuration > 0 )
                    {
                        Response.Cache.SetCacheability( System.Web.HttpCacheability.Public );
                        Response.Cache.SetExpires( RockDateTime.Now.AddSeconds( _pageCache.OutputCacheDuration ) );
                        Response.Cache.SetValidUntilExpires( true );
                    }
                }

                string pageTitle = BrowserTitle;
                string siteTitle = _pageCache.Layout.Site.Name;
                string seperator = pageTitle.Trim() != string.Empty && siteTitle.Trim() != string.Empty ? " | " : "";

                base.Title = pageTitle + seperator + siteTitle;

                if ( !string.IsNullOrWhiteSpace( _pageCache.Description ) )
                {
                    HtmlMeta metaTag = new HtmlMeta();
                    metaTag.Attributes.Add( "name", "description" );
                    metaTag.Attributes.Add( "content", _pageCache.Description.Trim() );
                    AddMetaTag( this.Page, metaTag );
                }

                if ( !string.IsNullOrWhiteSpace( _pageCache.KeyWords ) )
                {
                    HtmlMeta metaTag = new HtmlMeta();
                    metaTag.Attributes.Add( "name", "keywords" );
                    metaTag.Attributes.Add( "content", _pageCache.KeyWords.Trim() );
                    AddMetaTag( this.Page, metaTag );
                }

                if ( !string.IsNullOrWhiteSpace( _pageCache.HeaderContent ) )
                {
                    Page.Header.Controls.Add( new LiteralControl( _pageCache.HeaderContent ) );
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Loads all of the configured blocks for the current page into the control tree
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit( EventArgs e )
        {
            var slDebugTimings = new StringBuilder();
            var stopwatchInitEvents = Stopwatch.StartNew();
            bool showDebugTimings = this.PageParameter( "ShowDebugTimings" ).AsBoolean();
            bool canAdministratePage = false;

            if ( showDebugTimings )
            {
                TimeSpan tsDuration = RockDateTime.Now.Subtract( (DateTime)Context.Items["Request_Start_Time"] );
                slDebugTimings.AppendFormat( "OnInit [{0}ms] @ {1} \n", stopwatchInitEvents.Elapsed.TotalMilliseconds, tsDuration.TotalMilliseconds );
                stopwatchInitEvents.Restart();
            }

            // Add the ScriptManager to each page
            _scriptManager = ScriptManager.GetCurrent( this.Page );

            if ( _scriptManager == null )
            {
                _scriptManager = new ScriptManager { ID = "sManager" };
                Page.Trace.Warn( "Adding script manager" );
                Page.Form.Controls.AddAt( 0, _scriptManager );
            }

            // enable history on the ScriptManager
            _scriptManager.EnableHistory = true;

            // TODO: Delete this line, only used for testing
            _scriptManager.AsyncPostBackTimeout = 180;

            // wire up navigation event
            _scriptManager.Navigate += new EventHandler<HistoryEventArgs>( scriptManager_Navigate );

            // Add library and UI bundles during init, that way theme developers will only
            // need to worry about registering any custom scripts or script bundles they need
            _scriptManager.Scripts.Add( new ScriptReference( "~/Bundles/WebFormsJs" ) );
            _scriptManager.Scripts.Add( new ScriptReference( "~/Scripts/Bundles/RockLibs" ) );
            _scriptManager.Scripts.Add( new ScriptReference( "~/Scripts/Bundles/RockUi" ) );
            _scriptManager.Scripts.Add( new ScriptReference( "~/Scripts/Bundles/RockValidation" ) );

            // Recurse the page controls to find the rock page title and zone controls
            Page.Trace.Warn( "Recursing layout to find zones" );
            Zones = new Dictionary<string, KeyValuePair<string, Zone>>();
            FindRockControls( this.Controls );

            // Add a Rock version meta tag
            Page.Trace.Warn( "Adding Rock metatag" );
            string version = typeof( Rock.Web.UI.RockPage ).Assembly.GetName().Version.ToString();
            HtmlMeta rockVersion = new HtmlMeta();
            rockVersion.Attributes.Add( "name", "generator" );
            rockVersion.Attributes.Add( "content", string.Format( "Rock v{0}", version ) );
            AddMetaTag( this.Page, rockVersion );

            if ( showDebugTimings )
            {
                slDebugTimings.AppendFormat( "CheckingForLogout [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                stopwatchInitEvents.Restart();
            }

            // If the logout parameter was entered, delete the user's forms authentication cookie and redirect them
            // back to the same page.
            Page.Trace.Warn( "Checking for logout request" );
            if ( PageParameter( "logout" ) != string.Empty )
            {
                if ( CurrentUser != null )
                {
                    var transaction = new Rock.Transactions.UserLastActivityTransaction();
                    transaction.UserId = CurrentUser.Id;
                    transaction.LastActivityDate = RockDateTime.Now;
                    transaction.IsOnLine = false;
                    Rock.Transactions.RockQueue.TransactionQueue.Enqueue( transaction );
                }

                FormsAuthentication.SignOut();

                // After logging out check to see if an anonymous user is allowed to view the current page.  If so
                // redirect back to the current page, otherwise redirect to the site's default page
                if ( _pageCache != null )
                {
                    if ( _pageCache.IsAuthorized( Authorization.VIEW, null ) )
                    {
                        // Remove the 'logout' queryparam before redirecting
                        var pageReference = new PageReference( PageReference.PageId, PageReference.RouteId, PageReference.Parameters );
                        foreach ( string key in PageReference.QueryString )
                        {
                            if ( !key.Equals( "logout", StringComparison.OrdinalIgnoreCase ) )
                            {
                                pageReference.Parameters.Add( key, PageReference.QueryString[key] );
                            }
                        }
                        Response.Redirect( pageReference.BuildUrl(), false );
                        Context.ApplicationInstance.CompleteRequest();
                    }
                    else
                    {
                        _pageCache.Layout.Site.RedirectToDefaultPage();
                    }
                    return;
                }
                else
                {
                    CurrentPerson = null;
                    CurrentUser = null;
                }
            }

            var rockContext = new RockContext();

            if ( showDebugTimings )
            {
                slDebugTimings.AppendFormat( "CreateRockContext [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                stopwatchInitEvents.Restart();
            }

            // If the impersonated query key was included then set the current person
            Page.Trace.Warn( "Checking for person impersanation" );
            string impersonatedPersonKey = PageParameter( "rckipid" );
            if ( !String.IsNullOrEmpty( impersonatedPersonKey ) )
            {
                Rock.Model.PersonService personService = new Model.PersonService( rockContext );

                Rock.Model.Person impersonatedPerson = personService.GetByEncryptedKey( impersonatedPersonKey );
                if ( impersonatedPerson == null )
                {
                    impersonatedPerson = personService.GetByUrlEncodedKey( impersonatedPersonKey );
                }
                if ( impersonatedPerson != null )
                {
                    Rock.Security.Authorization.SetAuthCookie( "rckipid=" + impersonatedPerson.EncryptedKey, false, true );
                    CurrentUser = impersonatedPerson.GetImpersonatedUser();
                }
            }

            // Get current user/person info
            Page.Trace.Warn( "Getting CurrentUser" );
            Rock.Model.UserLogin user = CurrentUser;

            if ( showDebugTimings )
            {
                slDebugTimings.AppendFormat( "GetCurrentUser [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                stopwatchInitEvents.Restart();
            }

            // If there is a logged in user, see if it has an associated Person Record.  If so, set the UserName to
            // the person's full name (which is then cached in the Session state for future page requests)
            if ( user != null )
            {
                Page.Trace.Warn( "Setting CurrentPerson" );
                UserName = user.UserName;
                int? personId = user.PersonId;

                if ( personId.HasValue )
                {
                    string personNameKey = "PersonName_" + personId.Value.ToString();
                    if ( Session[personNameKey] != null )
                    {
                        UserName = Session[personNameKey].ToString();
                    }
                    else
                    {
                        Rock.Model.PersonService personService = new Model.PersonService( rockContext );
                        Rock.Model.Person person = personService.Get( personId.Value );
                        if ( person != null )
                        {
                            UserName = person.FullName;
                            CurrentPerson = person;
                        }

                        Session[personNameKey] = UserName;
                    }
                }

                if ( showDebugTimings )
                {
                    slDebugTimings.AppendFormat( "GetCurrentPerson [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                    stopwatchInitEvents.Restart();
                }

                // check that they aren't required to change their password
                if ( user.IsPasswordChangeRequired == true && Site.ChangePasswordPageReference != null )
                {
                    // don't redirect if this is the change password page
                    if ( Site.ChangePasswordPageReference.PageId != this.PageId )
                    {
                        Site.RedirectToChangePasswordPage( true, true );
                    }
                }
            }

            // If a PageInstance exists
            if ( _pageCache != null )
            {
                BrowserTitle = _pageCache.BrowserTitle;
                PageTitle = _pageCache.PageTitle;
                PageIcon = _pageCache.IconCssClass;
                BodyCssClass = _pageCache.BodyCssClass;

                // If there's a master page, update its reference to Current Page
                if ( this.Master is RockMasterPage )
                {
                    ( (RockMasterPage)this.Master ).SetPage( _pageCache );
                }

                // Add CSS class to body
                if ( !string.IsNullOrWhiteSpace( this.BodyCssClass ) )
                {
                    // attempt to find the body tag
                    var body = (HtmlGenericControl)this.Master.FindControl( "body" );
                    if ( body != null )
                    {
                        body.Attributes.Add( "class", this.BodyCssClass );
                    }
                }

                // check if page should have been loaded via ssl
                Page.Trace.Warn( "Checking for SSL request" );
                if ( !Request.IsSecureConnection && (_pageCache.RequiresEncryption || Site.RequiresEncryption) )
                {
                    string redirectUrl = Request.Url.ToString().Replace( "http:", "https:" );
                    Response.Redirect( redirectUrl, false );
                    Context.ApplicationInstance.CompleteRequest();
                    return;
                }

                // Verify that the current user is allowed to view the page.
                Page.Trace.Warn( "Checking if user is authorized" );

                var isCurrentPersonAuthorized = _pageCache.IsAuthorized( Authorization.VIEW, CurrentPerson );

                if ( showDebugTimings )
                {
                    slDebugTimings.AppendFormat( "isCurrentPersonAuthorized [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                    stopwatchInitEvents.Restart();
                }

                if ( !isCurrentPersonAuthorized )
                {
                    if ( user == null )
                    {
                        // If not authorized, and the user hasn't logged in yet, redirect to the login page
                        Page.Trace.Warn( "Redirecting to login page" );

                        var site = _pageCache.Layout.Site;
                        if ( site.LoginPageId.HasValue )
                        {
                            site.RedirectToLoginPage( true );
                        }
                        else
                        {
                            FormsAuthentication.RedirectToLoginPage();
                        }
                    }
                    else
                    {
                        // If not authorized, and the user has logged in, redirect to error page
                        Page.Trace.Warn( "Redirecting to error page" );

                        Response.Redirect( "~/Error.aspx?type=security", false );
                        Context.ApplicationInstance.CompleteRequest();
                    }
                }
                else
                {
                    // Set current models (context)
                    Page.Trace.Warn( "Checking for Context" );
                    ModelContext = new Dictionary<string, Data.KeyEntity>();
                    try
                    {
                        char[] delim = new char[1] { ',' };

                        // Check to see if a context from query string should be saved to a cookie first
                        foreach ( string param in PageParameter( "SetContext", true ).Split( delim, StringSplitOptions.RemoveEmptyEntries ) )
                        {
                            string[] parts = param.Split( '|' );
                            if ( parts.Length == 2 )
                            {
                                var contextModelEntityType = EntityTypeCache.Read( parts[0], false, rockContext );
                                int? contextId = parts[1].AsIntegerOrNull();

                                if ( contextModelEntityType != null && contextId.HasValue )
                                {
                                    var contextModelType = contextModelEntityType.GetEntityType();
                                    var contextDbContext = Reflection.GetDbContextForEntityType( contextModelType );
                                    if ( contextDbContext != null )
                                    {
                                        var contextService = Reflection.GetServiceForEntityType( contextModelType, contextDbContext );
                                        if ( contextService != null )
                                        {
                                            MethodInfo getMethod = contextService.GetType().GetMethod( "Get", new Type[] { typeof( int ) } );
                                            if ( getMethod != null )
                                            {
                                                var getResult = getMethod.Invoke( contextService, new object[] { contextId.Value } );
                                                var contextEntity = getResult as IEntity;
                                                if ( contextEntity != null )
                                                {
                                                    SetContextCookie( contextEntity, false, false );
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if ( showDebugTimings )
                        {
                            slDebugTimings.AppendFormat( "Set Page Context(s) [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                            stopwatchInitEvents.Restart();
                        }

                        // first search the cookies for any saved context, but pageContext can replace it
                        GetCookieContext( GetContextCookieName( false ) );      // Site
                        GetCookieContext( GetContextCookieName( true ) );       // Page (will replace any site values)

                        // check for page context
                        foreach ( var pageContext in _pageCache.PageContexts )
                        {
                            int? contextId = PageParameter( pageContext.Value ).AsIntegerOrNull();
                            if ( contextId.HasValue )
                            {
                                ModelContext.AddOrReplace( pageContext.Key, new Data.KeyEntity( contextId.Value ) );
                            }
                        }

                        // check for any encrypted contextkeys specified in query string
                        foreach ( string param in PageParameter( "context", true ).Split( delim, StringSplitOptions.RemoveEmptyEntries ) )
                        {
                            string contextItem = Rock.Security.Encryption.DecryptString( param );
                            string[] parts = contextItem.Split( '|' );
                            if ( parts.Length == 2 )
                            {
                                ModelContext.AddOrReplace( parts[0], new Data.KeyEntity( parts[1] ) );
                            }
                        }

                        if ( showDebugTimings )
                        {
                            slDebugTimings.AppendFormat( "Check Page Context(s) [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                            stopwatchInitEvents.Restart();
                        }

                    }
                    catch
                    {
                        // intentionally ignore exception
                    }

                    // set viewstate on/off
                    this.EnableViewState = _pageCache.EnableViewState;

                    Page.Trace.Warn( "Checking if user can administer" );
                    canAdministratePage = _pageCache.IsAuthorized( Authorization.ADMINISTRATE, CurrentPerson );

                    if ( showDebugTimings )
                    {
                        slDebugTimings.AppendFormat( "canAdministratePage [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                        stopwatchInitEvents.Restart();
                    }

                    // Create a javascript object to store information about the current page for client side scripts to use
                    Page.Trace.Warn( "Creating JS objects" );
                    if ( !ClientScript.IsStartupScriptRegistered( "rock-js-object" ) )
                    {
                        string script = string.Format( @"
            Rock.settings.initialize({{
            siteId: {0},
            layoutId: {1},
            pageId: {2},
            layout: '{3}',
            baseUrl: '{4}'
            }});",
                            _pageCache.Layout.SiteId, _pageCache.LayoutId, _pageCache.Id, _pageCache.Layout.FileName, ResolveUrl( "~" ) );

                        ClientScript.RegisterStartupScript( this.Page.GetType(), "rock-js-object", script, true );
                    }

                    AddTriggerPanel();

                    // Add config elements
                    if ( _pageCache.IncludeAdminFooter )
                    {
                        Page.Trace.Warn( "Adding popup controls (footer elements)" );
                        AddPopupControls();

                        Page.Trace.Warn( "Adding zone elements" );
                        AddZoneElements( canAdministratePage );
                    }

                    // Initialize the list of breadcrumbs for the current page (and blocks on the page)
                    Page.Trace.Warn( "Setting breadcrumbs" );
                    PageReference.BreadCrumbs = new List<BreadCrumb>();

                    // If the page is configured to display in the breadcrumbs...
                    string bcName = _pageCache.BreadCrumbText;
                    if ( bcName != string.Empty )
                    {
                        PageReference.BreadCrumbs.Add( new BreadCrumb( bcName, PageReference.BuildUrl() ) );
                    }

                    // Add the Google Analytics Code script if a code was specified for the site
                    if ( !string.IsNullOrWhiteSpace( _pageCache.Layout.Site.GoogleAnalyticsCode ) )
                    {
                        AddGoogleAnalytics( _pageCache.Layout.Site.GoogleAnalyticsCode );
                    }

                    // Flag indicating if user has rights to administer one or more of the blocks on page
                    bool canAdministrateBlockOnPage = false;

                    if ( showDebugTimings )
                    {
                        slDebugTimings.AppendFormat( "start loading blocks [{0}ms]\n", stopwatchInitEvents.Elapsed.TotalMilliseconds );
                        stopwatchInitEvents.Restart();
                    }

                    // Load the blocks and insert them into page zones
                    Page.Trace.Warn( "Loading Blocks" );
                    var pageBlocks = _pageCache.Blocks;
                    foreach ( Rock.Web.Cache.BlockCache block in pageBlocks )
                    {
                        var stopwatchBlockInit= Stopwatch.StartNew();
                        Page.Trace.Warn( string.Format( "\tLoading '{0}' block", block.Name ) );

                        // Get current user's permissions for the block instance
                        Page.Trace.Warn( "\tChecking permission" );
                        bool canAdministrate = block.IsAuthorized( Authorization.ADMINISTRATE, CurrentPerson );
                        bool canEdit = block.IsAuthorized( Authorization.EDIT, CurrentPerson );
                        bool canView = block.IsAuthorized( Authorization.VIEW, CurrentPerson );

                        // Make sure user has access to view block instance
                        if ( canAdministrate || canEdit || canView )
                        {

                            // Load the control and add to the control tree
                            Page.Trace.Warn( "\tLoading control" );
                            Control control = null;

                            // Check to see if block is configured to use a "Cache Duration'
                            if ( block.OutputCacheDuration > 0 )
                            {
                                // Cache object used for block output caching
                                Page.Trace.Warn( "Getting memory cache" );
                                RockMemoryCache cache = RockMemoryCache.Default;
                                string blockCacheKey = string.Format( "Rock:BlockOutput:{0}", block.Id );
                                if ( cache.Contains( blockCacheKey ) )
                                {
                                    // If the current block exists in our custom output cache, add the cached output instead of adding the control
                                    control = new LiteralControl( cache[blockCacheKey] as string );
                                }
                            }

                            if ( control == null )
                            {
                                try
                                {
                                    control = TemplateControl.LoadControl( block.BlockType.Path );
                                    control.ClientIDMode = ClientIDMode.AutoID;
                                }
                                catch ( Exception ex )
                                {
                                    NotificationBox nbBlockLoad = new NotificationBox();
                                    nbBlockLoad.ID = string.Format( "nbBlockLoad_{0}", block.Id );
                                    nbBlockLoad.CssClass = "system-error";
                                    nbBlockLoad.NotificationBoxType = NotificationBoxType.Danger;
                                    nbBlockLoad.Text = string.Format( "Error Loading Block: {0}", block.Name );
                                    nbBlockLoad.Details = string.Format( "{0}<pre>{1}</pre>", HttpUtility.HtmlEncode( ex.Message ), HttpUtility.HtmlEncode( ex.StackTrace ) );
                                    nbBlockLoad.Dismissable = true;
                                    control = nbBlockLoad;

                                    if ( this.IsPostBack )
                                    {
                                        // throw an error on PostBack so that the ErrorPage gets shown (vs nothing happening)
                                        throw;
                                    }
                                }
                            }

                            if ( control != null )
                            {
                                if ( canAdministrate || ( canEdit && control is RockBlockCustomSettings ) )
                                {
                                    canAdministrateBlockOnPage = true;
                                }

                                // If the current control is a block, set its properties
                                var blockControl = control as RockBlock;
                                if ( blockControl != null )
                                {
                                    Page.Trace.Warn( "\tSetting block properties" );
                                    blockControl.SetBlock( _pageCache, block, canEdit, canAdministrate );
                                    control = new RockBlockWrapper( blockControl );

                                    // Add any breadcrumbs to current page reference that the block creates
                                    Page.Trace.Warn( "\tAdding any breadcrumbs from block" );
                                    if ( block.BlockLocation == BlockLocation.Page )
                                    {
                                        blockControl.GetBreadCrumbs( PageReference ).ForEach( c => PageReference.BreadCrumbs.Add( c ) );
                                    }

                                    // If the blocktype's security actions have not yet been loaded, load them now
                                    block.BlockType.SetSecurityActions( blockControl );

                                    // If the block's AttributeProperty values have not yet been verified verify them.
                                    // (This provides a mechanism for block developers to define the needed block
                                    //  attributes in code and have them automatically added to the database)
                                    Page.Trace.Warn( "\tChecking if block attributes need refresh" );
                                    if ( !block.BlockType.IsInstancePropertiesVerified )
                                    {
                                        Page.Trace.Warn( "\tCreating block attributes" );
                                        if ( blockControl.CreateAttributes( rockContext ) )
                                        {
                                            // If attributes were updated, update the block attributes for all blocks in page of same type
                                            pageBlocks
                                                .Where( b => b.BlockTypeId == block.BlockTypeId )
                                                .ToList()
                                                .ForEach( b => b.ReloadAttributeValues() );
                                        }
                                        block.BlockType.IsInstancePropertiesVerified = true;
                                    }

                                }

                            }

                            FindZone( block.Zone ).Controls.Add( control );
                            if ( control is RockBlockWrapper )
                            {
                                ( (RockBlockWrapper)control ).EnsureBlockControls();
                            }

                            if ( showDebugTimings )
                            {
                                stopwatchBlockInit.Stop();
                                slDebugTimings.AppendFormat(
                                    "create/init block {0} <span class='label label-{2}'>[{1}ms]</span>\n",
                                    block.Name,
                                    stopwatchBlockInit.Elapsed.TotalMilliseconds,
                                    stopwatchBlockInit.Elapsed.TotalMilliseconds > 500 ? "danger" : "info");
                            }
                        }
                    }

                    // Make the last crumb for this page the active one
                    Page.Trace.Warn( "Setting active breadcrumb" );
                    if ( PageReference.BreadCrumbs.Any() )
                    {
                        PageReference.BreadCrumbs.Last().Active = true;
                    }

                    Page.Trace.Warn( "Getting parent page references" );
                    var pageReferences = PageReference.GetParentPageReferences( this, _pageCache, PageReference );
                    pageReferences.Add( PageReference );
                    PageReference.SavePageReferences( pageReferences );

                    // Update breadcrumbs
                    Page.Trace.Warn( "Updating breadcrumbs" );
                    BreadCrumbs = new List<BreadCrumb>();
                    foreach ( var pageReference in pageReferences )
                    {
                        pageReference.BreadCrumbs.ForEach( c => BreadCrumbs.Add( c ) );
                    }

                    // Add the page admin footer if the user is authorized to edit the page
                    if ( _pageCache.IncludeAdminFooter && ( canAdministratePage || canAdministrateBlockOnPage ) )
                    {
                        // Add the page admin script
                        AddScriptLink( Page, "~/Scripts/Bundles/RockAdmin", false );

                        Page.Trace.Warn( "Adding admin footer to page" );
                        HtmlGenericControl adminFooter = new HtmlGenericControl( "div" );
                        adminFooter.ID = "cms-admin-footer";
                        adminFooter.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                        this.Form.Controls.Add( adminFooter );

                        phLoadStats = new PlaceHolder();
                        adminFooter.Controls.Add( phLoadStats );

                        HtmlGenericControl buttonBar = new HtmlGenericControl( "div" );
                        adminFooter.Controls.Add( buttonBar );
                        buttonBar.Attributes.Add( "class", "button-bar" );

                        // RockBlock Config
                        HtmlGenericControl aBlockConfig = new HtmlGenericControl( "a" );
                        buttonBar.Controls.Add( aBlockConfig );
                        aBlockConfig.Attributes.Add( "class", "btn block-config" );
                        aBlockConfig.Attributes.Add( "href", "javascript: Rock.admin.pageAdmin.showBlockConfig();" );
                        aBlockConfig.Attributes.Add( "Title", "Block Configuration" );
                        HtmlGenericControl iBlockConfig = new HtmlGenericControl( "i" );
                        aBlockConfig.Controls.Add( iBlockConfig );
                        iBlockConfig.Attributes.Add( "class", "fa fa-th-large" );

                        if ( canAdministratePage )
                        {
                            // RockPage Properties
                            HtmlGenericControl aAttributes = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aAttributes );
                            aAttributes.ID = "aPageProperties";
                            aAttributes.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                            aAttributes.Attributes.Add( "class", "btn properties" );
                            aAttributes.Attributes.Add( "height", "500px" );
                            aAttributes.Attributes.Add( "href", "javascript: Rock.controls.modal.show($(this), '" + ResolveUrl( string.Format( "~/PageProperties/{0}?t=Page Properties", _pageCache.Id ) ) + "')" );
                            aAttributes.Attributes.Add( "Title", "Page Properties" );
                            HtmlGenericControl iAttributes = new HtmlGenericControl( "i" );
                            aAttributes.Controls.Add( iAttributes );
                            iAttributes.Attributes.Add( "class", "fa fa-cog" );

                            // Child Pages
                            HtmlGenericControl aChildPages = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aChildPages );
                            aChildPages.ID = "aChildPages";
                            aChildPages.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                            aChildPages.Attributes.Add( "class", "btn page-child-pages" );
                            aChildPages.Attributes.Add( "height", "500px" );
                            aChildPages.Attributes.Add( "href", "javascript: Rock.controls.modal.show($(this), '" + ResolveUrl( string.Format( "~/pages/{0}?t=Child Pages&pb=&sb=Done", _pageCache.Id ) ) + "')" );
                            aChildPages.Attributes.Add( "Title", "Child Pages" );
                            HtmlGenericControl iChildPages = new HtmlGenericControl( "i" );
                            aChildPages.Controls.Add( iChildPages );
                            iChildPages.Attributes.Add( "class", "fa fa-sitemap" );

                            // RockPage Zones
                            HtmlGenericControl aPageZones = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aPageZones );
                            aPageZones.Attributes.Add( "class", "btn page-zones" );
                            aPageZones.Attributes.Add( "href", "javascript: Rock.admin.pageAdmin.showPageZones();" );
                            aPageZones.Attributes.Add( "Title", "Page Zones" );
                            HtmlGenericControl iPageZones = new HtmlGenericControl( "i" );
                            aPageZones.Controls.Add( iPageZones );
                            iPageZones.Attributes.Add( "class", "fa fa-columns" );

                            // RockPage Security
                            HtmlGenericControl aPageSecurity = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aPageSecurity );
                            aPageSecurity.ID = "aPageSecurity";
                            aPageSecurity.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                            aPageSecurity.Attributes.Add( "class", "btn page-security" );
                            aPageSecurity.Attributes.Add( "height", "500px" );
                            aPageSecurity.Attributes.Add( "href", "javascript: Rock.controls.modal.show($(this), '" + ResolveUrl( string.Format( "~/Secure/{0}/{1}?t=Page Security&pb=&sb=Done",
                                EntityTypeCache.Read( typeof( Rock.Model.Page ) ).Id, _pageCache.Id ) ) + "')" );
                            aPageSecurity.Attributes.Add( "Title", "Page Security" );
                            HtmlGenericControl iPageSecurity = new HtmlGenericControl( "i" );
                            aPageSecurity.Controls.Add( iPageSecurity );
                            iPageSecurity.Attributes.Add( "class", "fa fa-lock" );

                            // System Info
                            HtmlGenericControl aSystemInfo = new HtmlGenericControl( "a" );
                            buttonBar.Controls.Add( aSystemInfo );
                            aSystemInfo.ID = "aSystemInfo";
                            aSystemInfo.ClientIDMode = System.Web.UI.ClientIDMode.Static;
                            aSystemInfo.Attributes.Add( "class", "btn system-info" );
                            aSystemInfo.Attributes.Add( "height", "500px" );
                            aSystemInfo.Attributes.Add( "href", "javascript: Rock.controls.modal.show($(this), '" + ResolveUrl( "~/SystemInfo?t=System Information&pb=&sb=Done" ) + "')" );
                            aSystemInfo.Attributes.Add( "Title", "Rock Information" );
                            HtmlGenericControl iSystemInfo = new HtmlGenericControl( "i" );
                            aSystemInfo.Controls.Add( iSystemInfo );
                            iSystemInfo.Attributes.Add( "class", "fa fa-info-circle" );
                        }
                    }

                    // Check to see if page output should be cached.  The RockRouteHandler
                    // saves the PageCacheData information for the current page to memorycache
                    // so it should always exist
                    if ( _pageCache.OutputCacheDuration > 0 )
                    {
                        Response.Cache.SetCacheability( System.Web.HttpCacheability.Public );
                        Response.Cache.SetExpires( RockDateTime.Now.AddSeconds( _pageCache.OutputCacheDuration ) );
                        Response.Cache.SetValidUntilExpires( true );
                    }

                    // create a page view transaction if enabled
                    if ( !Page.IsPostBack && _pageCache != null )
                    {
                        if ( _pageCache.Layout.Site.EnablePageViews )
                        {
                            PageViewTransaction transaction = new PageViewTransaction();
                            transaction.DateViewed = RockDateTime.Now;
                            transaction.PageId = _pageCache.Id;
                            transaction.SiteId = _pageCache.Layout.Site.Id;
                            if ( CurrentPersonAlias != null )
                            {
                                transaction.PersonAliasId = CurrentPersonAlias.Id;
                            }

                            transaction.IPAddress = GetClientIpAddress();
                            transaction.UserAgent = Request.UserAgent ?? "";
                            transaction.Url = Request.Url.ToString();
                            transaction.PageTitle = _pageCache.PageTitle;
                            var sessionId = Session["RockSessionID"];
                            if ( sessionId != null )
                            {
                                transaction.SessionId = sessionId.ToString();
                            }

                            RockQueue.TransactionQueue.Enqueue( transaction );
                        }
                    }
                }

                stopwatchInitEvents.Restart();

                string pageTitle = BrowserTitle ?? string.Empty;
                string siteTitle = _pageCache.Layout.Site.Name;
                string seperator = pageTitle.Trim() != string.Empty && siteTitle.Trim() != string.Empty ? " | " : "";

                base.Title = pageTitle + seperator + siteTitle;

                if ( !string.IsNullOrWhiteSpace( _pageCache.Description ) )
                {
                    HtmlMeta metaTag = new HtmlMeta();
                    metaTag.Attributes.Add( "name", "description" );
                    metaTag.Attributes.Add( "content", _pageCache.Description.Trim() );
                    AddMetaTag( this.Page, metaTag );
                }

                if ( !string.IsNullOrWhiteSpace( _pageCache.KeyWords ) )
                {
                    HtmlMeta metaTag = new HtmlMeta();
                    metaTag.Attributes.Add( "name", "keywords" );
                    metaTag.Attributes.Add( "content", _pageCache.KeyWords.Trim() );
                    AddMetaTag( this.Page, metaTag );
                }

                if (!string.IsNullOrWhiteSpace( _pageCache.Layout.Site.PageHeaderContent ))
                {
                    Page.Header.Controls.Add( new LiteralControl( _pageCache.Layout.Site.PageHeaderContent ) );
                }

                if ( !string.IsNullOrWhiteSpace( _pageCache.HeaderContent ) )
                {
                    Page.Header.Controls.Add( new LiteralControl( _pageCache.HeaderContent ) );
                }

                if ( !_pageCache.AllowIndexing || !_pageCache.Layout.Site.AllowIndexing )
                {
                    Page.Header.Controls.Add( new LiteralControl( "<meta name=\"robots\" content=\"noindex, nofollow\"/>" ) );
                }

                if ( showDebugTimings )
                {
                    TimeSpan tsDuration = RockDateTime.Now.Subtract( (DateTime)Context.Items["Request_Start_Time"] );
                    slDebugTimings.AppendFormat( "done oninit [{0}ms] @ {1} \n", stopwatchInitEvents.Elapsed.TotalMilliseconds, tsDuration.TotalMilliseconds );
                    stopwatchInitEvents.Restart();
                }

                if ( showDebugTimings && canAdministratePage )
                {
                    Page.Form.Controls.Add( new Label
                    {
                        ID="lblShowDebugTimings",
                        Text = string.Format( "<pre>{0}</pre>", slDebugTimings.ToString() )
                    } );
                }
            }
        }