何时在 ASP.Net MVC 中使用 TempData 与 Session

Posted

技术标签:

【中文标题】何时在 ASP.Net MVC 中使用 TempData 与 Session【英文标题】:When to use TempData vs Session in ASP.Net MVC 【发布时间】:2010-12-02 19:00:58 【问题描述】:

我正在尝试掌握 MVC 框架的窍门,所以请耐心等待。

现在,我使用会话存储的唯一目的是存储当前登录的用户。我的网站很简单。对于此示例,请考虑三个域对象:Person、Meeting 和 File。用户可以登录并查看会议的“仅限成员”个人资料,并可以向其中添加文件,或者如果他们未登录,则可以查看会议的公开“个人资料”。

因此,从会议的私人资料中,我有一个登录用户,我有一个“添加文件”链接。此链接路由到 FileContoller.Add(int meetingId)。通过此操作,我得到了用户想要使用会议 ID 添加文件的会议,但是在发布表单后,我仍然需要知道用户正在向哪个会议添加文件。这就是我的问题所在,我应该通过 TempData 传递“当前正在与之交互”的会议,还是将其添加到 Session 存储中?

这是我目前设置添加操作的方式,但它不起作用:

    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);

编辑:

根据大多数答案,任何人都可以提供任何示例,说明应该在 TempData 与 Session 中存储哪种数据(消息除外)?

【问题讨论】:

TempDataKeys是什么类型,只是一个类?还是一个枚举? @Anon343224user 现在为时已晚,但我正在为像你和我这样想知道的人写信。我也想知道,在github.com/Macht59/StenoCryptor/blob/master/… 找到了类似的用法,它是一个静态类,包含 consts 字符串字段。 现代读者请注意:TempData 在 .NET Core 中的工作方式与此处的许多答案中描述的方式不同。详情见我的回答here。 【参考方案1】:

“它不起作用”不是很具有描述性,但让我提供一些建议。

在底层,TempData 使用 Session 来存储值。所以在存储机制或类似的方面没有太大区别。但是,TempData 仅持续到收到下一个请求。

如果用户在表单发布之间发出 ajax 请求,TempData 就会消失。任何请求都会清除 TempData。因此,只有在您进行手动重定向时,它才真正可靠。

为什么不能简单地将会议 ID 呈现到视图表单中的隐藏字段?您已经将其添加到模型中。或者,将其作为参数添加到您的路线中。

【讨论】:

有两个 cmets 描述了对我不起作用的内容。我猜我可以传递对象,而不必再次从数据库中检索它,但现在我想,这可能会增加很多并发问题。【参考方案2】:

我更喜欢在页面本身中维护这种数据。将 meetingID 呈现为隐藏输入,以便将其提交回控制器。然后,处理帖子的控制器可以将该会议 ID 反馈给将要呈现的任何视图,以便该会议 ID 基本上可以在您需要时传递。

这有点像在调用将对其进行操作的方法之前将值存储在全局变量中与将值直接传递给方法之间的区别。

【讨论】:

【参考方案3】:

默认的 TempData 提供程序使用会话,因此实际上并没有太大区别,只是您的 TempData 在下一个请求结束时被清除。当数据只需要在两个请求之间保留时,您应该使用 TempData,最好是第二个请求是重定向,以避免来自用户的其他请求(例如来自 AJAX)的问题意外删除数据。如果数据需要保持更长的时间,您应该重新填充 TempData 或直接使用 Session。

【讨论】:

我明白这一点。我在 GET 方法中将会议对象放在 TempData 中,然后当用户发布表单时,我应该可以再次从 TempData 中检索它,对吧? 不,你不能数。 TempData 仅用于重定向。如果您在 GET 中设置 TempData,那么您的页面会进行 AJAX 调用,然后用户 POST,TempData 会消失。 “不,你数不过来。” -> ""不,你不能指望那个。"有关 TempData 和重定向的更多信息,请参阅我的答案中的链接。 @Craig,我明白你的意思。如果我不发出任何 ajax 请求,就我而言,它不应该还在吗? 我不会打赌。如果用户 POST 数据,但由于服务器端验证而失败,该怎么办。所以 POST 返回一个视图,而不是重定向。用户修复了验证问题并再次发布。 TempData 消失了,因为它在 POST 失败后被删除。无论如何,您可能迟早会使用 AJAX,所以不要计划不使用它。 TempData 确实仅用于重定向; MVC 团队的一名成员私下向我证实了这一点。【参考方案4】:

