我应该如何将会话状态集成到 ASP.NET MVC 应用程序中?

发布于 2024-07-13 01:48:37 字数 2080 浏览 5 评论 0原文

我正在寻找有关如何在 ASP.NET MVC 应用程序中使用 Session 的想法? 特别是当使用母版页并尝试将数据获取到母版页而不绕过控制器时。 这个问题一开始是我问了很多小问题,但后来我设法将其塑造成一个解决方案,该解决方案尚未实施,但在某种程度上是可行的。 如有任何反馈,我们将不胜感激。


我提出的解决方案又名“除非有人说停止,否则我将要实现的解决方案!”

我的模型类继承自 ModelBase - 其中包含母版页所需的信息(每个页面只有一个视图) )对于它在标头或页脚中显示的某些内容以及基于登录者的配置驱动设置。

我的最佳解决方案如下 - 此处显示“产品页面”:

假设:我在某个时刻已经在会话中保留了某些数据 - 例如,可能是通过网关页面传入的 partnerIdcurrentLoggedInUserEmail 属性或完全成熟的对象。

我有一个 ModelBase 类,每个模型 - 例如 ProductModel 都继承自该类

我有一个 MySiteControllerBase 类(继承自 Controller) - 它是 ProductController 的子类。

ProductController 的操作方法中,我使用 'new ProductModel()' 创建产品视图的模型。 该模型类本身对会话一无所知,也不知道如何填充ModelBase。 它本质上甚至不知道 ModelBase - 它只是继承自它。 我的链式构造函数不执行任何操作(因为我不想传递它 Session)。

我为所有采用模型参数的重载重写了 MySiteControllerBase 中的View(...)。 我检查该参数是否属于 ModelBase 类型,如果是,我会填充 partneridcurrentLoggedInuserEmail 等属性。 幸运的是,因为我位于一个继承自 Controller 的类中,所以我可以直接访问 Session,因此我可以直接将它们从那里取出。

此方法意味着仅由我执行“return View(model)”即可自动填充 ModelBase 上的属性。 但是,如果 ProductModel 的模型需要访问 ModelBase 上定义的任何内容,则会出现一个明显的问题。 它将变为 null,因为它尚未填充。

这个问题可以通过将 Session 传递给 new ProductModel(session) 来解决,后者又将其沿着构造函数链传递给 new ModelBase(session)代码>. 我真的喜欢这个解决方案,因为我喜欢将模型视为一个非常愚蠢的数据结构,根本不应该知道任何外部数据结构。 另一个解决方案可能是即兴发挥,如果我发现 ProductController 需要使用 ModelBase 中定义的任何内容,我只需创建一个方法 MySiteControllerBase.UpdateModelBase( ProductModel, session) 以将其显式填充到 ProductController 中。 我希望这是清楚的!

我想到的其他问题是:

  • 单元测试怎么样? MVC 中是否有关于会话状态的任何抽象,或者我应该构建自己的抽象吗? 我在源代码中搜索了“会话”,但没有找到任何结果!
  • 会话跟踪如何与 MVC 中的 /REST/FUL/URLS 配合使用? cookie 关闭时是否有任何我需要了解的问题?
  • 我是否应该以不同于传统的方式看待会议?

I'm looking for thoughts on how should I use Session in an ASP.NET MVC application? Especially when using masterpages and tryin to just get the data to the masterpage without bypassing the controller. This question started off by me asking a lot of little questions, but then I managed to mould it into a solution which as yet I have not implemented but one which is somewhat workable. Would appreciate any feedback.


My proposed solution aka 'what i am about to implement unless someone says stop!'

I have my model classes inheriting from ModelBase -- which contains the information needed by the masterpage (there is only one view per page) for certain things it displays in the masthead or footer as well as configuration driven settings based upon who is logged in.

My best solution is as follows - shown here for a 'products page':

Assumption: I have at some point already stuck certain data in session - for instance perhaps a partnerId which came in through a gateway page, or a currentLoggedInUserEmail property or a fully blown object.

I have a ModelBase class from which every model - such as ProductModel inherits

I have a MySiteControllerBase class (inherits from Controller) - which is subclassed by ProductController.

In my action method in ProductController I create the model for the product view with 'new ProductModel()'. This model class itself knows nothing about session or how to populate ModelBase. It essentially doesn't even know about ModelBase - it just inherits from it. My chained constructor does nothing (because I don't want to pass it Session).

