วิธีการเข้าถึงตัวแปรเซสชันจากคลาสใด ๆ ใน ASP.NET?


157

ฉันสร้างไฟล์คลาสในโฟลเดอร์ App_Code ในแอปพลิเคชันของฉัน ฉันมีตัวแปรเซสชัน

Session["loginId"]

ฉันต้องการเข้าถึงตัวแปรเซสชั่นนี้ในชั้นเรียนของฉัน แต่เมื่อฉันเขียนบรรทัดต่อไปนี้มันจะให้ข้อผิดพลาด

Session["loginId"]

ทุกคนสามารถบอกวิธีเข้าถึงตัวแปรเซสชันภายในคลาสที่สร้างในโฟลเดอร์ app_code ใน ASP.NET 2.0 (C #) ได้ไหม

คำตอบ:


363

(อัปเดตเพื่อความสมบูรณ์)
คุณสามารถเข้าถึงตัวแปรเซสชันจากหน้าหรือการควบคุมโดยใช้Session["loginId"]และจากคลาสใด ๆ (เช่นจากภายในไลบรารีคลาส) โดยใช้System.Web.HttpContext.Current.Session["loginId"].

แต่โปรดอ่านคำตอบเดิมของฉัน ...


ฉันมักจะใช้คลาส wrapper รอบ ๆ เซสชัน ASP.NET เพื่อทำให้การเข้าถึงตัวแปรเซสชันง่ายขึ้น:

public class MySession
{
    // private constructor
    private MySession()
    {
      Property1 = "default value";
    }

    // Gets the current session.
    public static MySession Current
    {
      get
      {
        MySession session =
          (MySession)HttpContext.Current.Session["__MySession__"];
        if (session == null)
        {
          session = new MySession();
          HttpContext.Current.Session["__MySession__"] = session;
        }
        return session;
      }
    }

    // **** add your session properties here, e.g like this:
    public string Property1 { get; set; }
    public DateTime MyDate { get; set; }
    public int LoginId { get; set; }
}

คลาสนี้เก็บอินสแตนซ์ของตัวเองหนึ่งตัวในเซสชัน ASP.NET และอนุญาตให้คุณเข้าถึงคุณสมบัติเซสชันของคุณในแบบที่ปลอดภัยจากคลาสใด ๆ เช่นนี้

int loginId = MySession.Current.LoginId;

string property1 = MySession.Current.Property1;
MySession.Current.Property1 = newValue;

DateTime myDate = MySession.Current.MyDate;
MySession.Current.MyDate = DateTime.Now;

วิธีนี้มีข้อดีหลายประการ:

  • มันช่วยให้คุณประหยัดจากการหล่อแบบจำนวนมาก
  • คุณไม่จำเป็นต้องใช้คีย์เซสชั่นแบบตายตัวตลอดการสมัคร (เช่น Session ["loginId"]
  • คุณสามารถจัดทำเอกสารรายการเซสชันของคุณโดยเพิ่มความคิดเห็นเอกสาร XML ในคุณสมบัติของ MySession
  • คุณสามารถเริ่มต้นตัวแปรเซสชั่นของคุณด้วยค่าเริ่มต้น (เช่นมั่นใจว่าพวกเขาจะไม่เป็นโมฆะ)

6
ไม่จำเป็นต้องเขียนโค้ดใด ๆ ใช้ตามที่แสดงในคำตอบ เช่น "public int LoginId {get; set;}" -> นี่เรียกว่าคุณสมบัติอัตโนมัติ
M4N

4
หากคุณใช้. net 3.x คุณสามารถใช้คุณสมบัติอัตโนมัติดังที่แสดงในรหัสของฉัน ด้วย. net 2.x / 1.x สิ่งนี้ไม่พร้อมใช้งานและคุณต้องใช้ตัวรับ / setter ของคุณสมบัติของคุณเอง: private int _loginId; LoginId int สาธารณะ {รับ {return _loginId; } set {_loginId = value; }}
M4N

2
ดูดีตอนนี้ฉันคิดว่าฉันได้รับคำตอบของปัญหาของฉันแล้วและฉันก็ใช้วิธีของคุณมันสะอาดและง่ายต่อการดูแลตัวแปรเซสชันทั้งหมดของฉันในที่เดียว ขอบคุณ @Martin คุณยอดเยี่ยม
Prashant

23
@ M4N หวังว่าฉันจะสามารถแสดงความกตัญญูได้มากกว่า +1 นี่เป็นวิธีที่ฉันโปรดปรานในการจัดการกับเซสชัน / แคชในโครงการของฉัน รหัสของฉันแท้จริงขอบคุณ
Brandon Boone

4
@Kristopher ในขณะที่คุณสมบัติ 'ปัจจุบัน' เป็นแบบคงที่อินสแตนซ์ของ MySession ที่ส่งคืนไม่ใช่ ... วิธีการและคุณสมบัติคงที่มีความปลอดภัยในการใช้วิธีนี้
Darren

104

เข้าถึงเซสชันผ่านเธรด HttpContext: -

HttpContext.Current.Session["loginId"]

ขอบคุณแอนโทนี่ตันสำหรับขั้นตอนง่าย ๆ นี้
Kings

ขอบคุณแอนโทนี่ +1 มาก
Owais Qureshi

ขอบคุณ ลืมสิ่งที่ namespace เป็น :)
แอนโธนีฮอร์น

@AththonyWJones ฉันใช้วิธีการของคุณ แต่มีปัญหาคุณสามารถอธิบายฉันได้ไหมว่าฉันผิดหรือวิธีการใช้งานที่เหมาะสมคำถามของฉันstackoverflow.com/questions/45254279/…
adnan

และถ้าคุณต้องการแปลงเป็น HttpSessionStateBase: เซสชัน HttpSessionStateBase = ใหม่ HttpSessionStateWrapper (HttpContext.Current.Session); Re: stackoverflow.com/questions/5447611/…
sobelito

24

ปัญหาเกี่ยวกับวิธีแก้ปัญหาที่แนะนำคือสามารถทำลายคุณลักษณะด้านประสิทธิภาพบางอย่างที่มีอยู่ใน SessionState หากคุณใช้ที่เก็บข้อมูลเซสชันที่ไม่อยู่ในกระบวนการ ("โหมดเซิร์ฟเวอร์สถานะ" หรือ "โหมดเซิร์ฟเวอร์ SQL") ในโหมด oop ข้อมูลเซสชั่นจะต้องต่อเนื่องกันในตอนท้ายของการร้องขอหน้าและยกเลิกการเรียงหน้าตอนเริ่มต้นของการร้องขอหน้าซึ่งอาจมีค่าใช้จ่ายสูง เพื่อปรับปรุงประสิทธิภาพ SessionState พยายามยกเลิกการดีซีเรียลไลซ์เฉพาะสิ่งที่ต้องการโดยเฉพาะการดีซีเรียลไลซ์ตัวแปรเมื่อมีการเข้าถึงในครั้งแรกเท่านั้นและจะทำการซีเรียลไลเซชันใหม่ หากคุณมีตัวแปรเซสชันจำนวนมากและผลักพวกเขาทั้งหมดให้เป็นหนึ่งคลาสทุกอย่างในเซสชั่นของคุณจะถูกดีซีเรียลไลซ์ในทุกคำขอของเพจที่ใช้เซสชันและทุกอย่างจะต้องถูกทำให้เป็นอนุกรมอีกครั้ง สิ่งที่ควรพิจารณาหากคุณใช้เซสชันจำนวนมากและโหมด oop


4
+1 สำหรับการทำให้ดีขึ้น หากคุณไม่ได้ใช้ InProc สำหรับเซสชันดังนั้น Ernie จะถูกต้อง 100% อย่างไรก็ตาม InProc มีข้อ จำกัด มากเนื่องจากไม่รองรับ webfarms และจะหายไปหากแอปพลิเคชันเริ่มต้นใหม่ หมายเหตุด้วยค่าใช้จ่ายด้านประสิทธิภาพเรากำลังมองหาพรีเมี่ยม 20% ในการใช้โหมด State Server และมีการเพิ่มค่าใช้จ่ายในการทำให้เป็นอันดับ อย่างที่คุณจินตนาการได้ว่าอาจมีราคาแพง คุณสามารถหลีกเลี่ยงบางส่วนของค่าใช้จ่ายในการทำให้เป็นอันดับโดยการติดกับประเภทดั้งเดิม (เช่น int, สตริง, อักขระ, ไบต์, ฯลฯ ) วัตถุที่กำหนดเองจะต้องเผชิญกับอนุกรม ระวังผู้ใช้
Zack Jannsen

+1 ข้อดี การเปลี่ยนแปลงที่จะแต่งงานกับสองแนวคิดจะมีแต่ละคุณสมบัติในคลาส "เซสชัน" ที่กำหนดเองนี้เรียกเซสชัน asp.net เองแทนวัตถุขนาดใหญ่หนึ่งในเซสชัน ต้องทำการคัดเลือกนักแสดงที่ @ M4N หลีกเลี่ยงวิธีการ แต่อาจคุ้มค่าถ้าคุณอ่านเฉพาะบางครั้งในแต่ละครั้ง
eol

12

คำตอบที่นำเสนอก่อนหน้าของฉันจะให้คำตอบที่เหมาะสมกับปัญหาอย่างไรก็ตามฉันรู้สึกว่ามันสำคัญที่จะต้องเข้าใจว่าทำไมข้อผิดพลาดนี้จึงส่งผล:

Sessionทรัพย์สินของPageผลตอบแทนที่ตัวอย่างของการพิมพ์ที่HttpSessionStateสัมพันธ์กับการร้องขอโดยเฉพาะอย่างยิ่งที่ เป็นจริงเทียบเท่ากับการโทรPage.SessionPage.Context.Session

MSDNอธิบายว่ามันเป็นไปได้อย่างไร:

เพราะเพจ ASP.NET มีการอ้างอิงเริ่มต้นกับ namespace System.Web (ซึ่งมีHttpContextระดับ) คุณสามารถอ้างอิงสมาชิกของบนหน้าขอบโดยไม่มีการอ้างอิงระดับที่มีคุณสมบัติครบถ้วนที่จะHttpContextHttpContext

อย่างไรก็ตามเมื่อคุณพยายามเข้าถึงคุณสมบัตินี้ภายในคลาสใน App_Code คุณสมบัตินั้นจะไม่พร้อมใช้งานสำหรับคุณยกเว้นว่าคลาสของคุณมาจากคลาสเพจ

ทางออกของฉันสถานการณ์ผู้ทรงพบนี้คือการที่ฉันไม่เคยผ่านวัตถุหน้าชั้นเรียน ฉันค่อนข้างจะแยกวัตถุที่ต้องการจากเซสชันของหน้าและส่งพวกเขาไปยังชั้นเรียนในรูปแบบของการเก็บค่าชื่อ / อาร์เรย์ / รายการขึ้นอยู่กับกรณี


นั่นคือคำอธิบายที่ดีก็ช่วยให้ฉัน +1 สำหรับ :) ว่า
Owais Qureshi

