Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
SergioFerrari
Active Contributor
0 Kudos

Introduction


Who never got the following message using the BACK Button to resume the last visited page?
<<I>"Warning: Page has Expired. The page you requested was created using information you submitted in a form.
This page is no longer available. As a security precaution, Internet Explorer does not automatically resubmit your information for you.

To resubmit your information and view this Web page, click the Refresh button. "


>  Users do not like that warning page and me too   <

I recently worked on the

BACK Navigation

in a project where a great B2B Portal has been created via a custom BSP application designed according to the MVC pattern.
I discovered some helpful settings, JavaScript statements and finally I implemented the new powerful BSP TAG &LT;zbn:DisableBackNavigation&GT;.
OK, now let's go into technical details:


APPROACH 1 - SETTINGS - Tuning cache settings

Via SE80 it is possible to specify caching parameters on each controller.

An example:

The first thing to know is that the "Page has Expired" warning page is generated by the browser only if Browser or Server cache value is not set.
>  No cache, then get "Warning: Page has Expired. ...".   <

Are you working with

stateless

applications? If yes, set the Browser cache to 3600 and skip the rest of the Blog.
If not, it's a pity. You are not so lucky. Wait before setting

statefull

applications to use cache.
You will solve the "Page has Expired" problem but you will you introduce even a worst problem.


>  Statefull application with cache, then get the client (Browser) to be NOT synchronized with the server (BSP application) <
Let me explain: let's take a shopping cart application.
The collection of items in the cart will be maintained in an ABAP internal table binded in the cart view. Then, if a user perform a BACK Navigation he/she will see a previous cart; different items will be displayed in the browser then what are in the ABAP table.
I don't want to think what will happen if an action is requested for an item that is no more in the cart (add_item(1),add_item(2),drop_item(1),BACK Navigation, BACK Navigation, update_item(1))...


APPROACH 2 - SETTINGS - Hiding BACK Button to the user


In order to avoid BACK Navigation problem, it would be nice to disable the BACK command on the browser.
Too easy. Life is not so.
You could start your application in a new window disabling the all the browser's buttons.


>  Statefull application in a window without buttons - If your users like it... <
Please note that

right-clicking

on the page the Back command is still there..

In any case, in order to disable the Backspace Navigation,

>  do not forget to make use of the &LT;htmlb:document disableBackspaceNavigation="TRUE"&GT; <




APPROACH 3 - JAVASCRIPT - An easy and powerful solution


A simple JavaScript function may be coded in your BSP in order to disable the BACK Navigation.

>  With <B>history.forward()</B>, BACK Navigation is no more a Nightmare <

Picture - BSP Extension - DisableBackspaceNavigation

Picture - BSP Extension - DisableBackspaceNavigation - Attributes

Picture - BSP Extension - Class - Attribute

Picture - BSP Extension - Class - Methods

DO_AT_BEGINNING source code:


Version improved by Mario Vangerven (it uses a cookie):


returnlinkgenerate.

    WHEN 'TRUE'.

  •     Get returnPage

      DATA: l_return_page TYPE string.

      DATA: o_http_request_warning_page TYPE REF TO if_http_request.

      o_http_request_warning_page = me->m_page_context->get_request( ).

      l_return_page = o_http_request_warning_page->if_http_entity~get_form_field( name = 'returnPage' ).

  •     Render A HREF TAG

      CONCATENATE html cl_abap_char_utilities=>cr_lf 'Server Step Id:  ' me->server_step_id ' '');'
