代码之家  ›  专栏  ›  技术社区  ›  scottm

何时在ASP.NET MVC中使用tempdata vs会话

  •  59
  • scottm  · 技术社区  · 16 年前

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

    现在,我使用会话存储的唯一目的是存储当前登录的用户。我的网站很简单。对于这个例子,考虑三个域对象:个人、会议和文件。用户可以登录并查看会议的“仅成员”配置文件,并可以向其中添加文件,或者在未登录时查看会议的公共“配置文件”。

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

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

        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 vs会话中应存储哪些类型的数据(消息除外)的示例?

    7 回复  |  直到 7 年前
        1
  •  87
  •   Craig Stuntz    16 年前

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

    但是,将会话用于任何类型的安全性都是极其危险的。会话和成员身份在ASP.NET中是完全独立的。 You can "steal" sessions from other users 是的,人们确实是这样攻击网站的。因此,如果您希望根据用户是否登录选择性地停止日志信息,请查看 IsAuthenticated 如果要根据登录的用户类型有选择地显示信息,请使用 Role provider .因为gets可以缓存, 只有 有选择地允许访问get中的操作的方法是使用authorizeAttribute。

    更新 回答您编辑过的问题:您已经有了一个在问题中使用tempdata的好例子,即,在失败的帖子之后返回一个简单的错误消息。在什么方面 应该 存储在会话中(除了“不太多”),我只是将会话视为特定于用户的缓存。与非用户特定的缓存一样,您不应该将安全敏感信息放在那里。但这是一个很好的地方,贴东西,这是相对昂贵的查找。例如,我们的site.master上显示了用户的全名。它存储在一个数据库中,我们不想为我们服务的每个页面对它进行数据库查询。(我们的应用程序的安装是在一家公司中使用的,因此用户的全名不被视为“安全敏感”。)因此,如果您将会话视为缓存,而缓存因用户拥有的cookie而有所不同,那么您就不会大错特错了。

        2
  •  17
  •   tvanfosson    16 年前

    默认的tempdata提供程序使用会话,因此实际上没有太多区别,只是在下一个请求结束时清除了tempdata。当数据只需要在两个请求之间保持时,您应该使用tempdata,最好第二个请求是重定向,以避免与来自用户的其他请求(例如来自Ajax)发生问题,从而意外删除数据。如果数据需要持续的时间超过这个时间,您应该重新填充tempdata或者直接使用会话。

        3
  •  4
  •   womp    16 年前

    “它不起作用”不是很有描述性,但让我提几个建议。

    在引擎盖下,tempdata使用会话来存储值。所以在存储机制或类似的方面没有太大的区别。但是,tempdata只持续到收到下一个请求。

    如果用户在表单发布之间发出Ajax请求,则tempdata将消失。任何请求都将清除tempdata。所以只有当你进行手动重定向时,它才是真正可靠的。

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

        4
  •  3
  •   A Coder    8 年前

    您可以根据需要使用它。澄清可以是:

    临时数据 VS 会话

    临时数据

    1. tempdata允许我们在单个后续请求期间保持数据。
    2. 一旦连续请求返回结果,ASP.NET MVC将自动使tempdata的值过期(这意味着,只有在目标视图完全加载之前,它才是活动的)。
    3. 仅对当前和后续请求有效
    4. tempdata具有保留tempdata值的keep方法。

      例子:

      tempdata.keep(),tempdata.keep(__empname_)

    5. tempdata在内部将值存储在to会话变量中。

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

    会议:

    1. 在用户会话未到期之前,会话能够更长时间地存储数据。
    2. 会话将在会话超时后过期。
    3. 它对所有请求都有效。
    4. 不适用
    5. 会话变量存储在sessionStateItemCollection对象中(通过页面的httpContext.session属性公开)。
    6. 它用于存储用户会话期间所需的长寿命数据,如用户ID、角色ID等。

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

        5
  •  0
  •   D'Arcy Rittich    16 年前

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

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

        6
  •  0
  •   queen3    16 年前

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

    如果您不想要完整的mvcontrib,那么解决方案是只需要1个方法+1个类,您可以很容易地从mvcontrib源中获取。

        7
  •  0
  •   Mervin    11 年前

    tempdata属性值存储在会话状态中。tempdata的值将一直保持,直到读取或会话超时为止。如果要将数据从一个控制器视图传递到另一个控制器视图,则应使用tempdata。

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