ASP.NET MVC 中的会话变量
Posted
技术标签:
【中文标题】ASP.NET MVC 中的会话变量【英文标题】:Session variables in ASP.NET MVC 【发布时间】:2010-10-08 06:53:56 【问题描述】:我正在编写一个 Web 应用程序,它允许用户浏览到网站内的多个网页并提出某些请求。用户输入的所有信息都将存储在我创建的对象中。问题是我需要从网站的任何部分访问此对象,而我真的不知道实现此目的的最佳方法。我知道一种解决方案是使用会话变量,但我不知道如何在 asp .net MVC 中使用它们。我将在哪里声明会话变量?有没有其他办法?
【问题讨论】:
您将网站和 Web 应用程序概念混为一谈……它们不是一回事。 听起来需要数据库 How to use sessions in an ASP.NET MVC 4 application?的可能重复 【参考方案1】:我想你会想考虑一下事情是否真的属于会话状态。这是我发现自己时常做的事情,它是一种很好的强类型方法,但是在将事情放在会话上下文中时应该小心。并不是所有的东西都应该因为它属于某个用户而存在。
在 global.asax 中钩住 OnSessionStart 事件
void OnSessionStart(...)
HttpContext.Current.Session.Add("__MySessionObject", new MySessionObject());
您可以从代码中 HttpContext.Current 属性 != null 的任何位置检索该对象。我使用扩展方法来做到这一点。
public static MySessionObject GetMySessionObject(this HttpContext current)
return current != null ? (MySessionObject)current.Session["__MySessionObject"] : null;
这样你就可以在代码中
void OnLoad(...)
var sessionObj = HttpContext.Current.GetMySessionObject();
// do something with 'sessionObj'
【讨论】:
如果正在使用 ASP MVC,那么最好不要使用来自 HttpContext.Current.Session 的实际 Session 对象,而是使用来自 System.Web.Abstractions.dll 的新 HttpSessionStateWrapper&HttpSessionStateBase 然后使用工厂或DI 获取 Session。 如何给会话变量赋值? (而不是仅仅访问) 对于那些试图弄清楚“OnSessionStart”事件是什么以及如何“挂钩”它的人,请参阅***.com/questions/1531125/… @Paul 你能举个例子吗?我似乎找不到任何使用 HttpSessionStateWrapper 的示例。 @AjayKelkar 此评论线程建议“如果正在使用 ASP MVC,那么最好不要使用来自 HttpContext.Current.Session 的实际 Session 对象,而是使用新的 HttpSessionStateWrapper&HttpSessionStateBase”,这表明你的答案不是更好【参考方案2】:这里的答案是正确的,但是我很难在 ASP.NET MVC 3 应用程序中实现它。我想访问控制器中的 Session 对象,但不知道为什么我不断收到“实例未设置为对象错误的实例”。我注意到的是,当我尝试通过执行以下操作访问会话时,在控制器中,我不断收到该错误。这是因为 this.HttpContext 是 Controller 对象的一部分。
this.Session["blah"]
// or
this.HttpContext.Session["blah"]
但是,我想要的是作为 System.Web 命名空间一部分的 HttpContext,因为这是上面的答案建议在 Global.asax.cs 中使用的那个。所以我必须明确地执行以下操作:
System.Web.HttpContext.Current.Session["blah"]
这对我有帮助,不确定我是否做了任何不是 M.O. 的事情。在这里,但我希望它可以帮助别人!
【讨论】:
System.Web.HttpContext.Current.Session["blah"] = value【参考方案3】:因为我不喜欢看到关于这个地方的“HTTPContext.Current.Session”,所以我使用单例模式来访问会话变量,它使您可以轻松访问强类型数据包。
[Serializable]
public sealed class SessionSingleton
#region Singleton
private const string SESSION_SINGLETON_NAME = "Singleton_502E69E5-668B-E011-951F-00155DF26207";
private SessionSingleton()
public static SessionSingleton Current
get
if ( HttpContext.Current.Session[SESSION_SINGLETON_NAME] == null )
HttpContext.Current.Session[SESSION_SINGLETON_NAME] = new SessionSingleton();
return HttpContext.Current.Session[SESSION_SINGLETON_NAME] as SessionSingleton;
#endregion
public string SessionVariable get; set;
public string SessionVariable2 get; set;
// ...
那么您可以从任何地方访问您的数据:
SessionSingleton.Current.SessionVariable = "Hello, World!";
【讨论】:
所以这个类有两个职责:维护单个实例,存储变量......我会使用 IOC 容器来拥有一个单例。 如果你已经有了一个设置,我可能也会制作一个成熟的可注入会话服务,不过,一致性可能是最大的优势,我更倾向于将此代码用于小功能集webapps.. webwizards,如果你愿意的话。 恐怕这是一种不好的做法,因为静态变量可以跨会话共享。【参考方案4】:如果您使用的是 asp.net mvc,这里是访问会话的简单方法。
来自控制器:
Controller.ControllerContext.HttpContext.Session["name"]
从一个角度来看:
<%=Session["name"] %>
这绝对不是访问会话变量的最佳方式,但它是直接路径。因此请谨慎使用(最好在快速原型制作期间),并在适当时使用 Wrapper/Container 和 OnSessionStart。
HTH
【讨论】:
hm.. 哪个是最好的方法?我应该将数据从控制器上的 Session 传递给 ViewState,不是吗? 您能解释一下这种方法的局限性吗? 我认为他的意思是最好有读/写方法。根据并发/线程使用情况,您可能还需要在这些读/写方法中加锁以避免竞争条件。【参考方案5】:好吧,恕我直言..
-
切勿在视图/母版页中引用会话
尽量减少会话的使用。 MVC 为此提供了 TempData obj,它基本上是一个 Session,只需要一次访问服务器即可。
关于#1,我有一个强类型主视图,它具有访问 Session 对象所代表的任何内容的属性....在我的实例中,强类型主视图是通用的,这给了我一些关于强类型的灵活性键入的查看页面
ViewMasterPage<AdminViewModel>
AdminViewModel
SomeImportantObjectThatWasInSession ImportantObject
AdminViewModel<TModel> : AdminViewModel where TModel : class
TModel Content
然后……
ViewPage<AdminViewModel<U>>
【讨论】:
【参考方案6】:虽然我不知道asp.net mvc,但这是我们在普通的.net网站中应该做的。它也应该适用于 asp.net mvc。
YourSessionClass obj=Session["key"] as YourSessionClass;
if(obj==null)
obj=new YourSessionClass();
Session["key"]=obj;
您可以将它放在一个方法中以便于访问。 高温
【讨论】:
【参考方案7】:有 3 种方法可以做到这一点。
可以直接访问
HttpContext.Current.Session
你可以模拟
HttpContextBase
为
HttpContextBase
创建扩展方法
我更喜欢第三种方式。这个链接是很好的参考。
Get/Set HttpContext Session Methods in BaseController vs Mocking HttpContextBase to create Get/Set methods
【讨论】:
【参考方案8】:我访问会话的方式是编写一个帮助类,它封装了各种字段名称及其类型。我希望这个例子有帮助:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;
namespace dmkp
/// <summary>
/// Encapsulates the session state
/// </summary>
public sealed class LoginInfo
private HttpSessionState _session;
public LoginInfo(HttpSessionState session)
this._session = session;
public string Username
get return (this._session["Username"] ?? string.Empty).ToString();
set this._session["Username"] = value;
public string FullName
get return (this._session["FullName"] ?? string.Empty).ToString();
set this._session["FullName"] = value;
public int ID
get return Convert.ToInt32((this._session["UID"] ?? -1));
set this._session["UID"] = value;
public UserAccess AccessLevel
get return (UserAccess)(this._session["AccessLevel"]);
set this._session["AccessLevel"] = value;
【讨论】:
我喜欢您的回答...您能否进一步详细说明正在发生的事情...以及为什么与此线程上的其他答案相比,这是一种更好的方法。【参考方案9】:这些家伙的回答很好,但我会提醒你不要总是依赖 Session。这样做既快速又容易,当然可以,但在所有情况下都不是很好。
例如,如果您遇到托管不允许会话使用的情况,或者您在网络场中,或者在共享 SharePoint 应用程序的示例中。
如果您想要一个不同的解决方案,您可以考虑使用IOC Container,例如Castle Windsor,创建一个提供程序类作为包装器,然后根据您的要求使用每个请求或会话生活方式保留您的类的一个实例.
IOC 将确保每次返回相同的实例。
更复杂的是,如果您需要一个简单的解决方案,只需使用会话。
出于兴趣,下面是一些实现示例。
使用此方法,您可以按照以下方式创建提供程序类:
public class CustomClassProvider : ICustomClassProvider
public CustomClassProvider(CustomClass customClass)
CustomClass = customClass;
public string CustomClass get; private set;
然后像这样注册它:
public void Install(IWindsorContainer container, IConfigurationStore store)
container.Register(
Component.For<ICustomClassProvider>().UsingFactoryMethod(
() => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
【讨论】:
【参考方案10】:您可以使用 ViewModelBase 作为所有模型的基类,该类将负责从会话中提取数据
class ViewModelBase
public User CurrentUser
get return System.Web.HttpContext.Current.Session["user"] as User ;
set
System.Web.HttpContext.Current.Session["user"]=value;
可以在HttpContextBase上写一个扩展方法来处理会话数据
T FromSession<T>(this HttpContextBase context ,string key,Action<T> getFromSource=null)
if(context.Session[key]!=null)
return (T) context.Session[key];
else if(getFromSource!=null)
var value = getFromSource();
context.Session[key]=value;
return value;
else
return null;
在控制器中像下面这样使用它
User userData = HttpContext.FromSession<User>("userdata",()=> return user object from service/db );
第二个参数是可选的,当会话中不存在值时,它将用于填充该键的会话数据。
【讨论】:
以上是关于ASP.NET MVC 中的会话变量的主要内容,如果未能解决你的问题,请参考以下文章