cl_abap_char_utilities=>cr_lf '' cl_abap_char_utilities=>cr_lf
INTO html.
CONCATENATE html cl_abap_char_utilities=>cr_lf
''
''');' cl_abap_char_utilities=>cr_lf
'document.write(''

'');' cl_abap_char_utilities=>cr_lf
'document.write(''' me->returnlinktext ''');' cl_abap_char_utilities=>cr_lf
'document.write(''

'');' cl_abap_char_utilities=>cr_lf
'' cl_abap_char_utilities=>cr_lf
'' cl_abap_char_utilities=>cr_lf
INTO html.
WHEN OTHERS.
CASE me->type.

  • Render client-side Java Script function history.forward()

        WHEN 'CLIENT'.

          CONCATENATE html cl_abap_char_utilities=>cr_lf

          'Server Step Id:  ' me->server_step_id ' '');' cl_abap_char_utilities=>cr_lf
'' cl_abap_char_utilities=>cr_lf
INTO html.
CONCATENATE html cl_abap_char_utilities=>cr_lf
'' cl_abap_char_utilities=>cr_lf
'' cl_abap_char_utilities=>cr_lf
'' cl_abap_char_utilities=>cr_lf

  • Get AgentStepId

          INTO html.

        WHEN 'SERVER'.

  • Get the cookie from the root path

  • => now we can even jump from one application to the other and still disable the back button

          DATA: o_http_request TYPE REF TO if_http_request.

          o_http_request = me->m_page_context->get_request( ).

          CALL METHOD o_http_request->if_http_entity~get_cookie

            EXPORTING

              name  = 'AgentStepId'

              path  = '/'

            IMPORTING

  • Calculate ServerStepId

              value = me->agent_step_id.

          DATA: l_server_step_id_int TYPE i.

          DATA: l_server_step_id_str TYPE string.

          IF me->agent_step_id IS INITIAL.

            me->server_step_id = '0'.

          ELSE.

            IF me->agent_step_id > me->server_step_id.

              me->server_step_id = me->agent_step_id.

              ADD 1 TO me->server_step_id.

            ELSE.

              me->server_step_id = me->agent_step_id.

              ADD 1 TO me->server_step_id.

  • Render complex client-side Java Script function

            ENDIF.

          ENDIF.

  • me->agent_step_id = o_http_request->if_http_entity~get_form_field( name = 'AgentStepId' ).

          DATA: o_bsp_runtime TYPE REF TO if_bsp_runtime.

          o_bsp_runtime = me->m_page_context->get_runtime( ).

          CONCATENATE html cl_abap_char_utilities=>cr_lf

          '' cl_abap_char_utilities=>cr_lf
''
INTO html.
CONCATENATE html cl_abap_char_utilities=>cr_lf
'Server Step Id:  ' me->server_step_id ' '');'

  • Set the cookie from the root path

  • => now we can even jump from one application to the other and still disable the back button

cl_abap_char_utilities=>cr_lf
'jsv_cookie = "AgentStepId="+history.length+"; path=/";' cl_abap_char_utilities=>cr_lf

          'document.cookie=jsv_cookie' cl_abap_char_utilities=>cr_lf

          '' cl_abap_char_utilities=>cr_lf
'' cl_abap_char_utilities=>cr_lf
INTO html.
ENDCASE.
ENDCASE.
*
prev_out->print_string( html ).
*
rc = co_element_continue.


ENDMETHOD.

  • Replace &LT; with <

  • Replace &GT; with &GT;

  • that because in the weblog special characters are not fully supported in the text

Version without cookie:


*!!!!!!!! ATTENTION !!!!!!!!!*

********************************

METHOD if_bsp_element~do_at_beginning .

  DATA: html     TYPE string.

  DATA: prev_out TYPE REF TO if_bsp_writer.

  •     Get returnPage

  prev_out = me-&GT;get_previous_out( ).

  CASE me-&GT;returnlinkgenerate.

    WHEN 'TRUE'.

      DATA: l_return_page               TYPE string.

  •     Render A HREF TAG

      DATA: o_http_request_warning_page TYPE REF TO if_http_request.

      o_http_request_warning_page = me-&GT;m_page_context-&GT;get_request( ).

      l_return_page = o_http_request_warning_page-&GT;if_http_entity~get_form_field( name  =  'returnPage' ).

      CONCATENATE html cl_abap_char_utilities=&GT;cr_lf

            '&LT;script&GT;' cl_abap_char_utilities=&GT;cr_lf

             'document.write(''&LT;B&GT;Server Step Id: &LT;/B&GT; ' me-&GT;server_step_id '&LT;/br&GT;'');' cl_abap_char_utilities=&GT;cr_lf

            '&LT;/script&GT;' cl_abap_char_utilities=&GT;cr_lf

             INTO html.

      CONCATENATE html cl_abap_char_utilities=&GT;cr_lf

        '&LT;!-- DisableBackNavigation Extension - Begin --!&GT;'

        '&LT;script language=JavaScript&GT;' cl_abap_char_utilities=&GT;cr_lf

         'document.write(''&LT;form method="POST" name="formWBN" action="'  l_return_page '"&GT;'');' cl_abap_char_utilities=&GT;cr_lf

         'document.write(''&LT;input name="AgentStepId" type="HIDDEN" value="''+history.length+''"/&GT;'');' cl_abap_char_utilities=&GT;cr_lf

         'document.write(''&LT;A HREF="javascript:void(document.formWBN.submit())"&GT;' me-&GT;returnlinktext '&LT;/A&GT;'');' cl_abap_char_utilities=&GT;cr_lf

         'document.write(''&LT;/form&GT;'');' cl_abap_char_utilities=&GT;cr_lf

        '&LT;/script&GT;' cl_abap_char_utilities=&GT;cr_lf

        '&LT;!-- DisableBackNavigation Extension - End   --!&GT;' cl_abap_char_utilities=&GT;cr_lf

             INTO html.

  •         Render client-side Java Script function history.forward()

    WHEN OTHERS.

      CASE me-&GT;type.

        WHEN 'CLIENT'.

          CONCATENATE html cl_abap_char_utilities=&GT;cr_lf

                '&LT;script&GT;' cl_abap_char_utilities=&GT;cr_lf

                 'document.write(''&LT;B&GT;Server Step Id: &LT;/B&GT; ' me-&GT;server_step_id '&LT;/br&GT;'');' cl_abap_char_utilities=&GT;cr_lf

                '&LT;/script&GT;' cl_abap_char_utilities=&GT;cr_lf

                 INTO html.

          CONCATENATE html cl_abap_char_utilities=&GT;cr_lf

            '&LT;!-- DisableBackNavigation Extension - Begin --!&GT;' cl_abap_char_utilities=&GT;cr_lf

            '&LT;script language=JavaScript&GT;' cl_abap_char_utilities=&GT;cr_lf

            'history.forward();' cl_abap_char_utilities=&GT;cr_lf

            '&LT;/script&GT;' cl_abap_char_utilities=&GT;cr_lf

  •         Get AgentStepId

            '&LT;!-- DisableBackNavigation Extension - End   --!&GT;' cl_abap_char_utilities=&GT;cr_lf

                 INTO html.

        WHEN 'SERVER'.

  •         Calculate ServerStepId

          DATA: o_http_request TYPE REF TO if_http_request.

          o_http_request = me-&GT;m_page_context-&GT;get_request( ).

          me-&GT;agent_step_id = o_http_request-&GT;if_http_entity~get_form_field( name  =  'AgentStepId' ).

          DATA: l_server_step_id_int TYPE i.

          DATA: l_server_step_id_str TYPE string.

          IF me-&GT;agent_step_id IS INITIAL.

            me-&GT;server_step_id = '0'.

          ELSE.

            IF me-&GT;agent_step_id &GT; me-&GT;server_step_id.

              me-&GT;server_step_id = me-&GT;agent_step_id.

              ADD 1 TO me-&GT;server_step_id.

            ELSE.

              me-&GT;server_step_id = me-&GT;agent_step_id.

  •         Render complex client-side Java Script function

              ADD 1 TO me-&GT;server_step_id.

            ENDIF.

  •          me-&GT;agent_step_id = o_http_request-&GT;if_http_entity~get_form_field( name  =  'AgentStepId' ).

          ENDIF.

          DATA: o_bsp_runtime TYPE REF TO if_bsp_runtime.

          o_bsp_runtime = me-&GT;m_page_context-&GT;get_runtime( ).

          CONCATENATE html cl_abap_char_utilities=&GT;cr_lf

            '&LT;!-- DisableBackNavigation Extension - Begin --!&GT;' cl_abap_char_utilities=&GT;cr_lf

            '&LT;script language=JavaScript&GT;' cl_abap_char_utilities=&GT;cr_lf

            ' if (' me-&GT;server_step_id '&GT;0)' cl_abap_char_utilities=&GT;cr_lf

            '  {' cl_abap_char_utilities=&GT;cr_lf

            '   if (history.length&LT;' me-&GT;server_step_id ')' cl_abap_char_utilities=&GT;cr_lf

            '    history.forward();' cl_abap_char_utilities=&GT;cr_lf

            '   else ' cl_abap_char_utilities=&GT;cr_lf

            '    {' cl_abap_char_utilities=&GT;cr_lf

            '     if (history.length&GT;' me-&GT;server_step_id ')' cl_abap_char_utilities=&GT;cr_lf

            '      {' cl_abap_char_utilities=&GT;cr_lf

            '       location.href=''' me-&GT;warningpage '?returnPage=' o_bsp_runtime-&GT;page_name ''';' cl_abap_char_utilities=&GT;cr_lf

            '      }' cl_abap_char_utilities=&GT;cr_lf

            '    }' cl_abap_char_utilities=&GT;cr_lf

            '  }' cl_abap_char_utilities=&GT;cr_lf

            '&LT;/script&GT;'

                 INTO html.

          CONCATENATE html cl_abap_char_utilities=&GT;cr_lf

            '&LT;script language=JavaScript&GT;' cl_abap_char_utilities=&GT;cr_lf

             'document.write(''&LT;B&GT;Server Step Id: &LT;/B&GT; ' me-&GT;server_step_id '&LT;/br&GT;'');' cl_abap_char_utilities=&GT;cr_lf

             'document.write(''&LT;input name="AgentStepId" type="HIDDEN" value="''history.length''"/&GT;'');' cl_abap_char_utilities=&GT;cr_lf

            '&LT;/script&GT;' cl_abap_char_utilities=&GT;cr_lf

            '&LT;!-- DisableBackNavigation Extension - End   --!&GT;' cl_abap_char_utilities=&GT;cr_lf

                 INTO html.

      ENDCASE.

  ENDCASE.

*

  prev_out-&GT;print_string( html ).

*

  rc = co_element_continue.

*

ENDMETHOD.



A SAMPLE APPLICATION

Create a statefull BSP application:

Picture - Web application

Create following controllers:

Picture - Controller for the client implementation

Picture - Controller for the Server implementation

Picture - Controller for the warning Page

Create following views:

mainClientimplementation.htm

That's all.

5 Comments