Cách sử dụng phiên trong ứng dụng ASP.NET MVC 4?


113

Tôi mới sử dụng ASP.NET MVC. Tôi đã sử dụng PHP trước đây và thật dễ dàng để tạo phiên và chọn bản ghi người dùng dựa trên các biến phiên hiện tại.

Tôi đã tìm khắp mọi nơi trên Internet để có hướng dẫn từng bước đơn giản có thể chỉ cho tôi cách tạo và sử dụng các phiên trong ứng dụng C # ASP.NET MVC 4 của tôi. Tôi muốn tạo một phiên với các biến người dùng mà tôi có thể truy cập từ bất kỳ đâu trong bộ điều khiển của mình và có thể sử dụng các biến trong các truy vấn LINQ của mình.



Câu trả lời:


160

Thử

//adding data to session
//assuming the method below will return list of Products

var products=Db.GetProducts();

//Store the products to a session

Session["products"]=products;

//To get what you have stored to a session

var products=Session["products"] as List<Product>;

//to clear the session value

Session["products"]=null;

3
Cảm ơn Jobert! u đã cho tôi một ý tưởng! Tuy nhiên, chỉ tự hỏi .., có thể thêm các biến người dùng vào một phiên trong khi đăng nhập không? và tôi cũng sẽ có quyền truy cập vào các biến phiên (chỉ được tạo một lần) trên các bộ điều khiển khác nhau trong ứng dụng của tôi chứ?
Thuto Paul Gaotingwe

31
Bạn có thể lưu trữ bất kỳ thứ gì hoặc bất kỳ loại dữ liệu nào trong một phiên. Sau khi được tạo, bạn có thể truy cập giá trị được lưu trữ trên tất cả các chế độ xem và bộ điều khiển. Cũng cần lưu ý rằng phiên được tạo chỉ có thể truy cập cho mỗi người dùng và mỗi trình duyệt. Có nghĩa là phiên được tạo bởi User1 bằng Firefox không thể được truy cập bởi cùng một người dùng sử dụng IE. Có những điều bạn cũng không nên làm với phiên chẳng hạn như. KHÔNG lưu trữ dữ liệu lớn trên đó. Điều này có thể làm chậm hiệu suất của máy chủ của bạn. Cuối cùng KHÔNG lưu trữ dữ liệu nhạy cảm với một phiên như mật khẩu hoặc số thẻ tín dụng
Jobert Enamno

2
Cảm ơn một lần nữa! Tôi tạo nó ở đâu để có thể truy cập nó trên các bộ điều khiển khác nhau?
Thuto Paul Gaotingwe

2
@JobertEnamno có an toàn để lưu trữ giá trị đến từ WebSecurity.CurrentUserIdđó không để kéo nó từ cơ sở dữ liệu nhiều lần (tôi thấy nó rất tốn kém)?
Andrius Naruševičius

2
Không có phiên điều khiển chéo, vì vậy khi bạn yêu cầu một trình điều khiển khác, ví dụ từ Account/LogOnđến Home/Index, Session["FirstName"]null. Các nhà phát triển phải tạo một bộ điều khiển cha mẹ ( BaseController) và xác định một lĩnh vực được bảo vệ ( internal protected HttpSessionStateBase SharedSession) có thể tiếp xúc với các biến Session được chia sẻ trong tất cả các bộ điều khiển phụ (điều này giả định rằng tất cả các bộ điều khiển ứng dụng của bạn được thừa hưởng từ BaseController)
Bellash

63

Do tính chất không trạng thái của web, các phiên cũng là một cách cực kỳ hữu ích để duy trì các đối tượng trên các yêu cầu bằng cách tuần tự hóa chúng và lưu trữ chúng trong một phiên.

Một trường hợp sử dụng hoàn hảo của trường hợp này có thể là nếu bạn cần truy cập thông tin thường xuyên trên ứng dụng của mình, để lưu các lệnh gọi cơ sở dữ liệu bổ sung cho mỗi yêu cầu, dữ liệu này có thể được lưu trữ trong một đối tượng và không được quản lý theo từng yêu cầu, như vậy:

Đối tượng có thể tái sử dụng, có thể tuần tự hóa của chúng tôi:

[Serializable]
public class UserProfileSessionData
{
    public int UserId { get; set; }

    public string EmailAddress { get; set; }

    public string FullName { get; set; }
}

Trường hợp sử dụng:

public class LoginController : Controller {

    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        if (ModelState.IsValid)
        {
            var profileData = new UserProfileSessionData {
                UserId = model.UserId,
                EmailAddress = model.EmailAddress,
                FullName = model.FullName
            }

            this.Session["UserProfile"] = profileData;
        }
    }

    public ActionResult LoggedInStatusMessage()
    {
        var profileData = this.Session["UserProfile"] as UserProfileSessionData;

        /* From here you could output profileData.FullName to a view and
        save yourself unnecessary database calls */
    }

}

Khi đối tượng này đã được tuần tự hóa, chúng ta có thể sử dụng nó trên tất cả các bộ điều khiển mà không cần tạo nó hoặc truy vấn lại cơ sở dữ liệu để tìm lại dữ liệu chứa trong nó.

Chèn đối tượng phiên của bạn bằng cách sử dụng Dependency Injection

