Bagaimana cara mengakses variabel sesi dari kelas apa pun di ASP.NET?

157

Saya telah membuat file kelas di folder App_Code di aplikasi saya. Saya memiliki variabel sesi

Session["loginId"]

Saya ingin mengakses variabel sesi ini di kelas saya, tetapi ketika saya menulis baris berikut maka itu memberikan kesalahan

Session["loginId"]

Adakah yang bisa memberitahu saya cara mengakses variabel sesi dalam kelas yang dibuat di folder app_code di ASP.NET 2.0 (C #)

Prashant
sumber

Jawaban:

363

(Diperbarui untuk kelengkapan)
Anda dapat mengakses variabel sesi dari halaman mana pun atau mengontrol menggunakan Session["loginId"]dan dari kelas apa pun (misalnya dari dalam perpustakaan kelas), menggunakanSystem.Web.HttpContext.Current.Session["loginId"].

Tapi tolong baca terus untuk jawaban asli saya ...


Saya selalu menggunakan kelas wrapper di sekitar sesi ASP.NET untuk menyederhanakan akses ke variabel sesi:

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

Kelas ini menyimpan satu instance dari dirinya sendiri di sesi ASP.NET dan memungkinkan Anda untuk mengakses properti sesi Anda dengan cara yang aman dari kelas apa pun, misalnya seperti ini:

int loginId = MySession.Current.LoginId;

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

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

Pendekatan ini memiliki beberapa keuntungan:

  • itu menyelamatkan Anda dari banyak jenis casting
  • Anda tidak harus menggunakan kunci sesi kode keras di seluruh aplikasi Anda (mis. Sesi ["loginId"]
  • Anda dapat mendokumentasikan item sesi Anda dengan menambahkan komentar dokumen XML pada properti MySession
  • Anda dapat menginisialisasi variabel sesi Anda dengan nilai default (mis. memastikan mereka bukan nol)
M4N
sumber
6
Tidak perlu menulis kode apa pun, gunakan seperti yang ditunjukkan dalam jawaban. Misalnya "public int LoginId {get; set;}" -> ini disebut properti otomatis.
M4N
4
Jika Anda menggunakan .net 3.x Anda dapat menggunakan properti otomatis seperti yang ditunjukkan dalam kode saya. Dengan .net 2.x / 1.x ini tidak tersedia dan Anda harus mengimplementasikan pengambil / penyetel properti Anda sendiri: private int _loginId; LoginId public int {get {return _loginId; } set {_loginId = value; }}
M4N
2
Terlihat keren sekarang, saya pikir saya mendapat jawaban dari masalah saya, dan saya sudah menggunakan cara Anda, sangat bersih dan mudah untuk mempertahankan semua variabel sesi saya di satu tempat. Terima kasih @Martin, Anda LUAR BIASA.
Prashant
23
@ M4N, Berharap saya bisa mengucapkan terima kasih sedikit lebih dari +1. Ini telah menjadi cara favorit saya untuk berurusan dengan sesi / cache di proyek saya. Kode saya, secara harfiah, berterima kasih kepada Anda.
Brandon Boone
4
@ Kristopher sementara properti 'Lancar' statis, contoh MySession yang dikembalikan tidak ... jadi tidak masalah. Metode dan properti statis aman digunakan dengan cara ini.
Darren
104

Akses Sesi melalui utas HttpContext: -

HttpContext.Current.Session["loginId"]
AnthonyWJones
sumber
Terima kasih banyak Anthony untuk langkah sederhana ini.
Raja
Terima kasih banyak Anthony, +1 untuk itu
Owais Qureshi
Terima kasih. Lupa apa namespace itu :)
Anthony Horne
@AnthonyWJones saya menggunakan metode Anda, tetapi memiliki masalah, dapatkah Anda menjelaskan kepada saya, di mana saya salah atau apa cara yang tepat untuk digunakan, pertanyaan saya stackoverflow.com/questions/45254279/…
adnan
dan jika Anda ingin mengonversi ke HttpSessionStateBase: Sesi HttpSessionStateBase = HttpSessionStateWrapper baru (HttpContext.Current.Session); re: stackoverflow.com/questions/5447611/...
sobelito
24

Masalah dengan solusi yang disarankan adalah ia dapat memecah beberapa fitur kinerja yang dibangun ke dalam SessionState jika Anda menggunakan penyimpanan sesi yang tidak dalam proses. ("Mode Server Negara" atau "Mode SQL Server"). Dalam mode oop, data sesi perlu diserialisasi pada akhir permintaan halaman dan deserialized pada awal permintaan halaman, yang bisa mahal. Untuk meningkatkan kinerja, SessionState berupaya untuk hanya melakukan deserialisasi apa yang diperlukan oleh hanya variabel deserialisasi ketika diakses pertama kali, dan hanya menserialisasi ulang dan mengganti variabel yang diubah. Jika Anda memiliki banyak variabel sesi dan mendorong semuanya menjadi satu kelas, pada dasarnya semua yang ada di sesi Anda akan di-deserialisasi pada setiap permintaan halaman yang menggunakan sesi dan semuanya perlu diserialisasi lagi walaupun hanya 1 properti yang diubah karena kelas diubah. Hanya sesuatu yang perlu dipertimbangkan jika Anda menggunakan banyak sesi dan mode oop.

Ernie
sumber
4
+1 untuk menyatukan ini. Jika Anda tidak menggunakan InProc untuk Session, maka Ernie 100% benar. Lagipula InProc sangat terbatas, karena tidak mendukung pertanian web dan akan hilang jika aplikasi dimulai kembali. Catatan, berdasarkan biaya kinerja kami melihat premi 20% dalam menggunakan mode Server Negara, dan biaya serialisasi ditambahkan di atas itu. Seperti yang Anda bayangkan ini bisa mahal. Anda dapat menghindari beberapa overhead serialisasi dengan tetap menggunakan tipe primitif (mis. Int, string, char, byte, dll.). Objek khusus akan dihadapkan dengan serialisasi. Hati-hati pengguna.
Zack Jannsen
+1 Poin bagus. Perubahan yang akan menggabungkan kedua konsep tersebut adalah memiliki masing-masing properti pada kelas "sesi" khusus ini memanggil sesi asp.net itu sendiri alih-alih satu objek besar dalam sesi. Harus melakukan casting tipe yang menghindari pendekatan @ M4N, tetapi mungkin layak jika Anda hanya membaca beberapa sesi setiap kali.
eol
12

Jawaban yang disajikan sebelum saya memberikan solusi tepat untuk masalah ini, namun, saya merasa penting untuk memahami mengapa hasil kesalahan ini:

The Sessionmilik Pagemengembalikan sebuah instance dari jenis HttpSessionStaterelatif terhadap permintaan tertentu. Page.Sessionsebenarnya setara dengan menelepon Page.Context.Session.

MSDN menjelaskan bagaimana ini mungkin:

Karena halaman ASP.NET berisi referensi default ke System.Web namespace (yang berisi HttpContextkelas), Anda dapat mereferensikan anggota HttpContextpada halaman .aspx tanpa referensi kelas yang memenuhi syarat untuk HttpContext.

Namun, ketika Anda mencoba mengakses properti ini dalam suatu kelas di App_Code, properti itu tidak akan tersedia untuk Anda kecuali kelas Anda berasal dari Kelas Halaman.

Solusi saya untuk skenario yang sering ditemui ini adalah bahwa saya tidak pernah melewatkan objek halaman ke kelas . Saya lebih suka mengekstrak objek yang diperlukan dari halaman Session dan meneruskannya ke Kelas dalam bentuk koleksi nilai-nama / Array / Daftar, tergantung pada kasusnya.

Cerebrus
sumber
Itu penjelasan yang bagus, itu membantu saya memberi +1 untuk itu :)
Owais Qureshi
1

Saya memiliki kesalahan yang sama, karena saya mencoba memanipulasi variabel sesi di dalam kelas Sesi kustom.

Saya harus meneruskan konteks saat ini (system.web.httpcontext.current) ke dalam kelas, dan kemudian semuanya berjalan dengan baik.

MA

MunsterMan
sumber
1

Dalam inti asp.net ini berfungsi berbeda:

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

Sumber: https://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/

Matty
sumber
0

Ini harus lebih efisien baik untuk aplikasi dan juga untuk pengembang.

Tambahkan kelas berikut ke proyek web Anda:

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

}

Berikut implementasinya:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Kapten Amerika
sumber