"First they will ignore you, then they will laugh at you,  then they will fight you, then you will win."
- Mahatma Gandhi

Wednesday, November 19, 2008
       
  
Blogs

Search Blogs

Details about PRG
Location: BlogsDoug's Blog   
Posted by: Doug.Danoff3/13/2007

One of my 2 readers, Steve Morse, asked a question about my post about the back button.

"A common pattern is "post backs" to the same page as a user interacts with the page. For example, the page displays a list with details of a selected item below. When a user clicks a list item it posts back, and the page now displays the details below. This is standard .ASPX with "view state". Are you saying there is something wrong with this technique?"

My other reader, Dave Sweeny, asked me to explain a bit more.

Being happy I have readers, I’ll try to take it down a level.

Steve, I think your scenario is this

  1. Page displays a list, with the content area of the page empty
  2. User clicks item in the list
  3. Browser posts back
  4. Server uses some form field to determine what to display, fills in the content with that item, and returns the page

I created a simple asp.net web project to show highlight what I think the problem is.

Our Form
SamplePostbackForm.JPG

The class behind our form
protected void Page_Load(object sender, EventArgs e)
{

    // These lines force pages to not cache.  Server is requested

    // for every display.  This is generally considered to

    // be normal PRG practice due to the nature of these apps.

    // It also helps to highlight the issue.  It is not

    // required by PRG

    Response.Cache.SetExpires(DateTime.Now);

    Response.Cache.SetCacheability(HttpCacheability.NoCache);

 

    // If this was a GET, determine the correct item

    // to display.  If it was a post, the item is displayed

    // another way.

    if ((this.IsPostBack == false)

        && (Request.QueryString["index"] != null))

    {

        int i = int.Parse(Request.QueryString["index"]);

        TextBox1.Text = "PRG-" + ListBox1.Items[i];

        ListBox1.SelectedIndex = i;

    }

}

protected void btnPRG_Click(object sender, EventArgs e)

{

    // The PRG approach sends a redirect request as a

    // result of the PRG Button POST

    Response.Redirect("default.aspx?index="

        + ListBox1.SelectedIndex);

}

protected void btnPF_Click(object sender, EventArgs e)

{

    // The PF approach (which is clouded by ASP.NET)

    // forwards to the same page.

    if (ListBox1.SelectedItem != null)

        TextBox1.Text = "PF-" + ListBox1.SelectedItem.Text;

    else

        TextBox1.Text = "PF-Nothing Selected";

}

 

Explained
Select any 3 items from the list, and hit either Post/Forward or Post/Redirect/Get.  Both accomplish the same thing with the different strategies: the text box is filled in with the value of the selected item on the server and an updated page is returned to the browser.

Since caching is turned off, when you use the browser controls to navigate around, the server is asked for a fresh version of the page every time the page is selected thru a back or forward button.  Note, you get the same symptoms with cache enabled if you back button then refresh.

Now play with it
First start with the PF button.  Select an item, hit PF, repeat.  Now start playing with the back button.  You get the trusty “Page Is Expired” error advising you to hit the refresh button. 
PageExpiredImage.JPG

When you do, you get a message box you get another cryptic message warning you about a resubmit and to be careful if you were trying to buy something.
ResubmitMessage.JPG

I agree.  If you were trying to buy something from this site, you should be very, very careful.

Next try playing with the PRG button.  Again, select an item, hit PRG, repeat enough times to clear your way past the nasty PF junk.  You should notice that the URL now indicates what you are looking at (it didn’t with PF).  Back button, Forward button, Refresh…   NO PROBLEMS!  You can even bookmark the URL and come back!

Google works this way too.  When you search Google, they redirect the URL back to you.  I would not be able to post this link if they used PF.

http://www.google.com/search?hl=en&q=www.strong-point.com

Conclusion
The problem I have with Steve’s scenario is not that it does not work.  It does work.  The problem I have with it is that it causes unexpected things to happen when the browser navigation controls are used.  It is heavily dependent on the sequence of actions performed by the user.

With PRG, browser navigation happens more easily.  As you can see, it is just as easy to code with PRG as it is with PF.  When you factor in all of the things you must do to prevent potential problems caused by PF…   there is no contest, PRG is easier.

The warning messages received during the PF scenarios are just the tip of the iceberg.  Much more serious problems can arise than just these messages.

References
In creating this response, I used this very good explanation of web caching.
http://www.mnot.net/cache_docs/#CONTROL

Permalink | Trackback

Comments (7)  Add Comment
Re: Details about PRG  By Steve.Morse on 3/13/2007
Ok. I understand what you are doing. It doesn't really work well with anything beyond the simplest ASP.NET web form however. Not passing judgement...maybe the way ASP.NET was designed is crap. But the reality is that Microsoft designed ASP.NET to present a development pattern similar to building a windows form where the "Viewstate" is managed for you. To do what you are suggesting you are essentially required to do an end run around this convenience by redirecting the browser back to the same form with all "Viewstate" as part of the querystring.

Re: Details about PRG  By Doug.Danoff on 3/13/2007
PRG doesn't require all viewstate to be passed on the querystring. Most of these apps have some form of persistence on the server: database, session, etc. The querystring only needs to pass the keys for that state.
I suppose PRG doesn’t work well when there is no server state. But in the complex apps you are talking about, PF won’t work none to good neither. In fact, in researching this problem, there are some show-stopper issues with passing viewstate between pages on the server.
Your best bet for complex is to keep business data state on the server… even if only in a WIP (work in process) area in serialize blob form… and have your URL’s request that data by key.

Re: Details about PRG  By Steve.Morse on 3/13/2007
I agree. ASP.NET keeps viewstate in a form field however.

Re: Details about PRG  By Doug.Danoff on 3/13/2007
Not sure what your point is there.

But, I do see a problem with Mantra... related to your issue. Viewstate comes in handy when a post is rejected (due to validation errors of something) and the user is given a chance to correct the problems. If the data is never applied to the model, that data is lost upon redirect.

There might need to be an exception for that. PRG is still essential for pages transfers, but a postback without successful model change... I need to think on that.

Re: Details about PRG  By Steve.Morse on 3/13/2007
My point is simply that it is difficult to do what you are describing because ASP.NET persists viewstate to a form field not in "some form of persistence on the server".

Re: Details about PRG  By Doug.Danoff on 3/14/2007
Yeah, but only for the life of a single page. Help me out here. Give me a scenario I can sink my teeth into.

Re: Details about PRG  By Vladimir Kelman on 8/29/2008
As I said in your previous post, I always consider this issue as MAJOR FLAW of ASP.NET WebForm paradigm, which makes it barely usable. It's a shame, considering an excellent .NET platform and C# language. Does anyone found the way to marry ASP.NET WebForm/ server-side controls model with PRG?
There are some tricks with using ASP.NET AJAX (Update Panel) to avoid page POST operation altogether, while keeping WebForm/ server-side controls model, but it is often overcomplicated...
MVC (ASP.NET MVC) would be a solution. I know...

Vladimir Kelman
http://www.pro-thoughts.blogspot.com/


Your name:
Title:
Comment:
Add Comment  Cancel 
Contact Information

Strong Point Consulting LLC is located in Malden, MA.

Contact us via
Contact@strong-point.com
A Senior Technologist will respond promptly.


Privacy Statement  |  Terms Of UseCopyright 2007 Strong Point Consulting LLC