Sesi null di ASP.Net MVC Controller Constructors


89

Mengapa Sesi null di konstruktor Pengontrol? Itu dapat diakses dari metode Tindakan. Agaknya, karena kerangka kerja Perutean MVC bertanggung jawab untuk memperbarui Pengontrol, kerangka tersebut belum (kembali) membuat Sesi pada saat itu.

Adakah yang tahu jika ini memang disengaja dan, jika demikian, mengapa?

[Saya telah berhasil mengatasi masalah ini dengan menggunakan Pola Pemuatan Malas.]

Jawaban:


80

Andrei benar - nilainya null karena saat berjalan di bawah kerangka kerja ASP.NET MVC, HttpContext (dan karenanya HttpContext.Session) tidak disetel saat kelas pengontrol dibuat seperti yang Anda harapkan, tetapi disetel ("diinjeksi") nanti oleh kelas ControllerBuilder. Jika Anda ingin pemahaman yang lebih baik tentang siklus hidup Anda dapat menarik kerangka kerja ASP.NET MVC (sumber tersedia), atau merujuk ke: halaman ini

Jika Anda perlu mengakses Sesi, salah satu cara adalah dengan menimpa metode "OnActionExecuting" dan mengaksesnya di sana, karena akan tersedia pada saat itu.

Namun, seperti yang disarankan Andrei, jika kode Anda bergantung pada Sesi maka akan berpotensi sulit untuk menulis pengujian unit, jadi mungkin Anda dapat mempertimbangkan untuk menggabungkan Sesi dalam kelas pembantu yang kemudian dapat ditukar dengan yang berbeda, non- versi web saat menjalankan pengujian unit, oleh karena itu lepaskan pengontrol Anda dari web.


3
Saya tidak yakin ini adalah pernyataan yang tepat tentang HttpContext. Ini sebenarnya dibangun tepat di awal seluruh aliran. Anda dapat membaca sedikit tentang aliran mendetail di sini beletsky.net/2011/06/inside-aspnet-mvc-route-to-mvchanlder.html atau Anda dapat menggunakan reflektor dan menemukan diri Anda ketika httpContext telah dibuat - garis sekitar 1556 di httpruntime .cs.
Alexey Shcherbak

@AlexeyShcherbak Ini mungkin sudah dibangun - OP adalah tentang apakah itu telah ditetapkan pada properti Sesi pengontrol MVC. yaitu Sesi HttpSessionStateBase publik {get; } di System.Web.Mvc.Controller Ini adalah hal yang berbeda.
MemeDeveloper

62

Selain jawaban lain di sini, meskipun Controller.Sessiontidak diisi di konstruktor, Anda masih dapat mengakses sesi melalui:

System.Web.HttpContext.Current.Session

dengan peringatan standar bahwa hal ini berpotensi mengurangi kemampuan pengujian pengontrol Anda.


3
Jenis untuk masing-masing dari dua properti sesi ini berbeda, yang mungkin penting jika Anda ingin menyimpan referensi ke status sesi itu sendiri.
BrianCooksey

@ BrianCooksey apa bedanya?
MichaelMao

1
Controller.Session berjenis System.Web.HttpSessionStateBase (lihat msdn.microsoft.com/en-us/library/… ) tetapi System.Web.HttpContext.Current.Session berjenis System.Web.SessionState.HttpSessionState (lihat msdn .microsoft.com / en-us / library /… )
BrianCooksey

Jawaban lama, tetapi ingin mengatakan itu System.Web.HttpContext.Current.Sessionjuga nulldi instanciator VS2019 MVC.
jp2code

Anda bisa mendapatkan HttpSessionStateBase dari HttpSessionState dengan membungkusnya menggunakan konstruktor HttpSessionStateWrapper.
Fabricio

11

Sesi disuntikkan nanti dalam siklus hidup. Mengapa Anda membutuhkan sesi dalam konstruktor? Jika Anda membutuhkannya untuk TDD, Anda harus membungkus sesi menjadi objek yang dapat dipermainkan.


1
Untuk menambah Andrei Rinea, ini adalah contoh spesifik dari teknik yang disebutkan olehnya: iridescence.no/post/…
murki

4
Saya ingin mengakses Sesi selama konstruktor saya sehingga saya dapat memiliki akses ke informasi sesi yang disimpan sebelumnya. Ya, saya dapat mengganti metode OnActionExecuting, tetapi ini jelas bukan solusi yang elegan.
Chris Arnold

8

Anda dapat mengganti metode Inisialisasi untuk menyetel sesi Anda.

protected override void Initialize(RequestContext requestContext)

2

Jika Anda menggunakan Wadah IoC, coba masukkan dan gunakan HttpSessionStateBasealih - alih Sessionobjek:

private static Container defaultContainer()
{
    return new Container(ioc =>
    {
        // session manager setup
        ioc.For<HttpSessionStateBase>()
           .Use(ctx => new HttpSessionStateWrapper(HttpContext.Current.Session)); 
    });
}

2

Jawaban ini mungkin bermanfaat bagi sebagian orang

Jika kita mengganti metode Inisialisasi maka kita harus menginisialisasi kelas dasar dengan konteks permintaan: base.Initialize (requestContext);

protected override void Initialize(RequestContext requestContext)
        {
            base.Initialize(requestContext);
           

        }

Berguna. Perhatikan bahwa tanda tangan metode protected override void Initialize(System.Web.Routing.RequestContext requestContext).
Martin_W
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.