TempData 是会话,所以它们并不完全不同。不过,区别很容易理解,因为TempData is for redirects, and redirects only。因此,当您在 TempData 中设置一些消息然后重定向时,您正在正确使用 TempData。

但是,将 Session 用于任何类型的安全性都是极其危险的。会话和成员资格在 ASP.NET 中是完全分开的。 You can "steal" sessions from other users,是的,人们确实以这种方式攻击网站。因此,如果您想根据用户是否登录选择性地停止发布信息,请查看IsAuthenticated,如果您想根据登录的用户类型选择性地显示信息,请使用Role provider。因为 GET 可以被缓存,所以在 GET 中选择性地允许访问操作的唯一方法是使用 AuthorizeAttribute。

更新回应您编辑的问题:您已经有一个在问题中使用 TempData 的好例子,即在 POST 失败后返回简单的错误消息。就 应该 存储在 Session 中的内容(除了“不多”)而言,我只是将 Session 视为用户特定的缓存。与非用户特定的缓存一样,您不应将安全敏感信息放在那里。但这是一个放置查找成本相对较高的东西的好地方。例如,我们的 Site.Master 上面显示了用户的全名。它存储在数据库中,我们不想为我们服务的每个页面都进行数据库查询。 (我们的应用程序安装在一家公司中使用,因此用户的全名不被认为是“安全敏感的”。)因此,如果您将 Session 视为随用户拥有的 cookie 而变化的缓存,您将不会不会错的。

【讨论】:

我不需要角色,登录后每个人都有相同的访问权限。不过我会研究 IsAuthenticated,谢谢 不是基于cookie的鉴权机制,用类似的方式不能盗取吗? @Ismail,是的,涉及 cookie(默认情况下)。不,它不能以类似的方式被盗。身份验证旨在确保安全。会话不是。它们是两种不同的东西。 @CraigStuntz 感谢您的解释,性能怎么样!使用会话是否会减慢应用程序加载时间? @AbdulsalamElsharif 是的,使用 Session 确实会降低性能。但是您可能必须完全禁用控制器的 Session(而不仅仅是避免 TempData)以避免这种情况。【参考方案5】:

我会建议 MvcContrib 的解决方案: http://jonkruger.com/blog/2009/04/06/aspnet-mvc-pass-parameters-when-redirecting-from-one-action-to-another/

如果您不想要完整的 MvcContrib,解决方案只有 1 个方法 + 1 个类,您可以轻松地从 MvcContrib 源中获取。

【讨论】:

【参考方案6】:

TempData 属性值存储在会话状态中。 TempData 的值会一直存在,直到它被读取或会话超时。如果你想将数据从一个控制器视图传递到另一个控制器视图,那么你应该使用 TempData。

当整个应用程序需要数据时使用 Session

【讨论】:

【参考方案7】:

您可以根据需要使用它。可以澄清一下,

TempDataSession

临时数据

    TempData 允许我们在单个后续请求期间持久化数据。 一旦连续请求返回结果,ASP.net MVC 将自动使 tempdata 的值过期(这意味着它只在目标视图完全加载之前才有效)。 仅对当前和后续请求有效

    TempData 有 Keep 方法来保留 TempData 的值。

    例子:

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

    TempData 在内部将值存储到 Session 变量中。

    仅用于存储一次消息,如验证消息、错误消息等。

会话:

    会话能够存储更长时间的数据,直到用户会话未过期。 会话将在会话超时后过期。 它适用于所有请求。 不适用 会话变量存储在 SessionStateItemCollection 对象中(通过页面的 HttpContext.Session 属性公开)。 它用于存储用户会话期间需要的长寿命数据,如用户 ID、角色 ID 等。

TempData 和 session,都需要类型转换来获取数据并检查空值以避免运行时异常。

【讨论】:

这是一个非常有用的答案,因为它有助于清楚地决定何时使用哪个。

以上是关于何时在 ASP.Net MVC 中使用 TempData 与 Session的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC4 异步控制器 - 为啥要使用?

asp.net MVC Razor 文本框控件验证

检测何时在 ASP.NET 中禁用 JavaScript

在ASP.NET MVC项目中使用React

[转载]在ASP.NET MVC中,使用Bundle来打包压缩js和css

ASP.NET MVC 和 Angularjs 与 ASP.NET MVC 和 Reactjs