1

ฉันมีข้อผิดพลาดเดียวกันเนื่องจากฉันพยายามจัดการตัวแปรเซสชันภายในคลาสเซสชันที่กำหนดเอง

ฉันต้องผ่านบริบทปัจจุบัน (system.web.httpcontext.current) ในชั้นเรียนแล้วทุกอย่างก็ใช้ได้ดี

แมสซาชูเซต


1

ใน asp.net core สิ่งนี้จะทำงานได้แตกต่างกัน:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

    public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

ที่มา: https://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/


0

สิ่งนี้ควรมีประสิทธิภาพมากขึ้นทั้งสำหรับแอปพลิเคชันและสำหรับนักพัฒนา

เพิ่มคลาสต่อไปนี้ในโครงการเว็บของคุณ:

/// <summary>
/// This holds all of the session variables for the site.
/// </summary>
public class SessionCentralized
{
protected internal static void Save<T>(string sessionName, T value)
{
    HttpContext.Current.Session[sessionName] = value;
}

protected internal static T Get<T>(string sessionName)
{
    return (T)HttpContext.Current.Session[sessionName];
}

public static int? WhatEverSessionVariableYouWantToHold
{
    get
    {
        return Get<int?>(nameof(WhatEverSessionVariableYouWantToHold));
    }
    set
    {
        Save(nameof(WhatEverSessionVariableYouWantToHold), value);
    }
}

}

นี่คือการดำเนินการ:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.