آشنایی با Session State در Asp.Net

در این مقاله با تکنیک مدیریت Session State در Asp.Net آشنا می شویم

آشنایی با Session State  در Asp.Net

در ابتدا لازم به ذکر است به این نکته اشاره کنیم که چرا ما به نگهداری وضعیت (state)مربوط به نرم افزار خود احتیاج داریم .همانطور که می دانید نرم افزاری که ما طراحی میکنیم stateless میباشد .به عبارتی دیگر یک instance جدید از صفحات وب با هر با ارسال صفحه به سمت سرور (postback) مجدد ایجاد میشود .HTTP یک پروتکل stateless می باشد و نمی تواند اطلاعات مربوط به کاربر را در صفحه نگهداری کند .به عنوان مثال اگر کاربر مقداری اطلاعات را در صفحه ثبت کند و سپس به صفحه ای دیگر برود اطلاعاتی که در صفحه قبل وارد کرده بود از بین می رود و علاوه بر این کاربر نمی تواند آن اطلاعات را بازیابی کند .

پس بنابراین در اینجا به وضعیتی احتیاج داریم که اطلاعات کاربر را بتواند در خود نگهداری کند , که این عمل بر عهده نقش خصوصی (Privitage role) با نام "Session State" میباشد .اساساً session یک متغیر واسط بین کاربر و سرور میباشد که در سمت سرور ذخیره میشود , حتی session می تواند در IIS که همان Internet Information Service میباشد هم ذخیره شود که در این حالت به صورت  "inproc mode" میباشد و یا حتی میتواند اطلاعات مربوط به بانک اطلاعاتی را در خود ذخیره کند که در این حالت نیز به صورت "outproc mode" میباشد که در ادامه در مورد این دو وضعیت بیشتر توضیح خواهیم داد .

بنابراین Session به ما برای حفظ اطلاعات کاربر در تمام مدت اجرای نرم افزار کمک میکند و این اطلاعات را در حافظه سرور ذخیره میکند . بنابراین session می تواند هر گونه اطلاعات و یا مقادیری را در سمت سرور ذخیره میکند و قابلیت دسترسی به آن اطلاعات در کل نرم افزار یا وب سایت فراهم میکند .

اکنون به چگونگی ذخیره اطلاعات کاربر در session می پردازیم :

در آغاز هنگامی که کاربر یک درخواست به سمت سرور ارسال می کند , رویداد start نرم افزار آغاز میشود و شئی ها و مقادیری که در نرم افزار تعریف کرده ایم قابل اشتراک در طول حیات نرم افزار میباشد .بعد از چرخه حیات برنامه , رویداد start مربوط به session برای هر کاربر به طور اختصاصی اجرا می شود و زمانی که کاربران دیگر سعی در اجرای نرم افزار دارند , رویداد session مربوط به کاربر قبلی برای آنها به صورت جداگانه ای آغاز به کار میکند .هر اطلاعاتی در نرم افزار با کمک یک کلمه کلیدی ذخیره میشوند .ما میتوانیم هر دو رویداد (نرم افزار و session) را با اضافه کردن "Global.asax" به نرم افزار خود مشاهده کنیم .

روند نگهداری session state به میتوانید در تصویر زیر مشاهده نمایید که در ابتدا کاربر به وب سایت یا نرم افزار ما مراجعه می کند , سپس اطلاعات مربوط به کاربر در سمت سرور ذخیره می کند , سپس اطلاعات مربوط به  session هر کاربر به صورت یک جدول در IIS ایجاد میشود و بعداً اگر کاربر به سمت سرور درخواستی ارسال کند ابتدا شماره منحصر بفردی که در session به آن اختصاص داده شد چک میشود و اگر معتبر بود اطلاعات به آن کاربر بازیابی می شود .

روند نگهداری اطلاعات در session در نرم افزار :

در ابتدا باید چگونگه با ذخیره و بازیابی اطلاعات آشنا شویم . در ادامه کد ذخیره اطلاعات در session را میتوانید مشاهده کنید :

    // Storing Username in session.Session[ "UserName" ] = txtUser.Text;  
    // Retreiving  
    values  
    from  
    session.// Check whether session variable null  
    or not if(Session[ "UserName" ] != null) { // Retreiving UserName  
    from  
    session lblWelcome.text = "Welcome: +Session[" UserName "];  
    }  
    else  
    {  
    //Do something else  
    }   

همانطور که می دانید , تمامی مقادیر به صورت پیش فرض در IIs ذخیره میشوند .اکنون برای حفظ تعادل ما احتیاج داریم که از IIs  خارج شویم .بنابراین ما به وضعیت "Outproc" احتیاج داریم .در ادامه تصویری از دو حالت session مشاهده می کنید .

نمایی از InProc Mode در Session

به صورت پیش فرض session mode  در Asp.Net اطلاعات را در حافظه متغیر جاری در applicaion domain ذخیره میکند . بنابراین این روش مناسبترین روش برای سرعت عملکرد نرم افزار میباشد , اما بزرگترین عیب این است که تمامی اطلاعات در application domain در سرور ذخیره میشوند و اگر ما سرور را restart کنیم , تمامی اطلاعات از بین میرود .در web.config می باست session mode را تنظیم کنیم .مانند تصویر زیر :

مزایاو معایب این روش به شرح زیر میباشد :

مزایا:

1 - اطلاعات مربوط به session در حافظه متغیر از application domain جاری ذخیره میشود .

2 - هیج نیازی به سریال سازی(serialization) اطلاعات در InProc Session mode نمی باشد .

3 - راحتی در اجرا , مشابه استفاده از ViewState

