ASP.NET MVC의 세션 변수


169

사용자가 특정 요청을하는 웹 사이트 내에서 여러 웹 페이지를 탐색 할 수있는 웹 응용 프로그램을 작성 중입니다. 사용자가 입력 한 모든 정보는 내가 만든 개체에 저장됩니다. 문제는 웹 사이트의 어느 부분에서 나이 객체에 액세스해야하며 이것을 달성하는 가장 좋은 방법을 모른다는 것입니다. 한 가지 해결책은 세션 변수를 사용하는 것이지만 ASP .net MVC에서 사용하는 방법을 모르겠습니다. 세션 변수는 어디에서 선언합니까? 다른 방법이 있습니까?


3
웹 사이트와 웹 응용 프로그램 개념을 혼합하고 있습니다 ... 같은 것은 아닙니다.
adripanico

1
데이터베이스가 필요한 것 같습니다
Coops

답변:


123

사물이 실제로 세션 상태에 속하는지 생각하고 싶을 것입니다. 이것은 내가 지금하고있는 일이며, 모든 것에 대한 강력한 유형의 접근 방식이지만 세션 컨텍스트에 넣을 때주의해야합니다. 일부 사용자의 것이기 때문에 모든 것이 있어야하는 것은 아닙니다.

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

32
ASP MVC를 사용하는 경우 HttpContext.Current.Session의 실제 Session 개체를 사용하지 않고 System.Web.Abstractions.dll의 새로운 HttpSessionStateWrapper & HttpSessionStateBase를 사용하는 경우 Factory 또는 DI를 사용하여 세션을 가져 오는 것이 좋습니다.
Paul

6
세션 변수에 무언가를 어떻게 할당합니까? (방금 액세스와 반대)
raklos

31
"OnSessionStart"이벤트가 무엇이며 어떻게 "후킹"하는지 알아
내려는 사람들

5
@Paul 예를 제공 할 수 있습니까? HttpSessionStateWrapper를 사용하는 예를 찾지 못하는 것 같습니다.
Joseph Woodward

4
이 코멘트 스레드 제안 @AjayKelkar 답을 제시하는 것이 더 낫지 "ASP MVC가 사용되는 경우가 HttpContext.Current.Session에서 실제 세션 객체를 사용하지 않는하지만 새로운 HttpSessionStateWrapper & HttpSessionStateBase 사용하는 것이 바람직하다"
협동 조합

48

대답은 정확하지만 ASP.NET MVC 3 앱에서 구현하는 데 어려움을 겪었습니다. 컨트롤러에서 Session 객체에 액세스하고 싶었는데 왜 "인스턴스가 객체 오류의 인스턴스로 설정되지 않았습니다"라는 메시지가 계속 나타나는지 알 수 없었습니다. 내가 알았던 것은 컨트롤러에서 다음을 수행하여 세션에 액세스하려고 할 때 해당 오류가 계속 발생한다는 것입니다. 이것은 this.HttpContext가 Controller 객체의 일부이기 때문입니다.

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

그러나 내가 원했던 것은 위의 답변이 Global.asax.cs에서 사용하도록 제안하기 때문에 System.Web 네임 스페이스의 일부인 HttpContext였습니다. 따라서 다음을 명시 적으로 수행해야했습니다.

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

이것은 내가 MO 주변에 있지 않은 것을했는지 확실하지 않지만 누군가에게 도움이되기를 바랍니다.


6
System.Web.HttpContext.Current.Session [ "blah"] = 값
Tomasz Iniewicz

21

장소에 대해 "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!";

2
따라서이 클래스에는 두 가지 책임이 있습니다. 단일 인스턴스를 유지하고 변수를 저장하는 것입니다. IOC 컨테이너를 사용하여 싱글 톤을 갖습니다.
Jowen

1
이미 하나의 설정을 가지고 있다면 아마도 완전한 인젝션 가능 세션 서비스도 만들 것입니다. 컨시스턴시가 아마도 가장 큰 이점 일 것입니다. 작은 기능 세트 웹 응용 프로그램 에이 코드를 사용하는 것이 더 좋습니다.
Dead.Rabit

14

asp.net mvc를 사용하는 경우 세션에 액세스하는 간단한 방법이 있습니다.

컨트롤러에서 :

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

보기에서 :

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

이것이 세션 변수에 액세스하는 가장 좋은 방법은 아니지만 직접 경로입니다. 따라서 빠른 프로토 타입 제작시주의해서 사용하고, 적절 해지면 래퍼 / 컨테이너 및 OnSessionStart를 사용하십시오.

HTH


2
흠 .. 가장 좋은 방법은? 컨트롤러의 세션에서 ViewState로 데이터를 전달해야합니까?
RredCat

2
이 방법의 수축을 설명 할 수 있습니까?
RredCat

1
그는 읽기 / 쓰기 방법을 사용하는 것이 가장 좋다고 생각했습니다. 동시성 / 스레드 사용에 따라 경쟁 조건을 피하기 위해 해당 읽기 / 쓰기 방법에서 잠금이 필요할 수도 있습니다.
DeepSpace101

13

이모 ..

  1. 뷰 / 마스터 페이지에서 세션을 참조하지 마십시오
  2. 세션 사용을 최소화하십시오. MVC는이를 위해 TempData obj를 제공하는데, 이는 기본적으로 서버로 단일 여행을하는 세션입니다.

# 1과 관련하여 Session 객체가 나타내는 모든 것에 액세스 할 수있는 속성이있는 강력한 형식의 Master View가 있습니다 .... 내 인스턴스에서 stongly typed Master View는 일반적으로 강력하게 형식화 된 View Pages와 관련하여 약간의 유연성을 제공합니다.

ViewMasterPage<AdminViewModel>

AdminViewModel
{
    SomeImportantObjectThatWasInSession ImportantObject
}

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

그리고...

ViewPage<AdminViewModel<U>>

7

asp.net mvc에 대해서는 잘 모르지만 이것이 일반적인 .net 웹 사이트에서해야 할 일입니다. asp.net mvc에서도 작동합니다.

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

쉽게 접근 할 수 있도록 메소드 안에 넣을 것입니다. HTH



7

세션에 액세스하는 내 방법은 다양한 필드 이름과 유형을 캡슐화하는 도우미 클래스를 작성하는 것입니다. 이 예제가 도움이되기를 바랍니다.

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

    }
}

나는 당신의 대답을 좋아합니다 ... 당신은 무슨 일이 일어나고 있는지 더 자세히 설명 할 수 있습니까? 왜 이것이이 스레드의 다른 대답과 대조되는 더 나은 접근 방식입니까?
Chef_Code

6

좋은 답변이지만 항상 세션에 의존하지 않도록주의하십시오. 그렇게하는 것은 쉽고 빠르며 물론 작동하지만 모든 상황에 적합하지는 않습니다.

예를 들어 호스팅에서 세션 사용을 허용하지 않는 시나리오 나 웹 팜에 있거나 공유 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<ICustomClassProvider>().UsingFactoryMethod(
                () => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
    }

4

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

두 번째 인수는 선택 사항입니다. 세션에 값이 없으면 해당 키의 세션 데이터를 채우는 데 사용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.