Asp.net mvc ASP.NET MVC-如何在控制器和视图以外的位置访问会话数据

Asp.net mvc ASP.NET MVC-如何在控制器和视图以外的位置访问会话数据,asp.net-mvc,session,Asp.net Mvc,Session,我们可以访问控制器和视图中的会话数据,如下所示: Session["SessionKey1"] 如何从控制器或视图以外的类访问会话值?我将使用依赖项注入,并将HttpContext实例(或仅会话)传递给需要访问会话的类。另一种方法是引用HttpContext.Current,但由于它是一个静态对象,因此测试起来会更加困难 public ActionResult MyAction() { var foo = new Foo( this.HttpContext );

我们可以访问控制器和视图中的会话数据,如下所示:

Session["SessionKey1"]

如何从控制器或视图以外的类访问会话值?

我将使用依赖项注入,并将HttpContext实例(或仅会话)传递给需要访问会话的类。另一种方法是引用HttpContext.Current,但由于它是一个静态对象,因此测试起来会更加困难

   public ActionResult MyAction()
   {

       var foo = new Foo( this.HttpContext );
       ...
   }


   public class Foo
   {
        private HttpContextBase Context { get; set; }

        public Foo( HttpContextBase context )
        {
            this.Context = context;
        }

        public void Bar()
        {
            var value = this.Context.Session["barKey"];
            ...
        }
   }

我自己还没有做过,但是Chad Meyer博客上的这个示例可能会有所帮助(来自这篇文章:)


您只需通过
HttpContext
调用它,如下所示:

HttpContext.Current.Session["MyValue"] = "Something";

我还将把所有会话变量包装到一个类文件中。这样,您就可以使用intelliSense来选择它们。这减少了代码中需要为会话指定“字符串”的步数。

这是我的解决方案版本。请注意,我也使用依赖项注入,唯一的主要区别是“session”对象是通过单例访问的

private iSession _Session;

private iSession InternalSession
{
    get
    {

        if (_Session == null)
        {                
           _Session = new SessionDecorator(this.Session);
        }
        return _Session;
    }
}
下面是SessionDecorator类,它使用装饰器模式围绕接口包装会话:

public class SessionDecorator : iSession
{
    private HttpSessionStateBase _Session;
    private const string SESSIONKEY1= "SESSIONKEY1";
    private const string SESSIONKEY2= "SESSIONKEY2";

    public SessionDecorator(HttpSessionStateBase session)
    {
        _Session = session;
    }

    int iSession.AValue
    {
           get
        {
            return _Session[SESSIONKEY1] == null ? 1 : Convert.ToInt32(_Session[SESSIONKEY1]);
        }
        set
        {
            _Session[SESSIONKEY1] = value;
        }
    }

    int iSession.AnotherValue
    {
        get
        {
            return _Session[SESSIONKEY2] == null ? 0 : Convert.ToInt32(_Session[SESSIONKEY2]);
        }
        set
        {
            _Session[SESSIONKEY2] = value;
        }
    }
}`

希望这有帮助:)

感谢您的回复。看起来有一些依赖注入框架。您建议使用哪种DI框架?有关于DI的必读文章吗?:)对于原始海报的要求,这似乎过于复杂了。@xraminx——不要把我的建议与DI框架混淆。我说的是使用DI,模式,而不是框架。其思想是将依赖项的实例传递给类,而不是让它创建一个或使用静态实例。通过模拟进行单元测试要容易得多。嘿嘿,在我读到这个答案之前,我从未真正“理解”过依赖注入这个术语,+1我相信Nick的答案(下面)一定是正确的答案。这很简单,不需要我注入更多的依赖项…@Nick——通过模拟静态HttpContext来尝试单元测试,看看这有多容易。我已经完成了--不,谢谢。仅供参考--框架设计者将HttpSessionStateBase和HttpContextBase引入框架的较新版本是有原因的,并且您可以通过修改控制器上下文来更改控制器中的HttpContext。它使单元测试您的操作变得更容易。原始海报从未询问过测试。他问他如何访问会话。这里您设置的值正确吗?我想访问相同的值。怎么做
public class SessionDecorator : iSession
{
    private HttpSessionStateBase _Session;
    private const string SESSIONKEY1= "SESSIONKEY1";
    private const string SESSIONKEY2= "SESSIONKEY2";

    public SessionDecorator(HttpSessionStateBase session)
    {
        _Session = session;
    }

    int iSession.AValue
    {
           get
        {
            return _Session[SESSIONKEY1] == null ? 1 : Convert.ToInt32(_Session[SESSIONKEY1]);
        }
        set
        {
            _Session[SESSIONKEY1] = value;
        }
    }

    int iSession.AnotherValue
    {
        get
        {
            return _Session[SESSIONKEY2] == null ? 0 : Convert.ToInt32(_Session[SESSIONKEY2]);
        }
        set
        {
            _Session[SESSIONKEY2] = value;
        }
    }
}`