哪里是存储自定义“用户”信息的最佳位置? ASP.NET 会话期间的对象?
我有一个 ASP.NET 应用程序,需要在会话中跨页面记住有关用户(以及他们来自哪家公司)的一些信息。
我想这几乎是任何具有一定规模的 ASP.NET 应用程序的要求。多年来我使用了几种不同的方法。
过去,我在查询字符串参数中传递了一个 id,如下所示:
site.com/page.aspx?usrid=1&companyid=2
然后实例化每个页面上的对象(来自数据库)。
另一种常见的方法是将我的对象存储在会话变量中:
Session["User"] = currentUser; // store at login
User currentUser = (User)Session["User"]; // retrieve on some other page
这可以节省数据库的访问,但如果用户对象很复杂并且站点有许多并发用户,我担心内存的使用。
我最近继承了一个在母版页上使用公共属性的应用程序,如下所示:
Master.theUser = currentUser; // store at login
User currentUser = Master.theUser; // retrieve on some other page
这可以保存转换,并且我认为对我来说看起来更具可读性,但我不知道它在性能方面是更好还是更差。它在 getter 中还有一些逻辑,如果私有值为 null,它会尝试从 Session 变量中获取它,尽管我不确定它是否从未使用过(或使用过 every get!? )或者什么。
我最新的想法是使用我的页面类。我有一个从标准 System.Web.UI.Page 基类派生的自定义页面类。它包括像 CurrentUser 这样的对象作为公共属性。这似乎工作正常。我更喜欢它。
但我真的不知道幕后发生了什么。谁能就哪种方法更好以及为什么提出意见?
也欢迎对此提出其他建议。
更新: 我已经使用trace.axd和Trace.Write进行了一些检查,看起来母版页版本和自定义页面类版本都没有“记住”页面之间的值。 “get”方法有一行代码,用于检查 User 属性是否为 null,如果是,则从会话变量中读取它。当页面在给定页面上第一次访问属性(Master.User 或派生类的 this.User)时,就会发生这种情况,然后后续请求可以获得该值(无需访问会话变量)。
I have an ASP.NET application that needs to remember some info about a user (and what company they are from) across pages, within a session.
I imagine this is a requirement of just about any ASP.NET application of a certain size. I've used a few different approaches over the years.
In the past, I've passed around an id in querystring parameters like so:
site.com/page.aspx?usrid=1&companyid=2
and then instantiated the object on each page (from the database).
Another common way of doing it is storing my objects in session variables:
Session["User"] = currentUser; // store at login
User currentUser = (User)Session["User"]; // retrieve on some other page
which saves a trip to the DB, but I worry about memory used if the User object is complex and the site has many concurrent users.
I have recently inherited an application that uses public properties on the master page, like this:
Master.theUser = currentUser; // store at login
User currentUser = Master.theUser; // retrieve on some other page
This saves the cast, and looks more readable to me I think, but I don't know if it's better or worse performance-wise. It also has some logic in the getter where if the private value is null, it tries to get it from the Session variable, though I'm not sure if that's never used (or used every get!?) or what.
My latest idea is to use my page class. I have a custom page class derived from the standard System.Web.UI.Page base class. It includes objects like CurrentUser as public properties. This seems to work OK. I like it even better.
But I really don't know what's going on under the covers. Can anyone give an opinion on which approach is better and why?
Alternative suggestions for doing this are also welcome.
Update:
I've done some checking use trace.axd and Trace.Write and it looks like neither the masterpage version nor the custom page class version "remember" the values between pages. The "get" methods have a line of code that checks if the User property is null, and if so, reads it from the session variable. This happens when a page accesses the property (Master.User or the derived class's this.User) for the first time on a given page, then subsequent requests can get the value (without going to the session variable).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Session 正是为了这个目的而设计的。它存储用户“会话”生命周期的相关数据,我认为是 20 分钟或者用户关闭浏览器。如果您担心 User 对象的大小,您可以只存储 ID,然后从数据库检索对象,但您必须权衡数据库往返的权衡。然而,我认为它通常与 Session 无关,因为它不像 ViewState 那样发送到客户端。您还可以使用 Curious Geek 示例中的属性公开此会话值,但使用 Session 对象而不是 ViewState 对象。
在母版页上设置该属性将不起作用,因为它只是当前实例化类的成员,该类在每个请求结束时都会进行垃圾收集,因此您在下一个请求中不会拥有它。
以下是 ASP.NET 中状态管理的总结:
http://msdn.microsoft.com/en-us/library/75x4ha6s。 ASPX
Session was designed for exactly this purpose. It stores pertinent data for the lifetime of the "session" of the user, which I think is 20 minutes or the user closes the browser. If you are concerned about the size of your User object, you can just store the ID, and then retrieve the object from the DB, but you have to weigh the tradeoff of the DB roundtrip. I don't think it's usually concern with Session, however, because it's not sent to the client like ViewState is. You could also expose this session value with a property like in Curious Geek's example, but use the Session object instead of the ViewState object.
Setting the property on the Master page won't work because that is only a member of the currently instantiated class which gets garbage collected at the end of each request, so you won't have it on the next request.
Here's a summary of state management in ASP.NET:
http://msdn.microsoft.com/en-us/library/75x4ha6s.aspx
我同意你
最新
的想法。让公共页面基类公开您的用户
类型的公共属性。该属性应该从会话密钥读取/写入会话密钥。我们还有另一个名为 GoBackPage 的属性,它在当前页面的视图状态中存储上一页的 URL。您仍然可以超越这一点,仅在视图状态中存储 UserId,并在公共页面基类中公开一个属性,该属性将从视图状态中读取 UserId 并返回 User 对象。
I agree with you
latest
idea. Have the common page base class expose a public property of type youruser
. The property should read/write from/to a session key. We also have another property called GoBackPage that stores the URL of the previous page in view-state of the current page.You can still go beyond this and store only the UserId in view-state and expose a property in the common page-base class that will read the UserId from the view-state and return the User Object.
到目前为止,最好的解决方案看起来像这样:
然后在任何webpage.aspx.cs上,您可以执行以下操作:
第一次使用它时它将命中会话,但后续在特定页面上使用响应会更快。
各种类和代码隐藏中的代码现在看起来更加整洁,因为我不需要每次使用它时都从 Session 中读取和转换我的 User 对象(和 Company 对象等)。
So thus far the best solution looks something like this:
Then on any webpage.aspx.cs, you can do something like this:
It will hit the Session the first time you use it, but subsequent uses on a particular page response will be faster.
Code within the various classes and code-behinds now looks a lot neater because I don't need to read and cast my User object (and Company object, etc) from Session every time I use it.