There are several options. If we're talking about intrarequest, then of course ViewBag is the best choice. Intrapage (across requests) then the best choice is probably hidden fields, unless it's sensitive data.
Between pages, then there are several options. You can of course pass data as query string parameters. Session also makes a convenient option, so long as the data size is small, and it's ok if the session gets lost (ie, you can get it again or regenerate it). In certain other situations, you can post data to another page using hidden fields, but this should largely be discouraged since you should prefer to use PRG (Post/Redirect/Get) pattern.
Some other options are using the context cache HttpContext.Cache
(Which i feel is misnamed, but oh well) or saving it in temporary tables in the database. Any "in-memory" option will have scalability issues if you decide to move to a web farm (Session can be made to be backed by database, but it slows things down).
It also depends on what data you're talking about. If it's user data, then another option is to store it in a cookie, or to use the user data portion of the Forms Authentication cookie, and create a custom IIdentity object.
Finally, there's just rebuilding the data from its source on every request.