I override View(...) in MySiteControllerBase for all the overloads that take a model parameter. I check to see if that parameter is of type ModelBase and if it is I populate the properties such as partnerid and currentLoggedInuserEmail. Fortunately because I'm inside a class that inherits from Controller I have direct access to Session so i can pull them straight out of there.

This method means that the properties on ModelBase are automatically populated just by me doing 'return View(model)'. However there is an obvious issue if the model for ProductModel needs to access anything defined on ModelBase. It's going to get null because it isn't populated yet.

This issue can be solved by passing in Session to new ProductModel(session) which would in turn pass it up the constructor chain to new ModelBase(session). I really dont like that solution though becasue I like to think of a model as a pretty dumb data structure that shouldn't know about any external data constructs at all. Another solution might be to just wing it, and if i ever find that ProductController needs to consume anything defined in ModelBase that I just create a method MySiteControllerBase.UpdateModelBase(productModel, session) to explicitly populate it inside ProductController. I hope thats clear!

Other questions that come to mind are :

  • What about unit testing? Is there any abstraction around Session state in MVC or should I build my own? I did a search in the sourcecode for 'session' and nothing came up!
  • How does session tracking work with /REST/FUL/URLS in MVC? Are there any issues ith cookies off that I need to know about?
  • Should I think of session differently from how I traditionally have?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

做个ˇ局外人 2024-07-20 01:48:37

尽管原则上在 ASP.NET MVC 应用程序中使用 Session 并没有什么问题(嗯,至少没有比在其他 ASP.NET 应用程序中使用它更错误的了......),但我倾向于认为它应该是最后的手段,当其他事情不起作用时。

尽管您的问题通常写得很好,但您没有详细说明您建议在会话中存储的内容。 我在您的问题中找到的两个示例是:

  • 当前用户电子邮件
  • partnerid

用户的电子邮件地址已经可以从表单身份验证中获得(如果您正在使用该地址),并且可以将其添加到其他不支持的 ASP.NET 会员提供程序中已经支持了。 目前尚不清楚partnerid实际上是什么,但我怀疑Session是存储它的唯一可能的地方。

另一方面,您完全有可能需要存储您没有告诉我们的东西,而这些东西实际上只适合会话。

因此,在您沿着这条路走得太远之前,请确保其他解决方案尚未可用于您需要存储的数据。

Although there is nothing, in principle, wrong with using Session in ASP.NET MVC applications (well, at least nothing more wrong than using it in other ASP.NET applications...), I tend to feel it should be a last resort, when other things don't work.

Although your question is, generally, very well-written, you don't go into any great detail on what you propose to store in Session. The two examples I found in your question are:

  • Current user e-mail
  • partnerid

The user's e-mail address is already available from forms authentication, if you are using that, and can be added to other ASP.NET membership providers which don't already support it. It's not clear what partnerid actually is, but I'm skeptical that the Session is the only possible place to store it.

On the other hand, it's entirely possible that you need to store stuff you haven't told us about which would really only fit in the session.

So before you go too far down this road, make sure that other solutions are not already available for the data you need to store.

梦纸 2024-07-20 01:48:37

至于单元测试,您将需要一个假的 HttpContext 对象(从 HttpContextBase 扩展)和一个假的会话对象(从 SessionStateBase 扩展)。 或者您也可以像我们一样,使用 Phil Haacks HttpSimulator。 这不是一个完美的解决方案,但是当您使用 asp 执行任何操作时,有如此多的紧密耦合的对象连接在一起,因此您不会真正发现任何特别优雅的东西。 我们发现我们经常遇到它,因此值得抓住这些类并将它们放入辅助库中。

Cookie 按域工作,因此实际上不存在任何问题。 您始终可以将会话配置为进程内且无 cookie。

一般来说,会话​​中保留的内容要非常稀疏。 但这也适用于 Webform。

As for unit testing, you will need a fake HttpContext object (extend from HttpContextBase) and a fake session object (extend from SessionStateBase). Or you can do what we do, and use Phil Haacks HttpSimulator. Not a perfect solution, but there are so many tightly coupled objects that get wired together when you do anything with asp that you wont ever really find anything particularly elegant. We found we kept bumping into it so much that it was worth it to grab those classes and stick them in a helper library.

Cookies work by domain, so there isn't really any problems around that. You can always configure session to be in-proc as well and cookieless.

In general, be very sparse with what you keep in the session. But that goes for Webforms as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文