asp.net-mvc ASP.NET MVC 中的会话变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/560084/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 23:20:23  来源:igfitidea点击:

Session variables in ASP.NET MVC

asp.net-mvcsessionsession-variables

提问by Draco

I am writing a web application that will allow a user to browse to multiple web pages within the website making certain requests. All information that the user inputs will be stored in an object that I created. The problem is that I need this object to be accessed from any part of the website and I don't really know the best way to accomplish this. I know that one solution is to use session variables but I don't know how to use them in asp .net MVC. And where would I declare a session variable? Is there any other way?

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

采纳答案by John Leidegren

I would think you'll want to think about if things really belong in a session state. This is something I find myself doing every now and then and it's a nice strongly typed approach to the whole thing but you should be careful when putting things in the session context. Not everything should be there just because it belongs to some user.

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

in global.asax hook the OnSessionStart event

在 global.asax 挂钩 OnSessionStart 事件

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

From anywhere in code where the HttpContext.Current property != null you can retrive that object. I do this with an extension method.

从代码中 HttpContext.Current 属性 != null 的任何地方,您都可以检索该对象。我用扩展方法来做到这一点。

public static MySessionObject GetMySessionObject(this HttpContext current)
{
    return current != null ? (MySessionObject)current.Session["__MySessionObject"] : null;
}

This way you can in code

这样你就可以在代码中

void OnLoad(...)
{
    var sessionObj = HttpContext.Current.GetMySessionObject();
    // do something with 'sessionObj'
}

回答by Tomasz Iniewicz

The answer here is correct, I however struggled to implement it in an ASP.NET MVC 3 app. I wanted to access a Session object in a controller and couldn't figure out why I kept on getting a "Instance not set to an instance of an Object error". What I noticed is that in a controller when I tried to access the session by doing the following, I kept on getting that error. This is due to the fact that this.HttpContext is part of the Controller object.

这里的答案是正确的,但是我很难在 ASP.NET MVC 3 应用程序中实现它。我想访问控制器中的 Session 对象,但不明白为什么我一直收到“实例未设置为对象错误的实例”。我注意到的是,当我尝试通过执行以下操作访问会话时,在控制器中,我不断收到该错误。这是因为 this.HttpContext 是 Controller 对象的一部分。

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

However, what I wanted was the HttpContext that's part of the System.Web namespace because this is the one the Answer above suggests to use in Global.asax.cs. So I had to explicitly do the following:

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

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

this helped me, not sure if I did anything that isn't M.O. around here, but I hope it helps someone!

这对我有帮助,不确定我是否在这里做了任何不是 MO 的事情,但我希望它可以帮助某人!

回答by Dead.Rabit

Because I dislike seeing "HTTPContext.Current.Session" about the place, I use a singleton pattern to access session variables, it gives you an easy to access strongly typed bag of data.

因为我不喜欢看到有关该地方的“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; }

    // ...

then you can access your data from anywhere:

那么您就可以从任何地方访问您的数据:

SessionSingleton.Current.SessionVariable = "Hello, World!";

回答by robertz

If you are using asp.net mvc, here is a simple way to access the session.

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

From a Controller:

从控制器:

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

From a View:

从观点来看:

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

This is definitely not the best way to access your session variables, but it is a direct route. So use it with caution (preferably during rapid prototyping), and use a Wrapper/Container and OnSessionStart when it becomes appropriate.

这绝对不是访问会话变量的最佳方式,但它是一种直接途径。因此请谨慎使用它(最好在快速原型制作期间),并在合适的时候使用 Wrapper/Container 和 OnSessionStart。

HTH

HTH

回答by E Rolnicki

Well, IMHO..

嗯,恕我直言..

  1. never reference a Session inside your view/master page
  2. minimize your useage of Session. MVC provides TempData obj for this, which is basically a Session that lives for a single trip to the server.
  1. 永远不要在您的视图/母版页中引用会话
  2. 尽量减少您对 Session 的使用。MVC 为此提供了 TempData obj,它基本上是一个 Session,它只存在一次到服务器的行程。

With regards to #1, I have a strongly typed Master View which has a property to access whatever the Session object represents....in my instance the stongly typed Master View is generic which gives me some flexibility with regards to strongly typed View Pages

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

ViewMasterPage<AdminViewModel>

AdminViewModel
{
    SomeImportantObjectThatWasInSession ImportantObject
}

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

and then...

进而...

ViewPage<AdminViewModel<U>>

回答by Daniel

My way of accessing sessions is to write a helper class which encapsulates the various field names and their types. I hope this example helps:

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

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

    }
}

回答by Mangesh Pimpalkar

There are 3 ways to do it.

有3种方法可以做到。

  1. You can directly access HttpContext.Current.Session

  2. You can Mock HttpContextBase

  3. Create a extension method for HttpContextBase

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

  2. 你可以模拟 HttpContextBase

  3. 创建扩展方法 HttpContextBase

I prefer 3rd way.This link is good reference.

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

Get/Set HttpContext Session Methods in BaseController vs Mocking HttpContextBase to create Get/Set methods

Get/Set HttpContext Session Methods in BaseController vs Mocking HttpContextBase 创建 Get/Set 方法

回答by DotNET

Although I don't know about asp.net mvc, but this is what we should do in a normal .net website. It should work for asp.net mvc also.

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

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

You would put this inside a method for easy access. HTH

你可以把它放在一个方法中以便于访问。HTH

回答by shenku

Great answers from the guys but I would caution you against always relying on the Session. It is quick and easy to do so, and of course would work but would not be great in all cicrumstances.

这些人的回答很好,但我会告诫你不要总是依赖 Session。这样做既快捷又容易,当然会起作用,但在所有情况下都不会很好。

For example if you run into a scenario where your hosting doesn't allow session use, or if you are on a web farm, or in the example of a shared SharePoint application.

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

If you wanted a different solution you could look at using an IOC Containersuch as Castle Windsor, creating a provider class as a wrapper and then keeping one instance of your class using the per request or session lifestyle depending on your requirements.

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

The IOC would ensure that the same instance is returned each time.

IOC 将确保每次返回相同的实例。

More complicated yes, if you need a simple solution just use the session.

更复杂的是,如果您需要一个简单的解决方案,只需使用会话即可。

Here are some implementation examples below out of interest.

下面是一些出于兴趣的实现示例。

Using this method you could create a provider class along the lines of:

使用此方法,您可以按照以下方式创建提供程序类:

public class CustomClassProvider : ICustomClassProvider
{
    public CustomClassProvider(CustomClass customClass)
    { 
        CustomClass = customClass;
    }

    public string CustomClass { get; private set; }
}

And register it something like:

并注册它,例如:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
            Component.For<ICustomClassProvider>().UsingFactoryMethod(
                () => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
    }

回答by Ajay Kelkar

You can use ViewModelBase as base class for all models , this class will take care of pulling data from session

您可以使用 ViewModelBase 作为所有模型的基类,此类将负责从会话中提取数据

class ViewModelBase 
{
  public User CurrentUser 
  {
     get { return System.Web.HttpContext.Current.Session["user"] as User };
     set 
     {
        System.Web.HttpContext.Current.Session["user"]=value; 
     }
  }
}

You can write a extention method on HttpContextBase to deal with session data

可以在 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;
}

Use this like below in controller

在控制器中使用如下所示

User userData = HttpContext.FromSession<User>("userdata",()=> { return user object from service/db  }); 

The second argument is optional it will be used fill session data for that key when value is not present in session.

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