When to use TempData vs Session in ASP.Net MVC
Asked Answered
T

7

68

I am trying to get the hang of MVC framework so bear with me.

Right now, the only thing I'm using the session store for is storing the current logged in user. My website is simple. For this example, consider three domain objects, Person, Meeting, and File. Users can log in and view a "members only" profile of a meeting and can add files to it, or view a meeting's public "profile" if they aren't logged in.

So, from the meeting's private profile, with a logged in user, I have a "add files" link. This link routes to FileContoller.Add(int meetingId). From this action, I get the meeting the user want to add files to using the meeting id, but after the form is posted, I still need to know which meeting the user is adding files to. That's where my question lies, should I pass the "currently interacting with" meeting through TempData, or add it to the Session store?

This is how I currently have the Add action setup, but it's not working:

    public ActionResult Add(int meetingId)
    {
        try
        {
            var meeting = _meetingsRepository.GetById(meetingId);
            ViewData.Model = meeting;
            TempData[TempDataKeys.CurrentMeeting] = meeting; /* add to tempdata here */
        }
        catch (Exception)
        {
            TempData[TempDataKeys.ErrorMessage] = "Unable to add files to this meeting.";
            return RedirectToRoute("MeetingsIndex");
        }

        return View();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Add(FormCollection form)
    {
        var member = Session[SessionStateKeys.Member] as Member;
        var meeting = TempData[TempDataKeys.CurrentMeeting] as Meeting; /* meeting ends up null here */

        if (member == null)
        {
            TempData[TempDataKeys.ErrorMessage] = "You must be logged in to add files to an meeting.";
            return RedirectToRoute("LoginPage");
        }

        if (meeting == null) 
        {
            TempData[TempDataKeys.ErrorMessage] = "An error occurred. No meeting selected.";
            return RedirectToRoute("MeetingsIndex");
        }

            // add files to meeting

        TempData[TempDataKeys.Notification] = "Successfully added.";
        return RedirectToRoute("AddFiles", new {meetingId = meeting.MeetingId});
}

Edit:

Based on most of the answers, can any one provide any examples on what kind of data (other than messages) should be stored in TempData vs Session?

Tod answered 30/9, 2009 at 20:14 Comment(3)
What type is TempDataKeys, just a class? Or an enum?Narcolepsy
@Narcolepsy it is too late but I'm writing for who wonders like you and me. I wondered it too and found similar usage at github.com/Macht59/StenoCryptor/blob/master/… it's a static class and contains consts string fields.Sweeting
Note to modern readers: TempData works differently as of .NET Core than how it is described in many of the answers here. See my answer here for details.Susurrant
U
99

TempData is session, so they're not entirely different. However, the distinction is easy to understand, because TempData is for redirects, and redirects only. So when you set some message in TempData and then redirect, you are using TempData correctly.

However, using Session for any kind of security is extremely dangerous. Session and Membership are entirely separate in ASP.NET. You can "steal" sessions from other users, and yes, people do attack web sites this way. So if you want to selectively stop a post information based on whether a user is logged in, look at IsAuthenticated, and if you want to selectively show information based on what type of user is logged in, you use a Role provider. Because GETs can be cached, the only way to selectively allow access to an action in a GET is with AuthorizeAttribute.

Update In response to your edited question: You already have a good example of using TempData in your question, namely, returning a simple error message after a failed POST. In terms of what should be stored in Session (beyond "not much"), I just think of Session as a user-specific cache. Like the non-user-specific Cache, you should not put security-sensitive information there. But it's a good place to stick stuff which is relatively expensive to look up. For example, our Site.Master has the user's full name displayed on it. That is stored in a database, and we don't want to do a database query for it for every page we serve. (An installation of our application is used in a single company, so a user's full name is not considered "security-sensitive.") So if you think of Session as a cache which varies by a cookie which the user has, you won't be far wrong.

Unaesthetic answered 30/9, 2009 at 20:31 Comment(7)
I don't need roles, everyone has the same access once logged in. I will do my research on IsAuthenticated though, thanksTod
Isn't Authentication mechanism based on cookie and can't it be stolen in similar way?Unrealizable
@Ismail, yes, a cookie is involved (by default). No, it can't be stolen in a similar way. Authentication is designed to be secure. Session isn't. They are two different things.Unaesthetic
@CraigStuntz Thanks for your explanation, What about performance! Does using session is slow down application loading time?Ic
@AbdulsalamElsharif Yes, using Session does hurt performance a bit. But you'll probably have to totally disable Session for the controller (not just avoid TempData) to avoid that.Unaesthetic
@CraigStuntz “Totally disable Session for the controller” What do you mean please, Can you clear.Ic
@AbdulsalamElsharif You use SessionStateAttribute; see this answer.Unaesthetic
H
17

