8

I'm building an MVC application. One of my taskS is to build a store. I set up a "wizard" like set of views that brings the user to fill different kind of data until the end of the operation, in total 7 steps.

My issue is about how to share some data between all these views.

First I used old-fashioned Session and everything worked on my desktop, but when I finally deployed my application into my company's hosting server I got exceptions because Session was erased randomly during some steps.

Now I modified everything to set up any data I need inside TempData, and refreshing all data in each step and it's seems to work properly.

I'm a little confused!

My confusion is about all these structures: Session (I know it coming from asp.net), ViewData, TempData and the magic ViewBag.

I read a lot about but I need someone that clearly tell me what is more appropriate for me in this case.

pb2q
  • 58,613
  • 19
  • 146
  • 147
JasonMenny
  • 223
  • 4
  • 14
  • 1
    Steven Sanderson has the detailed discussion about that subject in his book Pro ASP.NET MVC 2, Chapter 13 > Wizards and Multistep Forms. If you've got the book, you could check it out – archil Sep 01 '11 at 08:48
  • I bought the book, Im waiting Mr. Amazon! In the meantime my boss is asking me why our site is not working! It's an hard life! – JasonMenny Sep 01 '11 at 08:58
  • Actually, default backing storage for TempData is Session. So I wouldn't expect for it to work when the session gets cleared often. Be carefull though – archil Sep 01 '11 at 09:03
  • I know, in fact Im putting values inside TempData, putting the value inside some HiddenField and the reputting in TempData inside my [HttpPost] action. Not elegant but working – JasonMenny Sep 01 '11 at 09:05
  • 1
    http://stackoverflow.com/questions/6402628/multi-step-registration-process-issues-in-asp-net-mvc-splitted-viewmodels-singl/6403485#6403485 this answer may help you – archil Sep 01 '11 at 10:07

3 Answers3

3

I'd say the ViewBag is perfect for something like this. Now, you're referring to the ViewBag as a "Magic" viewbag, but in reality it just wraps the ViewData which is a dictionary of <string,object>

The way the ViewBag works is that it's just a dynamic wrapper around the ViewData, so when you ask for something, let's say ViewBag.ShoppingCart, it basically ask the underlying dictionary if it has an entry called "ShoppingCart", and returns the item.

UPDATE Problem is I didn't remember that ViewBag and ViewData is view-specific, so they're emptied whenever you hit a different View/Action.

Unless you need the ShoppingCart (or wizard-progress) to be stored in a database, I'd go for ViewBag TempData in your case :)

You could also take a look at this article from Rachel Apple for a bit more info on the three:

http://rachelappel.com/when-to-use-viewbag-viewdata-or-tempdata-in-asp.net-mvc-3-applications

(Ps. I'd recommend reading the comments as well on that post to get some more unbiased opinions)

Yngve B-Nilsen
  • 9,606
  • 2
  • 36
  • 50
  • 1
    How can be ViewBag used in this case? As I understood the question, he needs client side, multiple step wizard. And he wants to save each step data for the next step – archil Sep 01 '11 at 08:51
  • Infact if I understood ViewBag (and ViewData) is not what I need. I need a structure where I can put some values while Im moving across my Views. Now Im using TempData and HiddenField in each View, it's not so elegant but it'working right now. – JasonMenny Sep 01 '11 at 09:00
  • JasonMenny: I'm sorry, I've made a mistace, since ViewBag (ViewData) is action-specific. TempData however is not, so why not use that? @archil He specifies "between views", so I did not read that as client side, but actual calls to different ActionMethods. I'll update my answer. – Yngve B-Nilsen Sep 01 '11 at 11:12
2

Nothing wrong with using hidden fields - in my book, at least.

I'd 'fix' the Session issue instead of trying to write code around the problem. Run a simple test: change your Session provider to SQL, disable the hidden fields and see if your app works properly. If it doesn't, there are other (bigger) issues you have to worry about.

Is this app supposed to work in a web farm / "cloud" / behind a load-balancer? If so, you either have to:

  • change the session provider to something else: SQL, StateServer, memcache, etc. Not many code changes required.

http://msdn.microsoft.com/en-us/library/ms178587.aspx and http://memcachedproviders.codeplex.com/

OR

  • re-design your wizard steps and reduce your dependency on shared values between views. Session ID is all you need and you can query the DB for anything else. Not very fast but safe and stable.

Optimize: Use as many hidden fields as you like to reduce the number of DB queries (like I said, nothing wrong with this) but usually one field is enough to keep your serialized state between requests: http://blog.maartenballiauw.be/post/2009/10/08/Leveraging-ASPNET-MVC-2-futures-ViewState.aspx.

Even if you don't have to worry about multiple instances of your app (on different machines), IIS recycles the worker processes every now and then. When it does, you can end up with two instances running at the same time (for small amounts of time) on the same machine and some of your users might be unlucky enough to hit the server exactly during those moments.

It should not matter if the next request hits a different instance of your application. Always try to design with this goal in mind.

Hope it helps!

bkdc
  • 524
  • 3
  • 6
0

You have several options here: Use session, viewdata (or viewbag) but need to pass it using hidden fields or cookies.

Viewdata has the problem that will give more work.

I'd go with the session but maybe it gets cleared in your case because you probably have more than one server and when the 2nd request gets to another server, it just won't have the data from the previous step.

Solve this problem using a server that holds the session for all servers or use cookies (if the information is NOT critical).

Fabio Milheiro
  • 8,100
  • 17
  • 57
  • 96