معایب :

اگر چه InProc session سریعترین و رایجترین مکانیزمی است که به صورت پیش فرض وجود دارد , اما محدودیتهای هم به وجود می آورد که در ادامه به آن اشاره میکنیم :

1 - اگر روند انجام عملیات نرم افزار و یا application domain تنظیم مجدد(reset) شوند , تمامی اطلاعات session از بین می روند .

2 - با توجه به سرعت بالا , اطلاعات بیشتری در session ذخیره می شود که در نهایت باید حافظه بیشتری را برای این امر در نظر گرفت

3 - ما این مکانیزم را در سناریو Web Garden نمی توانیم استفاده کنیم .

4 - این Session mode برای سناریو های Web Farm مناسب نمی باشد .

با توجه به مزایا و معایبی که در بالا ذکر شد , ما میتوانیم نتیجه گیری کنیم که InProc یک مکانیزم سریع برای ذخیره اطلاعات Session می باشد , اما برای نرم افزارهای کوچک مناسب میباشد .در InProc  اگر سرور را restart کنیم و یا اگر چرخه Application Domain تنظیم مجددشود اطلاعات مربوط به session از بین میروند .

بنابراین این مکانیزم برای سناریوهای Web Farm و Web Garden مناسب نمی باشد .

حالا ما گزینه های دیگر را بررسی میکنیم .

STATESERVER MODE یا (OUTPROC MODE)

همچنین نام دیگر آن Out-Proc Session Mode میباشد .StateServe به تنهایی برای windows Service استفاده میشوند که مستقل از IIS میباشد و میتواند در سورو جدا اجرا شود .این Session State مجموعاً aspnet_state.exe را میدیریت می کند. این سرور ممکن است در یک سیستم اجرا شود , اما در خارج از Application Domain  مربوط به نرم افزاری که در حال اجرا است , قرار دارد . به این معنی است که اگر شما روند ASP.NET را restart کنید , اطلاعات مربوط به session همچنان در دسترس میباشد .این روش مزایا و معایب مختص به خود را دارد , همچنین برای دسترسی به اطلاعات زمان بیشتری احتیاج میباشد .

پیکربندی برای StateServer Session mode :

در StateServer mode , اطلاعات sesson در سرور جدا ذخیره میشود که از IIS مستقل با aspnet_state.exe  استفاده میکند .این روند به عنوان Windows Service اجرا میشود .شما می توانید این سرویس را از Windows MMC یا از Command prompt اجرا کنید .

به صورت پیش فرض "Startup Type" از ASP.NET به Manual تنظیم شده است و ما باید آن را به Automatic تغییر دهیم .

از طریق command prompt , فقط "net start aspnet_state" را وارد نمایید , به صورت پیش فرض این سرویس به درگاه TCP   42424  بررسی می کند .اما ما می توانیم درگاه را از Registry editor تغیر دهیم .مشابه تصویر زیر :

اکنون برای پیکربندی تنظیمات Stateserver به داخل Web.Config می رویم .در این قسمت ما باید stateConnetionString را تغییر دهیم .این عمل باعث میشود که سیسمتی که state server را اجرا کرده است تشخیص دهد .به صورت پیش فرض آی پی برای stateConnectionString  برابر با 127.0.0.1 میباشد و درگاه آن 42424 میباشد .

<configuration>  
    <system.web>  
        <sessionstate mode="StateServer"    time out="30" stateConnectionstring="tcpip=127.0.0.1"  
"tcpip=localhost:42424"  </sessionstate>  
    </system.web>  
</configuration> 

در ادامه به مقایسه InProc mode و OutProc mode در کد می پردازیم .

در ابتدا نرم افزار Visual Studio را اجرا میکنیم .یک پروژه جدید ایجاد میکنیم (یک web application خالی ایجاد میکنیم),

سپس یک web form Login.aspx به پروژه اضافه می کنیم , و یک کنترل Textbox برای دریافت نام کاربری و یک کنترل Button برای ورود در صفحه قرار میدهیم .


    <asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>  
    <asp:Button ID="btnSubmit" runat="server" Text="Go to Home Page" OnClick="btnSubmit_Click"/>  

سپس یک handler code برای دکمه ارسال می نویسیم , دستوراتی که در ادامه مشاهده میکنید دو عملیات را همزمان انجام می دهند :

1 -نام کاربری که وارد پنل کاربری شده را در Session ذخیره می کنیم .

2 -سپس کاربر را به صفحه اصلی هدایت می کنیم .


    protected void btnSubmit_Click(object sender, EventArgs e)  
    {  
       Session["UserName"] = txtUserName.Text.ToString();  
       Response.Redirect("Home.aspx");  
    }  

یک Web Form با نام Home.aspx ایجاد می کنیم .سپس یک کنترل Label در این صفحه قرار میدهیم .


    <label id="lblUserName" runat ="server"></label>  

در رویداد PageLoad صفحه نام کاربری را از Session State دریافت میکنیم .دستور زیر نیز دو عملیات را همزمان انجام می دهد ,

1 - نام کاربری را از Session دریافت میکند و در کنترل label قرار میدهد

2 - اگر نام کاربری وجود نداشت و کاربری وارد پنل کاربری نشده بود , عبارت "Anonymous User " را نمایش می دهد


    protected void Page_Load(object sender, EventArgs e)   
    {  
        if (Session["UserName"] != null && Session["UserName"] != "")   
        {  
            lblUserName.InnerText = Session["UserName"].ToString();  
        }   
        else   
        {  
            lblUserName.InnerText = "Anonymous User";  
        }