Trong một thế giới lý tưởng, bạn sẽ ' lập trình cho một giao diện, không phải triển khai ' và đưa đối tượng phiên có thể tuần tự hóa của bạn vào bộ điều khiển của bạn bằng cách sử dụng vùng chứa Inversion of Control mà bạn lựa chọn, giống như vậy (ví dụ này sử dụng StructureMap vì nó là đối tượng mà tôi quen thuộc nhất ).

public class WebsiteRegistry : Registry
{
    public WebsiteRegistry()
    {
        this.For<IUserProfileSessionData>().HybridHttpOrThreadLocalScoped().Use(() => GetUserProfileFromSession());   
    }

    public static IUserProfileSessionData GetUserProfileFromSession()
    {
        var session = HttpContext.Current.Session;
        if (session["UserProfile"] != null)
        {
            return session["UserProfile"] as IUserProfileSessionData;
        }

        /* Create new empty session object */
        session["UserProfile"] = new UserProfileSessionData();

        return session["UserProfile"] as IUserProfileSessionData;
    }
}

Sau đó, bạn sẽ đăng ký điều này trong Global.asax.cstệp của bạn .

Đối với những người không quen với việc tiêm các đối tượng phiên, bạn có thể tìm thấy một bài đăng blog chuyên sâu hơn về chủ đề này tại đây .

Một lời cảnh báo:

Cần lưu ý rằng các phiên nên được giữ ở mức tối thiểu, các phiên lớn có thể bắt đầu gây ra các vấn đề về hiệu suất.

Bạn cũng không nên lưu trữ bất kỳ dữ liệu nhạy cảm nào trong đó (mật khẩu, v.v.).


Bạn sẽ đặt định nghĩa lớp ở đâu? Tôi vẫn còn khá mới đối với mọi thứ, nhưng tôi chỉ tò mò về cách những người điều khiển khác sẽ nhìn thấy lớp học và biết nó là gì. Bạn chỉ cần thêm nó vào đầu bộ điều khiển? Tôi đã nghĩ về SessionStart trong global.asax Tôi sẽ khởi tạo mọi thứ nhưng có lẽ đó không phải là cách tốt nhất để làm điều đó.
Shaun314

@ Shaun314 Tốt nhất bạn nên sử dụng vùng chứa IoC để đưa đối tượng vào bộ điều khiển của bạn thông qua chèn phụ thuộc (xem chỉnh sửa).
Joseph Woodward

1
Tôi đang lưu trữ một số thông tin phiên sau khi đăng nhập người dùng bằng Identity 2. Tôi không thể truy xuất những thông tin đó trong các tác vụ và bộ điều khiển khác ngoài tác vụ đầu tiên mà tôi chuyển hướng người dùng đến. Bất kỳ ý tưởng?
Akbari,

17

Đây là cách trạng thái phiên hoạt động trong ASP.NET và ASP.NET MVC:

Tổng quan về trạng thái phiên ASP.NET

Về cơ bản, bạn làm điều này để lưu trữ một giá trị trong đối tượng Session:

Session["FirstName"] = FirstNameTextBox.Text;

Để truy xuất giá trị:

var firstName = Session["FirstName"];

10
Không có phiên điều khiển chéo nên khi bạn yêu cầu một trình điều khiển khác, ví dụ: từ Accountđến Home, Phiên ["FirstName"] là null. Các nhà phát triển phải tạo một BaseControllervà xác định một lĩnh vực được bảo vệ ( internal protected HttpSessionStateBase SharedSession) có thể tiếp xúc với những chia sẻ Sessionbiến trong tất cả các bộ điều khiển phụ (điều này giả định rằng tất cả các bộ điều khiển ứng dụng của bạn được thừa hưởng từ BaseController)
Bellash

4
Umm, chắc chắn là có? Có một biến Phiên trong Bộ điều khiển (bộ điều khiển cơ sở do MVC cung cấp).
aeliusd

7
@Bellash điều này hoàn toàn sai. Các phiên có sẵn trên các bộ điều khiển. Tôi vừa đặt Session ["test"] trong HomeController rồi đọc nó trong AccountController của tôi.
niico

0

Bạn có thể lưu trữ bất kỳ loại dữ liệu nào trong một phiên sử dụng:

Session["VariableName"]=value;

Biến này sẽ tồn tại trong 20 phút hoặc lâu hơn.


-8

U có thể lưu trữ bất kỳ giá trị nào trong phiên như Session ["FirstName"] = FirstNameTextBox.Text; nhưng tôi sẽ đề nghị u lấy làm trường tĩnh trong mô hình gán giá trị cho nó và u có thể truy cập giá trị trường đó bất kỳ nơi nào trong ứng dụng. Bạn không cần phiên. nên tránh phiên.

public class Employee
{
   public int UserId { get; set; }
   public string EmailAddress { get; set; }
   public static string FullName { get; set; }
}

trên bộ điều khiển - Employee.FullName = "ABC"; Bây giờ bạn có thể truy cập Tên đầy đủ này ở bất kỳ đâu trong ứng dụng.


10
Lưu trữ dữ liệu trên các trường tĩnh, đặc biệt là dữ liệu người dùng như tên Nhân viên sẽ gây ra các vấn đề nghiêm trọng trong môi trường nhiều người dùng. Khi hai người dùng khác nhau đăng nhập vào hệ thống, họ sẽ thấy cùng một Employee.EmailAddress vì trường tĩnh trên Employee là giống nhau cho mỗi trường hợp.
Gökçer Gökdal
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.