private void navigate( ResourceInfo destination, FullResponse secondaryResponse )
        {
            var requestState = AppRequestState.Instance.EwfPageRequestState;

            string destinationUrl;
            try {
                // Determine the final redirect destination. If a destination is already specified and it is the current page or a page with the same entity setup,
                // replace any default optional parameter values it may have with new values from this post back. If a destination isn't specified, make it the current
                // page with new parameter values from this post back. At the end of this block, redirectInfo is always newly created with fresh data that reflects any
                // changes that may have occurred in EH methods. It's important that every case below *actually creates* a new page info object to guard against this
                // scenario:
                // 1. A page modifies data such that a previously created redirect destination page info object that is then used here is no longer valid because it
                //    would throw an exception from init if it were re-created.
                // 2. The page redirects, or transfers, to this destination, leading the user to an error page without developers being notified. This is bad behavior.
                if( requestState.ModificationErrorsExist ||
                    ( requestState.DmIdAndSecondaryOp != null && requestState.DmIdAndSecondaryOp.Item2 == SecondaryPostBackOperation.NoOperation ) )
                    destination = InfoAsBaseType.CloneAndReplaceDefaultsIfPossible( true );
                else if( destination != null )
                    destination = destination.CloneAndReplaceDefaultsIfPossible( false );
                else
                    destination = createInfoFromNewParameterValues();

                // This GetUrl call is important even for the transfer case below for the same reason that we *actually create* a new page info object in every case
                // above. We want to force developers to get an error email if a page modifies data to make itself unauthorized/disabled without specifying a different
                // page as the redirect destination. The resulting transfer would lead the user to an error page.
                destinationUrl = destination.GetUrl();
            }
            catch( Exception e ) {
                throw getPossibleDeveloperMistakeException( "The post-modification destination page became invalid.", innerException: e );
            }

            // Put the secondary response into session state right before navigation so that it doesn't get sent if there is an error before this point.
            if( secondaryResponse != null ) {
                // It's important that we put the response in session state first since it's used by the Info.init method of the pre-built-response page.
                StandardLibrarySessionState.Instance.ResponseToSend = secondaryResponse;
                StandardLibrarySessionState.Instance.SetClientSideNavigation(
                    EwfApp.MetaLogicFactory.CreatePreBuiltResponsePageInfo().GetUrl(),
                    !secondaryResponse.FileName.Any(),
                    null );
            }

            // If the redirect destination is identical to the current page, do a transfer instead of a redirect.
            if( destination.IsIdenticalToCurrent() ) {
                AppRequestState.Instance.ClearUserAndImpersonator();
                resetPage();
            }

            // If the redirect destination is the current page, but with different query parameters, save request state in session state until the next request.
            if( destination.GetType() == InfoAsBaseType.GetType() )
                StandardLibrarySessionState.Instance.EwfPageRequestState = requestState;

            NetTools.Redirect( destinationUrl );
        }