Làm thế nào để truy cập các biến phiên từ bất kỳ lớp nào trong ASP.NET?


157

Tôi đã tạo một tệp lớp trong thư mục App_Code trong ứng dụng của mình. Tôi có một biến phiên

Session["loginId"]

Tôi muốn truy cập các biến phiên này trong lớp của mình, nhưng khi tôi viết dòng sau thì nó báo lỗi

Session["loginId"]

Ai đó có thể cho tôi biết cách truy cập các biến phiên trong một lớp được tạo trong thư mục app_code trong ASP.NET 2.0 (C #)

Câu trả lời:


363

(Được cập nhật cho đầy đủ)
Bạn có thể truy cập các biến phiên từ bất kỳ trang hoặc điều khiển nào bằng cách sử dụng Session["loginId"]và từ bất kỳ lớp nào (ví dụ: từ bên trong thư viện lớp), bằng cách sử dụngSystem.Web.HttpContext.Current.Session["loginId"].

Nhưng xin vui lòng đọc tiếp cho câu trả lời ban đầu của tôi ...


Tôi luôn sử dụng lớp bao bọc xung quanh phiên ASP.NET để đơn giản hóa việc truy cập vào các biến của phiên:

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

Lớp này lưu trữ một thể hiện của chính nó trong phiên ASP.NET và cho phép bạn truy cập các thuộc tính phiên của mình theo cách an toàn kiểu từ bất kỳ lớp nào, ví dụ như thế này:

int loginId = MySession.Current.LoginId;

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

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

Cách tiếp cận này có một số ưu điểm:

  • nó tiết kiệm cho bạn từ rất nhiều kiểu đúc
  • bạn không phải sử dụng các khóa phiên được mã hóa cứng trong toàn bộ ứng dụng của mình (ví dụ: Phiên ["loginId"]
  • bạn có thể ghi lại các mục phiên của mình bằng cách thêm nhận xét tài liệu XML vào các thuộc tính của MySession
  • bạn có thể khởi tạo các biến phiên của mình bằng các giá trị mặc định (ví dụ: đảm bảo chúng không rỗng)

6
Không cần phải viết bất kỳ mã nào, hãy sử dụng như trong câu trả lời. Ví dụ: "public int LoginId {get; set;}" -> đây được gọi là thuộc tính tự động.
M4N

4
Nếu bạn đang sử dụng .net 3.x, bạn có thể sử dụng các thuộc tính tự động như trong mã của tôi. Với .net 2.x / 1.x, điều này không khả dụng và bạn phải tự thực hiện getter / setter của các thuộc tính của mình: private int _loginId; công khai int Đăng nhập {get {return _loginId; } đặt {_loginId = value; }}
M4N

2
Bây giờ trông thật tuyệt, tôi nghĩ rằng tôi đã có câu trả lời cho vấn đề của mình và tôi đã sử dụng theo cách của bạn, nó rất sạch sẽ và dễ dàng để duy trì tất cả các biến phiên của tôi tại một nơi. Cảm ơn @Martin, bạn thật TUYỆT VỜI.
Prashant

23
@ M4N, Ước gì tôi có thể bày tỏ lòng biết ơn nhiều hơn +1. Điều này đã trở thành cách yêu thích của tôi để xử lý phiên / bộ đệm trong các dự án của tôi. Mã của tôi, theo nghĩa đen, là cảm ơn bạn.
Brandon Boone

4
@Kristopher trong khi thuộc tính 'Hiện tại' là tĩnh, ví dụ MySession được trả lại không ... vì vậy nó ổn. Các phương thức và thuộc tính tĩnh là an toàn để sử dụng theo cách này.
Darren

104

Truy cập Phiên thông qua các chủ đề HTTPContext: -

HttpContext.Current.Session["loginId"]

Cảm ơn một tấn Anthony cho bước đơn giản này.
Kings

Cảm ơn rất nhiều Anthony, + 1 vì điều đó
Owais Qureshi

Cảm ơn. Quên không gian tên là gì :)
Anthony Horne

@AnthonyWJones tôi sử dụng phương pháp của bạn, nhưng có vấn đề, bạn có thể giải thích cho tôi, nơi tôi đã sai lầm hoặc cách thích hợp để sử dụng là gì, câu hỏi của tôi stackoverflow.com/questions/45254279/...
Adnan

và nếu bạn muốn chuyển đổi sang httpSessionStateBase: httpSessionStateBase session = new HttpSessionStateWrapper (HttpContext.Cản.Session); re: stackoverflow.com/questions/5447611/ từ
sobelito

24

Vấn đề với giải pháp được đề xuất là nó có thể phá vỡ một số tính năng hiệu suất được tích hợp trong SessionState nếu bạn đang sử dụng bộ lưu trữ ngoài quy trình. ("Chế độ máy chủ trạng thái" hoặc "Chế độ máy chủ SQL"). Trong chế độ oop, dữ liệu phiên cần được tuần tự hóa ở cuối yêu cầu trang và được giải tuần tự hóa ở đầu yêu cầu trang, có thể tốn kém. Để cải thiện hiệu suất, SessionState cố gắng chỉ khử lưu lượng những gì cần thiết bằng cách chỉ khử biến khi nó được truy cập lần đầu tiên và nó chỉ tuần tự hóa lại và thay thế biến đã được thay đổi. Nếu bạn có rất nhiều biến phiên và chuyển tất cả chúng vào một lớp thì về cơ bản mọi thứ trong phiên của bạn sẽ được giải tuần tự hóa trên mỗi yêu cầu trang sử dụng phiên và mọi thứ sẽ cần được tuần tự hóa lại ngay cả khi chỉ có 1 thuộc tính thay đổi vì lớp đã thay đổi. Chỉ cần một cái gì đó để xem xét nếu bạn sử dụng rất nhiều phiên và chế độ oop.


4
+1 cho việc này. Nếu bạn không sử dụng InProc cho Phiên, thì Ernie chính xác 100%. InProc dù sao cũng rất hạn chế, vì nó không hỗ trợ webfarm và sẽ bị mất nếu ứng dụng khởi động lại. Lưu ý, bằng chi phí hiệu năng, chúng tôi đang xem xét mức phí bảo hiểm 20% khi sử dụng chế độ Máy chủ Nhà nước và chi phí tuần tự hóa được thêm vào đầu. Như bạn có thể tưởng tượng điều này có thể đắt tiền. Bạn có thể tránh một số chi phí tuần tự hóa bằng cách bám vào các kiểu nguyên thủy (ví dụ: int, chuỗi, char, byte, v.v.). Các đối tượng tùy chỉnh sẽ phải đối mặt với tuần tự hóa. Người dùng hãy cẩn thận.
Zack Jannsen

+1 Điểm tốt. Một thay đổi sẽ kết hợp hai khái niệm này là có mỗi thuộc tính trên lớp "phiên" tùy chỉnh này gọi chính phiên asp.net thay vì một đối tượng lớn trong phiên. Phải thực hiện kiểu truyền mà cách tiếp cận của @ M4N tránh, nhưng có thể đáng giá nếu bạn chỉ đọc một số phiên mỗi lần.
eol

12

Các câu trả lời được trình bày trước khi tôi cung cấp giải pháp apt cho vấn đề, tuy nhiên, tôi cảm thấy rằng điều quan trọng là phải hiểu tại sao lỗi này lại dẫn đến:

Các Sessiontài sản của Pagetrả về một thể hiện của loại HttpSessionStatetương ứng với yêu cầu đó cụ thể. Page.Sessionlà thực sự tương đương với cuộc gọi Page.Context.Session.

MSDN giải thích làm thế nào điều này là có thể:

Vì các trang ASP.NET chứa tham chiếu mặc định đến không gian tên System.Web (chứa HttpContextlớp), bạn có thể tham chiếu các thành viên HttpContexttrên trang .aspx mà không cần tham chiếu lớp đủ điều kiện HttpContext.

Tuy nhiên, khi bạn cố gắng truy cập thuộc tính này trong một lớp trong App_Code, thuộc tính sẽ không có sẵn cho bạn trừ khi lớp của bạn xuất phát từ Lớp Trang.

Giải pháp của tôi cho kịch bản thường gặp này là tôi không bao giờ chuyển các đối tượng trang cho các lớp . Tôi thà trích xuất các đối tượng cần thiết từ Phiên phiên và chuyển chúng vào Lớp dưới dạng bộ sưu tập giá trị tên / Mảng / Danh sách, tùy theo trường hợp.


Đó là lời giải thích tuyệt vời, nó đã giúp tôi +1 cho điều đó :)
Owais Qureshi

1

Tôi đã có cùng một lỗi, bởi vì tôi đã cố gắng thao tác các biến phiên trong một lớp Phiên tùy chỉnh.

Tôi đã phải chuyển ngữ cảnh hiện tại (system.web.httpcontext.cản) vào lớp, và sau đó mọi thứ đã hoạt động tốt.

Thạc sĩ


1

Trong lõi asp.net, công việc này khác nhau:

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

Nguồn: https://benjii.me/2016/07/USE-simes-and-httpcontext-in-aspnetcore-and-mvc-core/


0

Điều này sẽ hiệu quả hơn cho cả ứng dụng và cho cả nhà phát triển.

Thêm lớp sau vào dự án web của bạn:

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

}

Đây là cách thực hiện:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.