The default TempData provider uses the session so there really isn't much of a distinction, except that your TempData is cleared out at the end of the next request. You should use TempData when the data needs only to persist between two requests, preferably the second one being a redirect to avoid issues with other requests from the user -- from AJAX, for example -- deleting the data accidentally. If the data needs to persist longer than that, you should either repopulate the TempData or use the Session directly.

Hooknosed answered 30/9, 2009 at 20:27 Comment(6)
I understand that. I put the meeting object in TempData in the GET method, then when the users posts the form, I should be able to retrieve it from TempData again, right?Tod
No, you cannot count. TempData is for redirecting only. If you set TempData in a GET, then your page makes an AJAX call, then the user POSTs, the TempData is gone.Unaesthetic
"No you cannot count." -> ""No you cannot count on that." See the link in my answer for more on TempData and redirects.Unaesthetic
@Craig, I get your point. If I don't make any ajax requests, shouldn't it still be there, in my case?Tod
I wouldn't bet on it. What if the user POSTs data, but it fails, because of server-side validation. So the POST returns a view, instead of redirecting. The user fixes the validation issue and POSTs again. The TempData is gone, because it was erased after the failed POST. Anyway, you probably use AJAX sooner or later, so don't plan around not using it. TempData really is for redirects only; this was confirmed to me privately by a member of the MVC team.Unaesthetic
I would agree with Craig -- only use TempData for redirects where you can "guarantee" that it will be there.Hooknosed
W
9

You can use it as per your requirement. A clarification can be,

TempData Vs Session

TempData

  1. TempData allow us to persisting data for the duration of single subsequent request.
  2. ASP.net MVC will automatically expire the value of tempdata once consecutive request returned the result (it means, it alive only till the target view is fully loaded).
  3. It valid for only current and subsequent request only
  4. TempData has Keep method to retention the value of TempData.

    Example:

    TempData.Keep(), TempData.Keep(“EmpName”)

  5. TempData internally stored the value in to Session variable.

  6. It is used to stored only one time messages like validation messages, error messages etc.

Session:

  1. Session is able to store data much more long time, until user session is not expire.
  2. Session will be expire after the session time out occurred.
  3. It valid for all requests.
  4. N/A
  5. Session varible are stored in SessionStateItemCollection object (Which is exposed through the HttpContext.Session property of page).
  6. It is used to stored long life data like user id, role id etc. which required throughout user session.

TempData and session, both required typecasting for getting data and check for null values to avoid run time exception.

Woald answered 22/6, 2017 at 7:7 Comment(3)
This is a very helpful answer, as it helps to decide when to use which very clearly.Concepcion
What if another user makes a request at the same time? Do I need to make the TempData key unique or will each user have a different TempData?Luckey
@Luckey You don't have to do anything actually about it.Woald
P
4

"It doesn't work" isn't very descriptive, but let me offer a couple suggestions.

Under the hood, TempData uses Session to store values. So there isn't much difference in terms of storage mechanisms or anything like that. However, TempData only lasts until the next request is received.

If the user makes an ajax request in between form posts, TempData is gone. Any request whatsoever will clear TempData. So it's really only reliable when you're doing a manual redirect.

Why can't you just simply render the meeting ID to a hidden field in your View form? You're already adding it to the model. Alternately, add it to your route as a parameter.

Pulpit answered 30/9, 2009 at 20:27 Comment(1)
There are two comments that describe what's not working for me. I guessed I could pass the object and not have to retrieve it from the database again, but now that I think about it, that would probably add a lot of concurrency problems.Tod
N
0

I prefer to maintain that kind of data in the page itself. Render meetingID as a hidden input, so it gets submitted back to the controller. The controller handling the post can then feed that meeting ID back to whatever view will be rendered, so that the meetingID basically gets passed around as long as you need it.

It's kind of like the difference between storing a value in a global variable before calling a method that will operate on it, vs. passing the value directly to the method.

Nope answered 30/9, 2009 at 20:27 Comment(0)
B
0

I would suggest MvcContrib's solution: http://jonkruger.com/blog/2009/04/06/aspnet-mvc-pass-parameters-when-redirecting-from-one-action-to-another/

If you don't want full MvcContrib, the solution is only 1 method + 1 class that you can easily grab from MvcContrib sources.

Baksheesh answered 30/9, 2009 at 20:47 Comment(0)
W
0

The TempData property value is stored in session state. The value of TempData persists until it is read or until the session times out. If you want pass data one controller view to another controller view then you should use TempData.

Use Session when the data need for the throughout application

Washtub answered 28/3, 2014 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.