当前位置:  开发笔记 > 后端 > 正文

ASP.NET MVC中的会话变量

如何解决《ASP.NETMVC中的会话变量》经验,为你挑选了9个好方法。

我正在编写一个Web应用程序,允许用户浏览网站内的多个网页,提出某些请求.用户输入的所有信息都将存储在我创建的对象中.问题是我需要从网站的任何部分访问此对象,我真的不知道实现这一目标的最佳方法.我知道一个解决方案是使用会话变量,但我不知道如何在asp .net MVC中使用它们.我会在哪里声明会话变量?还有其他方法吗?



1> John Leidegr..:

我认为你会想到事情是否真的属于会话状态.这是我发现自己经常做的事情,这是一个很好的强类型方法,但是在把事情放在会话上下文时你应该小心.不是所有东西都应该只是因为它属于某个用户.

在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,然后使用Factory或DI来获取Session.
对于试图找出"OnSessionStart"事件是什么以及如何"挂钩"它的人,请参阅http://stackoverflow.com/questions/1531125/asp-net-mvc-onsessionstart-event
你如何为会话变量分配一些东西?(而不是仅仅访问)
@Paul你能提供一个例子吗?我似乎无法找到任何使用HttpSessionStateWrapper的例子.
@AjayKelkar这个评论线程建议"如果正在使用ASP MVC,那么最好不要使用来自HttpContext.Current.Session的实际Session对象,而是使用新的HttpSessionStateWrapper和HttpSessionStateBase",这表明你的答案不是更好

2> Tomasz Iniew..:

答案在这里是正确的,但我努力在ASP.NET MVC 3应用程序中实现它.我想访问控制器中的Session对象,但无法弄清楚为什么我继续得到"实例未设置为Object错误的实例".我注意到在控制器中,当我尝试通过执行以下操作来访问会话时,我一直在收到该错误.这是因为this.HttpContext是Controller对象的一部分.

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

但是,我想要的是HttpContext,它是System.Web命名空间的一部分,因为这是上面建议在Global.asax.cs中使用的答案.所以我必须明确地做以下事情:

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

这对我有所帮助,不确定我是否在这里做了一些不是MO的东西,但我希望它对某人有所帮助!


System.Web.HttpContext.Current.Session ["blah"] = value
如何分配值?

3> Dead.Rabit..:

因为我不喜欢看到关于这个地方的"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容器来拥有一个单例.

4> robertz..:

如果您使用的是asp.net mvc,这是一种访问会话的简单方法.

来自控制器:

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

从一个视图:

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

这绝对不是访问会话变量的最佳方式,但它是直接路由.因此请谨慎使用(最好在快速原型制作过程中),并在适当时使用Wrapper/Container和OnSessionStart.

HTH


嗯..哪种方式最好?我应该从控制器上的Session传递数据到ViewState,不应该?
你能解释一下这种方法的限制吗?

5> E Rolnicki..:

好吧,恕我直言..

    永远不要在视图/母版页中引用会话

    最小化Session的使用.MVC为此提供了TempData obj,它基本上是一个用于单次访问服务器的Session.

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

ViewMasterPage

AdminViewModel
{
    SomeImportantObjectThatWasInSession ImportantObject
}

AdminViewModel : AdminViewModel where TModel : class
{
   TModel Content
}

然后...

ViewPage>



6> 小智..:

虽然我不知道asp.net mvc,但这是我们应该在普通的.net网站上做的事情.它也适用于asp.net mvc.

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

您可以将其放在方法中以便于访问.HTH


人们,在投票时留下一些有用的东西,谢谢.

7> Mangesh Pimp..:

有3种方法可以做到这一点.

    你可以直接访问 HttpContext.Current.Session

    你可以模拟 HttpContextBase

    为.创建扩展方法 HttpContextBase

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

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



8> shenku..:

这些家伙给出了很好的答案,但我会提醒你不要总是依赖会议.这样做既快捷又容易,当然会起作用,但在所有的cicrumstances中都不会很好.

例如,如果您遇到托管不允许使用会话,或者您在Web场中或在共享SharePoint应用程序示例中的情况.

如果您想要一个不同的解决方案,您可以使用像Castle Windsor这样的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().UsingFactoryMethod(
                () => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
    }



9> 小智..:

我访问会话的方式是编写一个帮助程序类,其中封装了各种字段名称及其类型。我希望这个例子有帮助:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;

namespace dmkp
{
    /// 
    /// Encapsulates the session state
    /// 
    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; }
        }

    }
}

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有