views:

135

answers:

4

I'm currently involved in an ASP.NET project where I need to restrict the users ability to go back in the page structure using the back button. It is essentially a wizard style navigation and I don't want to give the user the ability to go back from the last step and re-submit the data. JavaScript is not an option unfortunately, so I "solved" it by setting the HttpCacheability in every pages Load event to NoCache. This gives the user the "Page expired" page when he or she clicks the back button. It isn't very elegant at all, and I'm wondering what other options I have to achive the desired results.

+1  A: 

It's not possible. Even if you get it working in internet explorer in Firefox it will not work.

The only way to handle this is you need to handle saving the state of a users step in either their session, database etc and then when they submit verify that they are submitting on the correct step.

Chris Marisic
I have created a separate class which I store in a strongly typed session that has a previous page property so that navigation is only allowed between certain steps, and not just jumping in anywhere without completing the required stepd.
daft
The issue is if the user uses firefox you will get no events fired when they use the back button because it uses perfect in memory caching that it will not fire an expired page event or pageload event so even with your custom class it won't do anything unless you verify on the submits where they are currently and where you expect them to be.
Chris Marisic
Thanks Chris, I have now surrendered to the idea that i have to let the page display old data when the back button is hit. They can't, as I originally stated in my post, be sent again since the cached data that has been collected from the user is cleared once the user gets to the last step. I could get around by simply clearing out the form before redirecting to the last page.
daft
+2  A: 

Keep the navigation state on the server side, and if the user hits a page that doesn't correspond with a next/prev click, redirect them to where they were supposed to be.

Rytmis
+2  A: 

Only expose one URL for your entire wizard. The step displayed will depend on session state, which can store what steps they have already completed.

That way there is no "invalid" URL for the user to load.

You should probably consider creating a UserControl for each step. You then place all the steps on a single .aspx page and show and hide them as appropriate.

ctford
This is the way I need to go I think. I need to expand the current functionality instead of altering the browser's base functionality, as Matt discourages below. Thanks all.
daft
If your wizard uses full postbacks this isn't a viable solution, you can still use the back button to redo posting data. If you run an ajax application, this is viable.
Chris Marisic
I'm not certain why full postbacks would matter. With the step information stored in session, the code would always be able to determine what step the user should be on.
Jason Berkan
My point was if he was trying to use his state saving functionality to determine which user controls are displayed the back button will still allow the user to have access to the previous controls so my point stands that you need to verify their current step vs where they're supposed to be on every postback.
Chris Marisic
+2  A: 

The short answer is "you can't." Because it's browser-side functionality, any method to do this will be via something exposed by the browser, which means it's trivially defeatable. The long answer is you don't want to. This creates usability issues (any changes to normal browser behavior is undesired). I would suggest using a session cookie to determine where in the process they should be and issue a 302 redirect to the appropriate page if they try to access the wrong page of the process (prior to processing any GET/POST data as well as discarding any data they may have been submitting). Trying to defeat the users by altering how the browser's base functionality works will always lead to headaches.

Matt