Hi,

On Jan 21, 2008, at 7:43 AM, Jonathan Rockway wrote:
Along these lines, how is everyone doing multi-page forms? I like to do GET/POST/redirect, but that needs the session to get the data from page
1 to page 2.  Without a session, I use the old "POST returns the form
with hidden fields that is page 1", but i *hate* that technique.  So I
use the session.

I'm going through this as well right now, doing a small checkout- style multi-step form. The following is my current idea on how to deal with this. Its still a rough draft but I think it will work ok. Any feedback is appreciated.

Below, when I mention PUT, i'm using PUT-tunneled-over-POST for web clients.

Users start by POST'ing to /checkout/start. This will create a cart containing the items to include in this checkout. In our case, we always include all the items currently pending payment, other sites might have a different policy/requirements. The point of this first step is to create a cart, with a unique identifier. We associate the cart with the logged in user and we include a security hash based on the cart id and user id on each form. After all this, we redirect to / checkout/cart/UNIQUE_ID/step1.

On each step, the GET will show the appropriate form. The user will fill the fields, and PUTs the result to the same address. Information received is checked and valid fields are stored in the cart state. After that, if all fields are correct, we redirect to the next step.

If they are not correct, we redirect to the same URL. Previous values, and error messages or error codes are given back using URL parameters. Usually we have very little parameters and they are all limited in size, so it fits the 1k max URL size.

Aside: If a field is unusually large, we need some kind of temporary storage, and this could break somewhat the Idempotence of each request. We could sha1 hash the bad content, store it somewhere keyed on this hash and send the hash to the client. This might solve it. Fortunately I never needed this.

On each step, the process updates the fields on the cart, and at the final step, we change the status of the cart to 'ready_to_process' and redirect the user to a success page.

The things I like on this approach:

Every request is idempotent: you can reload to your hearts content any page, you can post several times each step to update previous entered information, you can go back and forward, everything.

There is no final step of copying the cart usually stored in the session to your orders table. The cart is the order, you build the order step by step until its ready to be processed by our back-office staff.

Old, unfinished orders can be cleaned up after some time, and if they are request in the future you can just create a new one and redirect to it, or you can give the user a error message and suggest the creation of a new one. I keep carts for one year or until the items in it expire, but that's my business :). Yours might need different timings. You could also erase old carts based on the step they are at.

If you start a new checkout with another one still open, there are several options. My personal choice is to merge the old order with the new items, but you could also create a new one and suggest merging the old one (merging on demand). This part also depends on your business needs.

Anyway, this is my currently thinking on this subject. Any feedback appreciated.


(I also use the Flash for "You've added a record
successfully!" messages.  Totally non-RESTful, but the users seem to
like it.)

You not redirect with parameters? something like po_id=1&p1=Pedro&[EMAIL PROTECTED] to use message id 1 with two parameters, 1=Pedro and [EMAIL PROTECTED]

RESTfull, no?

Best regards,
--
Pedro Melo
Blog: http://www.simplicidade.org/notes/
XMPP ID: [EMAIL PROTECTED]
Use XMPP!



_______________________________________________
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/

Reply via email to