views:

568

answers:

6

I’m using the PRG pattern to avoid multiple form submission. It has, however, a serious drawback — you cannot simply echo the confirmation message to the user (obviously, the user won’t see the page, he will be redirected to another one).

What are the solutions to this problem? I know two of them, but none of them seems perfect.

  • Use a custom redirect URL, like: http://example.com/?msg=data-saved. It’s stateless, so I think it’s quite reliable. But it creates problems when user copies the link, bookmarks it, etc.
  • Store a session variable/cookie, and check it on every page load. If it’s set, clear it and display the message. It seems OK, but I’m not sure about this one — it relies strongly on cookies, it’s a little more complicated.

Or maybe there are other ways I don’t know about? Some combination of sessions and URL parameters? Dunno.

What’s the best way in your opinion? Which one has the least drawbacks? What are the pros and cons?

+1  A: 

I use the session variable method. I don't really like embedding error messages for display in the URL, especially with the URL-saving/sharing issues you note, and I like that if the user reloads the destination page it'll be a clean instance.

chaos
+1  A: 

It depends on what platform you're running on.

Ruby on Rails calls this flash[:notice] = "Your action was performed", ASP.NET MVC calls this TempData["notice"] = "Your action was performed"...

Basically they just store data in HttpSession for a single round trip only. This way you can retrieve data on another web request.

Ben Scheirman
In other words, the framework often takes your 2nd suggestion of using a session data store linked to a cookie.
Eli
+4  A: 

There are several other stack overflow questions that touch on this, though I don't think any summarize the problem so clearly. Here are a few:

Most of the convenient solutions are session-based or have more serious drawbacks (such as embedding the message in the querystring).

If you cannot guarantee that you'll have sessions, another (quite costly) method is to redirect to different views depending on the outcome of the form submission. For example, you might redirect to EditWidgetView, EditWidgetSaveSuccessfulView, or EditWidgetSaveErrorView (or perhaps you just don't redirect on errors). In some languages and frameworks, this is impractical to the point of making you give up on showing confirmation / error messages at all, but in others it may be worth it.

Jeff Sternal
+1  A: 

Pretty much every website that allows users to log in does so by relying on a cookie. It ain't a perfect solution, but it's the best we got.

Also session handling is one of those things that a web development framework typically takes care of for you.

Eli
+2  A: 

If you don't want to rely on sessions for whatever reason you could use a Get variable / custom url and then if that variable is present, check the refer. If the refer is proper, then display the message. Yes, this adds reliance on refers being sent in order to show the confirmation message, but otherwise you're relying on sessions (which while reliable, aren't 100% perfect for all solutions either.)

And honestly, some large sites that are normally pretty good about this kind of thing just stick a "actiondone=true" in the url. (I've noticed Facebook does it in some places.)

TheLordRedbeard
Thanks, the referer trick is very smart
Maciej Łebkowski
+1  A: 

Coming very late to this discussion..

You could use a combination of the two proposed options.

After the POST request the client is redirected (303) to an URL indicating that there could be a response message for this request:

Client: GET  http://example.com/foo.cgi
Server: 200  Ok

Client: POST http://example.com/bar.cgi
Server: 303  http://example.com/foo.cgi?msg=true

If the msg argument is true the message will be looked up in the session and (if found) included in the response to the client.
If the msg argument is ! true (or not present), the lookup step is skipped.

With this solution, you prevent the actual message being show in the URL, the URL only indicates there could be a message. Also, the message is only shown when needed (=when found in the session).

Another advantage is that this solution also allows for proper cash-controls to be included with HTTP responses.

Jacco
You can do this by checking the existence of the message in session data (and it’s cleared after each request). No need for a _GET parameter here...
Maciej Łebkowski
You could, but then you prevent your browser for ever caching the resource
Jacco