จะใช้เซสชันในแอปพลิเคชัน ASP.NET MVC 4 ได้อย่างไร?


113

ฉันยังใหม่กับ ASP.NET MVC ฉันเคยใช้ PHP มาก่อนและมันง่ายมากที่จะสร้างเซสชันและเลือกเรกคอร์ดผู้ใช้ตามตัวแปรเซสชันปัจจุบัน

ฉันได้ดูทุกที่บนอินเทอร์เน็ตเพื่อดูบทช่วยสอนแบบทีละขั้นตอนที่สามารถแสดงวิธีสร้างและใช้เซสชันในแอปพลิเคชัน C # ASP.NET MVC 4 ของฉัน ฉันต้องการสร้างเซสชันที่มีตัวแปรผู้ใช้ที่ฉันสามารถเข้าถึงได้จากทุกที่ในคอนโทรลเลอร์ของฉันและสามารถใช้ตัวแปรในการสืบค้น LINQ ของฉันได้



2
บทความนี้อาจเป็นที่สนใจ: brockallen.com/2012/04/07/think-twice-about-using-session-state
Daniel

คำตอบ:


160

ลอง

//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
ขอบคุณ Jobert! คุณให้ความคิดฉัน! แค่สงสัยว่า .. เป็นไปได้ไหมที่จะเพิ่มตัวแปรผู้ใช้ในเซสชันระหว่างการเข้าสู่ระบบ? และฉันจะสามารถเข้าถึงตัวแปรเซสชัน (สร้างเพียงครั้งเดียว) ในตัวควบคุมต่างๆในแอปพลิเคชันของฉันได้หรือไม่
Thuto Paul Gaotingwe

31
คุณสามารถจัดเก็บอะไรก็ได้หรือข้อมูลประเภทใดก็ได้ในเซสชัน เมื่อสร้างแล้วคุณสามารถเข้าถึงค่าที่จัดเก็บไว้ในมุมมองและตัวควบคุมทั้งหมด โปรดทราบด้วยว่าเซสชันที่สร้างขึ้นสามารถเข้าถึงได้ต่อผู้ใช้และต่อเบราว์เซอร์เท่านั้น หมายความว่าเซสชันที่สร้างโดย User1 โดยใช้ Firefox ไม่สามารถเข้าถึงได้โดยผู้ใช้คนเดียวกันโดยใช้ IE นอกจากนี้ยังมีสิ่งที่คุณไม่ควรทำกับเซสชั่นเช่น อย่าเก็บข้อมูลขนาดใหญ่ไว้ ซึ่งอาจทำให้เซิร์ฟเวอร์ของคุณทำงานช้าลง สุดท้ายอย่าจัดเก็บข้อมูลที่ละเอียดอ่อนในเซสชันเช่นรหัสผ่านหรือหมายเลขบัตรเครดิต
Jobert Enamno

2
ขอขอบคุณอีกครั้ง! ฉันจะสร้างได้ที่ไหนเพื่อให้สามารถเข้าถึงผ่านคอนโทรลเลอร์ต่างๆได้
Thuto Paul Gaotingwe

2
@JobertEnamno ปลอดภัยไหมที่จะจัดเก็บค่าที่มาจากWebSecurity.CurrentUserIdดังนั้นจึงไม่ดึงออกจากฐานข้อมูลหลายครั้ง (ฉันพบว่ามีค่าใช้จ่ายสูงมาก)?
Andrius Naruševičius

2
ไม่มีเซสชั่นควบคุมข้ามดังนั้นเมื่อคุณขอควบคุมอื่นตัวอย่างเช่นจากการเป็นAccount/LogOnไปHome/Index, เป็นSession["FirstName"] nullนักพัฒนาต้องสร้างตัวควบคุมหลัก ( BaseController) และกำหนดฟิลด์ที่มีการป้องกัน ( internal protected HttpSessionStateBase SharedSession) ซึ่งอาจเปิดเผยตัวแปรเซสชันที่ใช้ร่วมกันในตัวควบคุมย่อยทั้งหมด (สิ่งนี้ถือว่าตัวควบคุมแอปทั้งหมดของคุณได้รับมรดกจากBaseController)
Bellash

63

เนื่องจากลักษณะของเว็บที่ไม่มีสถานะเซสชันจึงเป็นวิธีที่มีประโยชน์อย่างยิ่งในการคงออบเจ็กต์ข้ามคำขอโดยการทำให้เป็นอนุกรมและจัดเก็บไว้ในเซสชัน

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

วัตถุที่สามารถนำมาใช้ซ้ำได้ของเรา:

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

    public string EmailAddress { get; set; }

    public string FullName { get; set; }
}

ใช้กรณี:

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 */
    }

}

เมื่ออ็อบเจ็กต์นี้ถูกทำให้เป็นอนุกรมแล้วเราสามารถใช้กับคอนโทรลเลอร์ทั้งหมดได้โดยไม่จำเป็นต้องสร้างหรือสืบค้นฐานข้อมูลสำหรับข้อมูลที่มีอยู่ภายในอีกครั้ง

ใส่วัตถุเซสชันของคุณโดยใช้ Dependency Injection

ในโลกแห่งอุดมคติคุณจะ 'ตั้งโปรแกรมไปยังอินเทอร์เฟซไม่ใช่การนำไปใช้งาน ' และฉีดอ็อบเจ็กต์เซสชันที่ต่ออนุกรมลงในคอนโทรลเลอร์ของคุณโดยใช้คอนเทนเนอร์ Inversion of Control ที่คุณเลือกเช่นนั้น (ตัวอย่างนี้ใช้ StructureMap เนื่องจากเป็นสิ่งที่ฉันคุ้นเคยมากที่สุด ).

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

