ASP.NET MVC 中的会话变量

我正在写一个网络应用程序,将允许用户浏览到网站内的多个网页,提出某些要求。用户输入的所有信息都将存储在我创建的对象中。问题是,我需要从网站的任何部分访问这个对象,我真的不知道最好的方式来实现这一点。我知道一个解决方案是使用会话变量,但我不知道如何在 ASP 中使用它们。网络 MVC。在哪里声明会话变量呢?还有别的办法吗?

309757 次浏览

我认为您应该考虑一下事物是否真的属于会话状态。这是我发现自己时不时会做的事情,对于整个事情来说,这是一个很好的强类型方法,但是在将事情放在会话上下文中时应该小心。并不是所有东西都应该存在,只因为它属于某个用户。

在 global.asax 中钩住 OnSessionStart 事件

void OnSessionStart(...)
{
HttpContext.Current.Session.Add("__MySessionObject", new MySessionObject());
}

从代码中 HttpContext。当前财产!= 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.net 的 mvc,但这是我们应该在一个正常的。网站。它也应该适用于 asp.net mvc。

YourSessionClass obj=Session["key"] as YourSessionClass;
if(obj==null){
obj=new YourSessionClass();
Session["key"]=obj;
}

你可以把它放在一个方法里面,方便访问。 高温

恕我直言。

  1. 永远不要在视图/母版页中引用会话
  2. 尽量减少会话的使用。MVC 为此提供了 TempData obj,它基本上是一个针对服务器的单次访问的 Session。

关于 # 1,我有一个强类型的主视图,它有一个属性可以访问 Session 对象表示的任何东西... ... 在我的实例中,强类型的主视图是通用的,这给了我一些关于强类型的视图页面的灵活性

ViewMasterPage<AdminViewModel>


AdminViewModel
{
SomeImportantObjectThatWasInSession ImportantObject
}


AdminViewModel<TModel> : AdminViewModel where TModel : class
{
TModel Content
}

然后..。

ViewPage<AdminViewModel<U>>

如果您正在使用 asp.net mvc,这里有一个访问会话的简单方法。

来自财务主管的信息:

{Controller}.ControllerContext.HttpContext.Session["{name}"]

视角:

<%=Session["{name}"] %>

这肯定不是访问会话变量的最佳方式,但它是一个直接路由。所以使用时要小心(最好是在快速成型期间) ,并在适当的时候使用 Wrapper/Container 和 onsessionStart。

高温

有三种方法可以做到这一点。

  1. 您可以直接访问 HttpContext.Current.Session

  2. 你可以模仿 HttpContextBase

  3. HttpContextBase创建扩展方法

我更喜欢第三种方式。这个链接是很好的参考。

获取/设置 BaseController 中的 HttpContext 会话方法与 Mocking HttpContextBase 创建 Get/Set 方法

这里的答案是正确的,但是我在 ASP.NET MVC 3应用程序中很难实现它。我想访问控制器中的 Session 对象,但不知道为什么总是得到“ Instance not set to an Instance of an Object error”。我注意到,在一个控制器中,当我尝试通过执行以下操作来访问会话时,我一直得到这个错误。这是因为。HttpContext 是 Controller 对象的一部分。

this.Session["blah"]
// or
this.HttpContext.Session["blah"]

然而,我想要的是 HttpContext,它是系统的一部分。Web 名称空间,因为上面的答案建议在 Global.asax.cs 中使用这个名称空间。所以我必须明确地做到以下几点:

System.Web.HttpContext.Current.Session["blah"]

这对我有帮助,虽然不确定我是否做了什么违反惯例的事,但我希望它能帮到别人!

他们的回答很棒,但我要提醒你不要总是依赖会议。这是迅速和容易做到这一点,当然会工作,但不会伟大的所有情况下。

例如,如果您遇到一个场景,您的主机不允许会话使用,或如果您是在一个网络场,或在一个共享 SharePoint 应用程序的例子。

如果需要不同的解决方案,可以考虑使用 IOC 容器(如 温莎城堡) ,创建一个提供程序类作为包装器,然后根据需求使用每个请求或会话生活方式保留类的一个实例。

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());
}

因为我不喜欢看“ HTTPContext”。现在。关于“会话”的地方,我使用一个单例模式来访问会话变量,它让你很容易访问强类型的数据包。

[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!";

您可以使用 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  });

第二个参数是可选的,当会话中不存在值时,它将用于填充该键的会话数据。

我访问会话的方法是编写一个 helper 类,它封装各种字段名及其类型。我希望这个例子有所帮助:

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; }
}


}
}