何时在 ASP.Net MVC 中使用 TempData 与 Session
我正在尝试掌握 MVC 框架,所以请耐心等待。
现在,我使用会话存储的唯一目的是存储当前登录的用户。我的网站很简单。对于此示例,请考虑三个域对象:人员、会议和文件。用户可以登录并查看会议的“仅限会员”个人资料,并且可以向其中添加文件,或者如果未登录,则可以查看会议的公共“个人资料”。
因此,从会议的私人个人资料中,通过登录用户,我有一个“添加文件”链接。此链接路由至 FileContoller.Add(int meetId)。通过此操作,我可以使用会议 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 中?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
TempData 是会话,因此它们并不完全不同。不过,区别很容易理解,因为 TempData 用于重定向,并且仅重定向。因此,当您在 TempData 中设置一些消息然后重定向时,您就正确使用了 TempData。
然而,将 Session 用于任何类型的安全都是极其危险的。会话和成员资格在 ASP.NET 中是完全独立的。 您可以“窃取”其他用户的会话,是的,人们确实以这种方式攻击网站。因此,如果您想根据用户是否登录有选择地停止发布信息,请查看 IsAuthenticated,如果您想根据登录的用户类型有选择地显示信息,请使用 角色提供程序。由于 GET 可以缓存,因此有选择地允许访问 GET 中的操作的唯一方法是使用 AuthorizeAttribute。
更新针对您编辑的问题:您已经有一个在问题中使用 TempData 的好示例,即在 POST 失败后返回简单的错误消息。就 Session 中应该存储的内容(除了“不多”之外)而言,我只是将 Session 视为特定于用户的缓存。与非用户特定的缓存一样,您不应将安全敏感信息放在那里。但这是一个放置查找相对昂贵的东西的好地方。例如,我们的Site.Master上显示了用户的全名。它存储在数据库中,我们不想为我们服务的每个页面都对其进行数据库查询。 (我们的应用程序的安装是在一家公司中使用的,因此用户的全名不被视为“安全敏感”。)因此,如果您将 Session 视为一个缓存,该缓存随用户拥有的 cookie 的不同而变化,那么您就不会'不会错的。
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.
默认的 TempData 提供程序使用会话,因此实际上没有太大区别,只是您的 TempData 在下一个请求结束时被清除。当数据只需要在两个请求之间保留时,您应该使用 TempData,第二个请求最好是重定向,以避免用户的其他请求(例如来自 AJAX)出现问题,意外删除数据。如果数据需要保留的时间超过该时间,您应该重新填充 TempData 或直接使用 Session。
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.
您可以根据您的要求使用它。需要澄清的是,
TempData 与 Session
TempData
TempData 有 Keep 方法来保留 TempData 的值。
示例:
TempData.Keep(), TempData.Keep(“EmpName”)
TempData 在内部将值存储到 Session 变量。
Session:
TempData 和 session 都需要进行类型转换来获取数据并检查空值以避免运行时异常。
You can use it as per your requirement. A clarification can be,
TempData Vs Session
TempData
TempData has Keep method to retention the value of TempData.
Example:
TempData.Keep(), TempData.Keep(“EmpName”)
TempData internally stored the value in to Session variable.
Session:
TempData and session, both required typecasting for getting data and check for null values to avoid run time exception.
“它不起作用”并不是很具有描述性,但让我提供一些建议。
在底层,TempData 使用 Session 来存储值。因此,在存储机制或类似方面没有太大区别。但是,TempData 仅持续到收到下一个请求为止。
如果用户在表单发布之间发出 ajax 请求,TempData 就会消失。任何请求都会清除 TempData。因此,只有在进行手动重定向时它才可靠。
为什么不能简单地将会议 ID 呈现到视图表单中的隐藏字段中?您已经将其添加到模型中。或者,将其作为参数添加到您的路线中。
"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.
我更喜欢在页面本身中维护此类数据。将 MeetingID 渲染为隐藏输入,以便将其提交回控制器。然后,处理帖子的控制器可以将该会议 ID 反馈给将呈现的任何视图,这样只要您需要,会议 ID 基本上就会被传递。
这有点像在调用对其进行操作的方法之前将值存储在全局变量中与将值直接传递给方法之间的区别。
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.
我建议 MvcContrib 的解决方案:
http://jonkruger.com/blog/2009/04/06/aspnet-mvc-pass-parameters-when-redirecting-from-one-action-to-another/
如果你不想完整MvcContrib,解决方案只是 1 个方法 + 1 个类,您可以轻松地从 MvcContrib 源中获取它们。
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.
TempData 属性值存储在会话状态中。 TempData 的值将一直存在,直到被读取或会话超时。如果要将数据从一个控制器视图传递到另一个控制器视图,那么您应该使用 TempData。
当整个应用程序需要数据时使用Session
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