จากนั้นคุณจะลงทะเบียนสิ่งนี้ในGlobal.asax.csไฟล์ของคุณ

สำหรับผู้ที่ไม่คุ้นเคยกับการฉีดวัตถุเซสชั่นที่คุณสามารถหาบล็อกโพสต์เพิ่มเติมในเชิงลึกเกี่ยวกับเรื่องที่นี่

คำเตือน:

เป็นที่น่าสังเกตว่าควรลดจำนวนเซสชันให้น้อยที่สุดเซสชันจำนวนมากอาจทำให้เกิดปัญหาด้านประสิทธิภาพได้

ขอแนะนำว่าอย่าเก็บข้อมูลที่ละเอียดอ่อนไว้ในนั้น (รหัสผ่าน ฯลฯ )


คุณจะใส่นิยามคลาสไว้ที่ใด ฉันค่อนข้างใหม่สำหรับทุกสิ่ง แต่ฉันแค่อยากรู้ว่าคอนโทรลเลอร์คนอื่นจะมองเห็นคลาสและรู้ว่ามันคืออะไร คุณเพิ่มไว้ที่ด้านบนของคอนโทรลเลอร์หรือไม่? ฉันกำลังคิดเกี่ยวกับ SessionStart ใน global.asax ฉันจะเริ่มต้นสิ่งต่าง ๆ แต่นั่นอาจไม่ใช่วิธีที่ดีที่สุดที่จะทำ
Shaun314

@ Shaun314 ตามหลักการแล้วคุณจะใช้คอนเทนเนอร์ IoC เพื่อฉีดวัตถุเข้าไปในตัวควบคุมของคุณผ่านการฉีดแบบพึ่งพา (ดูแก้ไข)
Joseph Woodward

1
ฉันกำลังจัดเก็บข้อมูลเซสชันบางส่วนหลังจากล็อกอินผู้ใช้โดยใช้ Identity 2 ฉันไม่สามารถดึงข้อมูลเหล่านั้นในการดำเนินการและคอนโทรลเลอร์อื่น ๆ ได้นอกจากการดำเนินการแรกที่ฉันเปลี่ยนเส้นทางผู้ใช้ ความคิดใด ๆ ?
Akbari

17

นี่คือวิธีการทำงานของสถานะเซสชันใน ASP.NET และ ASP.NET MVC:

ภาพรวมสถานะเซสชัน ASP.NET

โดยทั่วไปคุณทำสิ่งนี้เพื่อเก็บค่าในวัตถุเซสชัน:

Session["FirstName"] = FirstNameTextBox.Text;

ในการดึงค่า:

var firstName = Session["FirstName"];

10
ไม่มีเซสชันตัวควบคุมข้ามดังนั้นเมื่อคุณขอตัวควบคุมอื่นเช่นจากAccountถึงHomeเซสชัน ["FirstName"] จะเป็นโมฆะ นักพัฒนาต้องสร้างBaseControllerและกำหนดฟิลด์ที่มีการป้องกัน ( internal protected HttpSessionStateBase SharedSession) ซึ่งอาจเปิดเผยSessionตัวแปรที่ใช้ร่วมกันในตัวควบคุมย่อยทั้งหมด (ซึ่งถือว่าตัวควบคุมแอปทั้งหมดของคุณสืบทอดมาจากBaseController)
Bellash

4
อืมมีแน่เหรอ? มีตัวแปรเซสชันในคอนโทรลเลอร์ (ตัวควบคุมพื้นฐานที่ MVC ให้มา)
aeliusd

7
@Bellash นี่ผิดอย่างสิ้นเชิง เซสชันมีอยู่ในคอนโทรลเลอร์ฉันเพิ่งตั้ง Session ["test"] ใน HomeController แล้วอ่านใน AccountController ของฉัน
niico

0

คุณสามารถจัดเก็บข้อมูลประเภทใดก็ได้ในเซสชันโดยใช้:

Session["VariableName"]=value;

ตัวแปรนี้จะคงอยู่ 20 นาทีหรือมากกว่านั้น


-8

คุณสามารถเก็บค่าใด ๆ ในเซสชันเช่น Session ["FirstName"] = FirstNameTextBox.Text; แต่ฉันจะแนะนำให้คุณใช้เป็นฟิลด์คงที่ในโมเดลกำหนดค่าให้กับมันและคุณสามารถเข้าถึงค่าฟิลด์นั้นได้ทุกที่ในแอปพลิเคชัน คุณไม่ต้องการเซสชั่น ควรหลีกเลี่ยงเซสชัน

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

บนตัวควบคุม - Employee.FullName = "ABC"; ตอนนี้คุณสามารถเข้าถึงชื่อเต็มนี้ได้ทุกที่ในแอปพลิเคชัน


10
การจัดเก็บข้อมูลในฟิลด์แบบคงที่โดยเฉพาะข้อมูลผู้ใช้เช่นชื่อพนักงานจะทำให้เกิดปัญหารุนแรงในสภาพแวดล้อมที่มีผู้ใช้หลายคน เมื่อผู้ใช้ที่แตกต่างกันสองคนเข้าสู่ระบบพวกเขาจะเห็นพนักงานคนเดียวกันที่อยู่อีเมลเนื่องจากฟิลด์สแตติกในพนักงานจะเหมือนกันสำหรับแต่ละอินสแตนซ์
GökçerGökdal
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.