تمرير البيانات من Action Method ل View

-

اهلا وسهلا فيكم 

الهدف من هذا الدرس هو تعلم كيف نرسل البيانات من Action الى View بعد معالجتها،وطرق ارسال هذه البيانات

هناك 4 طرق مختلفة لتمرير البيانات من  Action Method الى View وهذه الطرق هي:

  • View Model Object
  • ViewBag
  • TempData
  • Session Variable

وحتي نفهم الموضوع خلونا نطبق امثلة عمليه على كل نوع. 

تمام التمام

النوع الأول View Model Object

في هذه الطريقة يتم ارجاع البيانات من action  الى view عن طريق Model Object .

تمام نرجع لمشروعنا StudentAcademy وبعدها ننتقل الى StudentsController وبعدها تضيف action جديد باسم StudentInfo ونضيف الكود التالي:

public IActionResult StudentInfo()
        {
            StudentsModel _Student = new StudentsModel();
            _Student.CustomerNo = "2100001";
            _Student.FullName = "Hatem Altalafha";
            _Student.Birthday = Convert.ToDateTime("01/01/1980");
            _Student.Gender = 1;
            _Student.Nationality = 1;
            _Student.Address = "Jordan";
            _Student.UserName = "Hatem";
            _Student.Password = "abc123";
            _Student.Email = "[email protected]";
            _Student.Mobile = "000000000";
            _Student.Note = "";
            return View(_Student);
        }

هذه الطريقة تعتمد على Model لاحظ في هذا المثال ان استخدمنا Model من نوع StudentsModel ،وهذا Model كنا عملناه من قبل، للتذكير الكود الخاص بهذا Model  بكون :



في هذا action استخدمنا بعض الخصائص property من StudentModel وخزنا فيها بيانات مثل (رقم العيل، الاسم ، تاريخ الميلاد ... الخ) واخر الaction استدعينا View وارسلنا لها Model من البيانات 

كود الاستدعاء 

return View(_Student);
لعرض هذه البيانات اكيد بنحتاج View، خلونا نعمل View بالنقر يمين فوق action وبعدها بنختار add New View ونضيف الكود التالي الى هذا view 
اسم View بكون هو نفس اسم action 

@model StudentsModel
@{
    ViewData["Title"] = "StudentInfo";
}

<h2>Student Info</h2>
<p>Customer No : @Model.StudentNo</p>
<p>Full Name: @Model.FullName</p>
<p>Birthday: @Model.Birthday</p>
<p>Gender : @Model.Gender </p>
<p>Nationality : @Model.Nationality </p>
<p>Address : @Model.Address </p>
<p>UserName : @Model.UserName </p>
<p>Password : @Model.Password</p>
<p>Email : @Model.Email </p>
<p>Mobile : @Model.Mobile </p>
نفهم الكود
في هذا View استقبلنا البيانات على شكل Model من نوع StudentModel وبعدها عملنا كود HTML لعرض البيانات. 
مثلا كود عرض الاسم بكون 
<p>Customer No : @Model.StudentNo</p>
بشكل تلقائي يتم قراءة البيانات المخزنه في Model من قبل MVC

تشغيل التطبيق

تمام التمام نشغل التطبيق ونشوف النتيجة :


طيب تمام الان نعمل تدريب باضافة التاريخ الحالي الى View 
حتي نعمل هذا التعديل وبما ان شغلنا الان Model فا اكيد نحنا بحاجة الى تعديل StudentModel ، لذا انتقل الى الملف StudentsModel في مجلد Models واضف خاصية جديده باسم CurrentDate ليكون التعديل: 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StudentsAcademy.Models
{
    public class StudentsModel
    {
        public string CustomerNo { get; set; }
        public string FullName { get; set; }
        public DateTime Birthday { get; set; }
        public int Gender { get; set; }
        public int Nationality { get; set; }
        public string Address { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public string Mobile { get; set; }
        public string Note { get; set; }
        public DateTime CurrentDate { get; set; }
    }
}
الهدف من هذا التعديل هو اضافة متغير لكي يتم تخزين التاريخ فيه ثم ارسالة الى View، تمام ننتقل الان الى المسمى StudentInfo داخل StudentsController واضف الكود التالي 
    public IActionResult StudentInfo()
        {
            StudentsModel _Student = new StudentsModel();
            _Student.CustomerNo = "2100001";
            _Student.FullName = "Hatem Altalafha";
            _Student.Birthday = Convert.ToDateTime("01/01/1980");
            _Student.Gender = 1;
            _Student.Nationality = 1;
            _Student.Address = "Jordan";
            _Student.UserName = "Hatem";
            _Student.Password = "abc123";
            _Student.Email = "[email protected]";
            _Student.Mobile = "000000000";
            _Student.Note = "";
            _Student.CurrentDate = DateTime.Now;
            return View(_Student);
        }
نفهم شو عملنا
الامر بسيط جدا، حيث قمنا بإضافة التاريخ الحالي الى StudentsModel ثم بعد ذلك تم تخزين التاريخ الحالي في Student.CurrentDate_  ومن ثم ارسالنا هذا StudentsModel الى View المسمى StudentInfo
في View نعمل تعديل بسيط بحيث نعرض التاريخ المرسل في Model@ الى هذا View ،التعديل على الكود :

model StudentsModel
@{
    ViewData["Title"] = "StudentInfo";
}
<p>Current Date: @Model.CurrentDate</p>
<hr />
<h2>Student Info</h2>
<p>Customer No : @Model.CustomerNo</p>
<p>Full Name: @Model.FullName</p>
<p>Birthday: @Model.Birthday</p>
<p>Gender : @Model.Gender </p>
<p>Nationality : @Model.Nationality </p>
<p>Address : @Model.Address </p>
<p>UserName : @Model.UserName </p>
<p>Password : @Model.Password</p>
<p>Email : @Model.Email </p>
<p>Mobile : @Model.Mobile </p>
نجرب التطبيق :

قم بتشغيل التطبيق بالانتقال الى الرابط 
https://localhost:44382/Students/StudentInfo
ستكون نتيجة التنفيذ 



تم قراءة التاريخ الحالي مع الوقت من Action المسمى StudentInfo ومن ثم تم ارسالها الى View .
نوع CurrentDate في StudentsModel هو DateTime لذلك لسنا بحاجة الى عمل أي cast هنا. حيث يتم قراءة التاريخ والوقت من CurrentDate

للتعامل مع التاريخ فقط في View يمكن التعديل على الكود الى الاتي : 


@model DateTime
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    Model: @Model and Year: @Model.Year
</body>
</html>

في هذا الكود يتم استقبال التاريخ فقط في view، وبعدها بنعمل cast له الىDateTime من خلال الامر

 @model DateTime
، وبعدها رجعنا السنة من التاريخ دون الحاجة إلى عمل cast باستخدام الكود:

Model: @Model and Year: @Model.Year

بنفس الطريقة ، يمكنك أيضًا إرسال View Model Object من النوع String ، class ، bool ، إلخ.
إذا كنت تقوم بتمرير string من action الى view، يجب عمل cast من string الى object، على النحو التالي:

retrun View((object)"How are you");

والسبب في ذلك هو أنه إذا كانت parameter في ()View  عبارة عن string، فسيتم البحث عن View  الي الو نفس اسم string المرسلة. مشان هيك وحتي يفهم .Net Core ان ال parameter المرسل عبارة عن string نحتاج إلى عمل cast من string  الى  object.

استخدام ViewBag

ViewBag عبارة عن متغير يتم تخزين قيم معينة داخله dynamic object حيث يمكن الوصل اليه من خلال view،

ومشان نفهم الموضوع بشكل افضل خلونا نعمل مثال بسيط ، حيث سنقوم بإضافة اسم المستخدم admin بشكل يدوي وتخزينه في ViewBag  ثم سنقوم بعرضها في View . لاحقا سنقرا هذه البيانات من قواعد البيانات.

تمام ننتقل الى StudentsController ثم أضف الكود التالي داخل action المسمى StudentInfo 

public IActionResult StudentInfo()
        {
            StudentsModel _Student = new StudentsModel();
            _Student.CustomerNo = "2100001";
            _Student.FullName = "Hatem Altalafha";
            _Student.Birthday = Convert.ToDateTime("01/01/1980");
            _Student.Gender = 1;
            _Student.Nationality = 1;
            _Student.Address = "Jordan";
            _Student.UserName = "Hatem";
            _Student.Password = "abc123";
            _Student.Email = "[email protected]";
            _Student.Mobile = "000000000";
            _Student.Note = "";
            _Student.CurrentDate = DateTime.Now;
            ViewBag.UserName = "Admin";
            return View(_Student);
        }
طريقة كتابة ViewBag بتكون بالشكل التالي :
ViewBag.ViewBagName="Value";
حيث ان ViewBagName هو اسم متغيير يمكن اضافة اي اسم ترغب به،(اكيد من الافضل يكون الو علاقة بالمكان الى موجود فيه). ثم بعدها Value هي القيمة المطلوب تخزينها.
تمام في مثالنا هنا استخدمنا الاسم UserName كا اسم لهاذ ViewBag وخزنا القيمة Admin فيه.

يمكن إضافة أي بيانات داخل ViewBag. 

تمام الان بعد ما خزنا القيم داخل ViewBag دور نتعلم كيف يمكن الوصول إلى هذه القيم في View وعرضها على الشاةشة، وحتي نوصل لهذه القيم بنسخدم الامر:
@ViewBag.(Variable Name) 
الكود التالي هو التعديل المطلوب:

تمام نطبق هذا الكلام في View ـ ونعدل على View بالشكل التالي :

@model StudentsModel
@{
    ViewData["Title"] = "StudentInfo";
}
Welcome ,@ViewBag.UserName
<hr />
<p>Current Date: @Model.CurrentDate</p>
<hr />
<p>Current Year: @Model.CurrentDate.Year</p>
<h2>Student Info</h2>
<p>Customer No : @Model.CustomerNo</p>
<p>Full Name: @Model.FullName</p>
<p>Birthday: @Model.Birthday</p>
<p>Gender : @Model.Gender </p>
<p>Nationality : @Model.Nationality </p>
<p>Address : @Model.Address </p>
<p>UserName : @Model.UserName </p>
<p>Password : @Model.Password</p>
<p>Email : @Model.Email </p>
<p>Mobile : @Model.Mobile </p>

قم بتشغيل التطبيق بالدخول الى الرابط 
https://localhost:44382/Students/StudentInfo
وبتكون نتيجة التنفيذ 





تمام مجموعة من النقاط المهمه بخصوص ViewBag 

    • تعد ViewBag طريقة خفيفة لنقل القيم من Controllers إلى Views.
    • تنقل ViewBag البيانات فقط من controller الى view، وليس العكس. 
    • تفقد ViewBag قيمتها في حالة حدوث إعادة التوجيه بين View. (من الخطأ في المشاريع الحقيقة استخدامها لعرض اسم المستخدم الحالي، لأنه سوف يفقد قيمته بمجرد الانتقال بين Views)
    • يمكن أن تحتوي على كائن من النوع primitive أو complex.
    • يمكنك تعيين أي عدد من properties values إلى ViewBag.


    شو هي TempData

    تعلمنا سابقا أن القيم في ViewBag تُفقد في حالة إعادة التوجيه بين Views،طيب ولو كنا بحاجة الى الاحتفاظ بهذه القيم، لحل هذه المشكلة يمكن استخدام TempDate.
    تمام
    TempData مشابه لـ ViewBag باستثناء أنه لا تفقد قيمتها أثناء إعادة التوجيه أيضًا بين Views.
    لكن في عيب ايضا باسخدام TempData في MVC وهو ان القيم الموجوده في TempData يتم فقدانها تلقائيًا بمجرد قراءتها.

    لفهم كيفية عمل TempData سنقوم بإعادة استخدام اسم المستخدم الذي استخدمناه سابقا في ViewBag داخل Action المسمى NewStudent في StudentsController لكن هنا سنستخدم TempDate
    انتقل الى NewStudent في StudentsController واضف الكود التالي :

    public IActionResult NewStudent()
            {
                TempData["UserName"] = "Admin";
                return View();
            }
    طريقة كتابة TempData  بتكون بالشكل التالي :
    TempData["ViewBagName"] = "Value";
    حيث ان ViewBagName هو اسم متغيير يمكن اضافة اي اسم ترغب به،(اكيد من الافضل يكون الو علاقة بالمكان الى موجود فيه). ثم بعدها Value هي القيمة المطلوب تخزينها.
    تمام في مثالنا هنا استخدمنا الاسم UserName كا اسم لهاذ TempData وخزنا القيمة Admin فيه.

    ننتقل الان الى View ونشوف كيف ممكن نعرض هذه القيمة :

    model StudentsModel
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
    </head>
    <body>
        Welcome ,@TempData["UserName"]
        <hr />
        <div class="container">
            <form method="post" asp-action="ReceivedDataByModelBinding">
                <div class="form-group">
                    <label>CustomerNo:</label>
                    <input class="form-control" asp-for="CustomerNo" />
                </div>
                <div class="form-group">
                    <label>FullName:</label>
                    <input class="form-control" asp-for="FullName" />
                </div>
                <div class="form-group">
                    <label>Birthday:</label>
                    <input class="form-control" asp-for="Birthday" />
                </div>
                <div class="form-group">
                    <label>Gender:</label>
                    <select class="form-control" asp-for="Gender">
                        <option value="M">Male</option>
                        <option value="F">Female</option>
                    </select>
                </div>
                <div class="form-group">
                    <label>Nationality:</label>
                    <select class="form-control" asp-for="Nationality">
                        <option value="M">Jordan</option>
                        <option value="F">Saudi Aribae</option>
                        <option value="F">UAE</option>
                    </select>
                </div>
                <div class="form-group">
                    <label>Address:</label>
                    <input class="form-control" asp-for="Address" />
                </div>
                <div class="form-group">
                    <label>UserName:</label>
                    <input class="form-control" asp-for="UserName" />
                </div>
                <div class="form-group">
                    <label>Password:</label>
                    <input class="form-control" asp-for="Password" />
                </div>
                <div class="form-group">
                    <label>Email:</label>
                    <input class="form-control" asp-for="Email" />
                </div>
                <div class="form-group">
                    <label>Mobile:</label>
                    <input class="form-control" asp-for="Mobile" />
                </div>
                <div class="form-group">
                    <label>Note:</label>
                    <input class="form-control" asp-for="Note" />
                </div>

                <button class="btn btn-primary" type="submit">Submit</button>
            </form>
        </div>
    </body>
    </html>

    طيب لو شغلنا التطبيق الان بنشوف النتيجة عرض اسم المسخدم Admin ، لكن مثل ما حكينا ان القيم يتم فقدانها بعد قرائتها.  وحتي نحفظ  القيم بنحتاج الى ان نرجع نحفظ القيم الخاصة ب TempData في View الثاني، تمام لو كان المطلوب بعد هذا View الي بنعمل في ادخال ابيانات الانتقال الى View ثاني لعرض هذه البيانات بنحتاج الى اضافة الكود التالي للاحتفاظ بقيمة TempData ولنفرض ان View الثاني هو ReceivedDataByModelBinding فا بالبتالي بكون الكود كالتالي :

    @model StudentsModel
    @{
        ViewData["Title"] = "ReceivedDataByModelBinding";
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>ReceivedDataByModelBinding</title>
    </head>
    <body>
        Welcome ,@TempData["UserName"]
        <hr />
        <h1>Customer Number :@Model.CustomerNo ,Full Name is @Model.FullName, Birthday @Model.Birthday</h1>
    </body>
    </html>
     
    قم بتشغيل التطبيق بالانتقال الى الرابط 
    https://localhost:44382/Students/NewStudent
    ستلاحظ ان اسم المستخدم تم عرضه بأول الصفحة 



    عند تعبئة البيانات المطلوبة والانتقال الى View المسمى ReceivedDataByModelBinding ستلاحظ اختفاء اسم المستخدم 






    لنقم بإضافة الكود

     TempData["UserName"] = "Admin";
     داخل action المسمى ReceivedDataByModelBinding 
    الكود التالي 

    public IActionResult ReceivedDataByModelBinding(StudentsModel Student)
            {
                TempData["UserName"] = "Admin";
                return View("ReceivedDataByModelBinding", Student);
            }
    اعد تشغيل التطبيق ستلاحظ ان اسم المستخدم تم عرضه في View المسمى ReceivedDataByModelBinding 


    ملاحظات مهمه حول TempData 

    TempData تعتمد على Session Middleware لذلك عليك إضافة ()services.AddSession إلى ()ConfigureServices  في Startup.cs class.
    توضح الأسطر المميزة في الكود أدناه ما يجب عليك إضافته إلى Startup class.
    public void ConfigureServices(IServiceCollection services)
            {
                services.AddControllersWithViews();
                services.AddSession();
            }
    تقوم طرق AddSession بإنشاء الخدمات التي تطلبها management Session.
    يقوم MVC تلقائيًا بإزالة قيم TempData بمجرد قراءتها. هناك طريقة "Keep" لمنع MVC من إزالة القيمة بمجرد قراءتها. ومع ذلك ، إذا تمت قراءة القيمة مرة أخرى (المرة الثانية) ، فسيقوم MVC بحذفها.
    تتيح لك طريقة " Peek’ " الحصول على القيمة وكذلك منعها من الحذف. هذا لأنه لا يخبر MVC بأن القيمة قد تمت قراءتها.

    استخدم session لتخزين القيمة بشكل دائم (حتى انتهاء الجلسة) لعدد القراءات التي تريدها وفي أي جزء من التطبيق.

    Session Variable

    Session state هي طريقة لتخزين البيانات أثناء تصفح المستخدم لموقع الويب. تقوم فكرة Session على تخزين البيانات في store  يحتفظ به التطبيق persist data  عبر الطلبات الواردة من العميل. يمكنك استخدام البيانات المخزنة في Session variable في أي مكان في موقع الويب الخاص بك.
    لتمكينsession  في التطبيق لا بد من إضافة الأوامر التالية 


    الامر 
    المكان 
    services.AddSession() 
    ()ConfigureServices  في ملف Startup
    app.UseSession() 
    ()Configure  ملف Startup

    كود الملف Startup الخاص بالمشروع 

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.HttpsPolicy;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using StudentsAcademy.Services;
    using StudentsAcademy.Middleware;
    using StudentsAcademy.Share;
    using Microsoft.EntityFrameworkCore;
    using StudentsAcademy.Interface;
    using StudentsAcademy.Repository;
    using StudentsAcademy.Models;
    namespace StudentsAcademy
    {
        public class Startup
        {
            public IConfiguration Configuration { get; }
            private IWebHostEnvironment env;
            
            public Startup(IConfiguration configuration, IWebHostEnvironment hostEnv)
            {
                Configuration = configuration;
                env = hostEnv;
            }
          
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddTransient<ICourses>(provider =>
                {
                    if (env.IsDevelopment())
                    {
                        var x = provider.GetService<CourseRepository>();
                        return x;
                    }
                    else
                    {
                        return new ClassRoomsRepository();
                    }
                });
               // services.AddTransient<ICourses>();
                services.Configure<Connections>(Configuration.GetSection("ConnectionStrings"));
                services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
                //services.AddTransient<ICourses, CourseRepository>();
                //services.AddScoped<ICourses, CourseRepository>();
                //services.AddSingleton<ICourses, CourseRepository>();
                services.AddTransient<IStorage, StorageRepository>();
                services.AddTransient<CourseSum>();
                services.AddSingleton<TotalStudents>();
                services.Configure<MyJson>(Configuration);
                services.AddControllersWithViews();
                services.AddSession();
            }
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                    app.UseStatusCodePages();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
               
                app.UseHttpsRedirection();
                app.UseStaticFiles();
                if ((Configuration.GetSection("Middleware")?.GetValue<bool>("EnableResponseEditingMiddleware")).Value)
                {
                    app.UseMiddleware<ResponseEditingMiddleware>();
                }
                if ((Configuration.GetSection("Middleware")?.GetValue<bool>("EnableRequestEditingMiddleware")).Value)
                {
                    app.UseMiddleware<RequestEditingMiddleware>();
                }
                if ((Configuration.GetSection("Middleware")?.GetValue<bool>("EnableShortCircuitMiddleware")).Value)
                {
                    app.UseMiddleware<ShortCircuitMiddleware>();
                }
                if ((Configuration.GetSection("Middleware")?.GetValue<bool>("EnableContentMiddleware")).Value)
                {
                    app.UseMiddleware<ContentMiddleware>();
                }
                //app.UseMiddleware<ResponseEditingMiddleware>();
                //app.UseMiddleware<RequestEditingMiddleware>();
                //app.UseMiddleware<ShortCircuitMiddleware>();
                //app.UseMiddleware<ContentMiddleware>();
                app.UseSession();
                app.UseRouting();
                app.UseAuthorization();
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllerRoute(
                        name: "default",
                        pattern: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }
    }





    لإضافة Session يجب ان تكون طريقة الكتابة بالشكل التالي 

    HttpContext.Session.SetString("SessionName",SessionValue ));

    لفهم كيف تعمل Session State. سنقوم بإضافة Session داخل action المسمى NewStudent في StudentsController
    تأكد من الغاء TempData الذي استخدمناه سابقا
    انتقل الى action المسمى NewStudent في StudentsController ثم أضف الكود التالي :

    public IActionResult NewStudent()
            {
                HttpContext.Session.SetString("UserName", "Admin");
                //TempData["UserName"] = "Admin";
                return View();
            } 

    يجب إضافة namespace Microsoft.AspNetCore.Http في controller لاستخدام session.
    تعمل طريقة ()SetString  على إضافة وتحويل أي قيمة ك string إلى session variable. في هذه الحالة، عملنا إضافة اسم المستخدم admin.
    للوصول إلى قيمة session’s variable في view، يجب عليك إضافة singleton service إلى طريقة ()ConfigureServices  الخاصة بـ Startup.cs كما هو موضح أدناه

    public void ConfigureServices(IServiceCollection services)
            {
                services.AddTransient<ICourses>(provider =>
                {
                    if (env.IsDevelopment())
                    {
                        var x = provider.GetService<CourseRepository>();
                        return x;
                    }
                    else
                    {
                        return new ClassRoomsRepository();
                    }
                });
               // services.AddTransient<ICourses>();
                services.Configure<Connections>(Configuration.GetSection("ConnectionStrings"));
                services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
                //services.AddTransient<ICourses, CourseRepository>();
                //services.AddScoped<ICourses, CourseRepository>();
                //services.AddSingleton<ICourses, CourseRepository>();
                services.AddTransient<IStorage, StorageRepository>();
                services.AddTransient<CourseSum>();
                services.AddSingleton<TotalStudents>();
                services.Configure<MyJson>(Configuration);
                services.AddControllersWithViews();
                services.AddSession();
                services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            }

    عدم إضافة هذا الكود سيؤدي الى خطأ

    يجب إضافة الأوامر التالية ل View، سنقوم هنا بإضافتها الى ملف ViewImports.cshtml بدل من تكرارها في جميع Views 
    سيكون شكل ViewImports.cshtml كالتالي:

    @using StudentsAcademy
    @using StudentsAcademy.Models
    @using Microsoft.AspNetCore.Http
    @inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

    انتقل الى NewStudent View ثم أضف الكود التالي لعرض قيمة Session: 

    @model StudentsModel
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
    </head>
    <body>
        @*Welcome ,@TempData["UserName"]*@
        Welcome,@HttpContextAccessor.HttpContext.Session.GetString("UserName")
        <hr />
        <div class="container">
            <form method="post" asp-action="ReceivedDataByModelBinding">
                <div class="form-group">
                    <label>CustomerNo:</label>
                    <input class="form-control" asp-for="CustomerNo" />
                </div>
                <div class="form-group">
                    <label>FullName:</label>
                    <input class="form-control" asp-for="FullName" />
                </div>
                <div class="form-group">
                    <label>Birthday:</label>
                    <input class="form-control" asp-for="Birthday" />
                </div>
                <div class="form-group">
                    <label>Gender:</label>
                    <select class="form-control" asp-for="Gender">
                        <option value="M">Male</option>
                        <option value="F">Female</option>
                    </select>
                </div>
                <div class="form-group">
                    <label>Nationality:</label>
                    <select class="form-control" asp-for="Nationality">
                        <option value="M">Jordan</option>
                        <option value="F">Saudi Aribae</option>
                        <option value="F">UAE</option>
                    </select>
                </div>
                <div class="form-group">
                    <label>Address:</label>
                    <input class="form-control" asp-for="Address" />
                </div>
                <div class="form-group">
                    <label>UserName:</label>
                    <input class="form-control" asp-for="UserName" />
                </div>
                <div class="form-group">
                    <label>Password:</label>
                    <input class="form-control" asp-for="Password" />
                </div>
                <div class="form-group">
                    <label>Email:</label>
                    <input class="form-control" asp-for="Email" />
                </div>
                <div class="form-group">
                    <label>Mobile:</label>
                    <input class="form-control" asp-for="Mobile" />
                </div>
                <div class="form-group">
                    <label>Note:</label>
                    <input class="form-control" asp-for="Note" />
                </div>

                <button class="btn btn-primary" type="submit">Submit</button>
            </form>
        </div>
    </body>
    </html>
    لقد قمنا بإضافة namespace  Microsoft.AspNetCore.Http. ثم قمنا بعمل injected لsingleton object  من خلال توجيه الحقن باستخدام ASP.NET Core Dependency Injection.
    أخيرًا ، حصلنا على قيمة session values باستخدام  الأمر :
    Welcome,@HttpContextAccessor.HttpContext.Session.GetString("UserName")

    قم بتشغيل التطبيق ثم انتقل الى الرابط التالي  https://localhost:44382/students/NewStudent




    معلومات مهمه حول Session

    تمامًا مثل طريقة ()SetString ، تحتوي session أيضًا على () SetInt32 التي تخزن القيمة int في session variable:

    HttpContext.Session.SetInt32("MySession", 100);

    لتحديد وقت انتهاء ل session أضف الكود التالي داخل ConfigureServices في Startup، حيث حددنا هنا مدة Session ب 30 دقيقة


    public void ConfigureServices(IServiceCollection services)
            {
                services.AddTransient<ICourses>(provider =>
                {
                    if (env.IsDevelopment())
                    {
                        var x = provider.GetService<CourseRepository>();
                        return x;
                    }
                    else
                    {
                        return new ClassRoomsRepository();
                    }
                });
               // services.AddTransient<ICourses>();
                services.Configure<Connections>(Configuration.GetSection("ConnectionStrings"));
                services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
                //services.AddTransient<ICourses, CourseRepository>();
                //services.AddScoped<ICourses, CourseRepository>();
                //services.AddSingleton<ICourses, CourseRepository>();
                services.AddTransient<IStorage, StorageRepository>();
                services.AddTransient<CourseSum>();
                services.AddSingleton<TotalStudents>();
                services.Configure<MyJson>(Configuration);
                services.AddControllersWithViews();
                services.AddSession();
                services.AddSession(options => {
                    options.IdleTimeout = TimeSpan.FromMinutes(30);
                });

                services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            }

    تخزين أنواع معقده complex data

    يمكن تخزين اناع معقده في Session مثل class variable،  ولازم حتي نتعامل مع الاناع المعقدة القيام بالتالي:
    اولا إجراء serialize.
    ثانيا عمل De-serialize للحصول على القيم serialized من session.

    تمام حتي نفهم الموضوع بشكل افضل نطبق مثال عملي :
    المثال هو تخزين اسم المستخدم وكلمة المرور

    في هذا المثال سنعمل على إنشاء Controller للتأكد من اسم المستخدم وكلمة المرور وبعدها بنخزين اسم المستخدم وكلمة المرور داخل session ومن ثم ارسال هذا session الى View لعرض البيانات. 
    تمام التمام نبدا بعمل class داخل مجلد Models باسم LoginAuthentication ثم أضف الكود التالي : 


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    namespace StudentsAcademy.Models
    {
        public class LoginAuthentication
        {
            public string UserName { get; set; }
            public string Password { get; set; }
        }
    }

    ثم أضف ملف class آخر داخل مجلد Models باسم SessionExtensions كما في الكود الموضح ادناه، الغرض من هذا الملف هو تعريف 2 function  لاستقبال وعرض ال complex data في session.

    using Microsoft.AspNetCore.Http;
    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    namespace StudentsAcademy.Models
    {
        public static class SessionExtensions
        {
            public static void Set<T>(this ISession session, string key, T value)
            {
                session.SetString(key, JsonConvert.SerializeObject(value));
            }
            public static T Get<T>(this ISession session, string key)
            {
                var value = session.GetString(key);
                return value == null ? default(T) :
                    JsonConvert.DeserializeObject<T>(value);
            }
        }
    }
    سنقوم هنا بتثبيت اسم المستخدم وكلمة المرور لغاية فهم الطريقة، لاحقا سنقرا هذه البيانات من قواعد البيانات.
    انتقل الى LoginController بعد اضافته واضف action باسم CheckUserNamePassword  

    using Microsoft.AspNetCore.Mvc;
    using StudentsAcademy.Interface;
    using StudentsAcademy.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    namespace StudentsAcademy.Controllers
    {
        public class LoginController : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
            public IActionResult Hello()
            {
                ViewBag.Message = "Hello World";
                return View();
            }
            public IActionResult CheckUserNamePassword()
            {
                HttpContext.Session.Set("UserDetails", new LoginModel
                {
                    UserName = "Admin",
                    Password = "Admin"
                });     
                return RedirectToAction("StudentInfo", "Students");
            }

        }
    }

    نفهم الكود :
    في action المسمى CheckUserNamePassword استخدمنا function المسمى Set وهذا ال function عرفناه مسباق في ملفSessionExtensions وفي هذا ال function اضفنا  username، password الى Session
    وفي السطر الأخير تم إعادة التوجيه الى View باستخدام الامر RedirectToAction والسبب في ذلك ان هذا View المطلوب StudentInfo موجود في مجلد مختلف عن مجلد Students
    في هذه المرحلة تم تثبيت username، passwordوذلك لغرض فهم الموضوع، سنقوم لاحقا بإرجاع هذه المعلومات من قاعدة البيانات 
    الان دور نعمل View لإدخال اسم المستخدم وكلمة المرور. 
    انتقل الى action المسمى Index في Login controller ثم اضف View بالنقر يمين فوق action واختر Add new View ليكون شكل التطبيق :

    ثم أضف الكود التالي: 

    @model LoginModel
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
    </head>
    <body>
          <div class="container">
            <form method="post" asp-action="CheckUserNamePassword">
      
                <div class="form-group">
                    <label>UserName:</label>
                    <input class="form-control" asp-for="UserName" />
                </div>
                <div class="form-group">
                    <label>Password:</label>
                    <input class="form-control" asp-for="Password" />
                </div>
                
                <button class="btn btn-primary" type="submit">Submit</button>
            </form>
        </div>
    </body>
    </html>
    تمام نفهم الكود :
    استخدمنا الامر :
      <form method="post" asp-action="CheckUserNamePassword">
    وذلك لربط هذا View  مع action  باسم  CheckUserNamePassword والنوع Post ، يعني عند النقر فوق Submit في هذا ال View يتم استدعاء ال action المسمى CheckUserNamePassword والامر asp-action هو المسؤول عن هذا الربط.
    بعد هيك اضفنا 2 control في الصفحة من نوع input بهدف ادخال اسم المستخدم وكلمة المرو ، الكود الذي يعمل على ذلك : 
     <input class="form-control" asp-for="UserName" />
     <input class="form-control" asp-for="Password" />
    الامر asp-for هو المسوؤل عن ربط هذا control مع property الموجود في model تذكر ان في اول هذا View استخدمنا الكود
     @model LoginModel
    والي بيعني ان هذا View مربوط مع LoginModel 

    قم بتشغيل المشروع بالانتقال الى الرابط
    https://localhost:44382/Login

    سيكون شكل التطبيق :


    ثم انقر فوق زر Submit 
    ملاحظات :
    في هذه المرحلة ما عملنا تأكد من صحة اسم المستخدم وكلمة المرور، فقط عملنا كود يعمل على الانتقال مباشرة ال StudentInfo View،مع تخزين اسم المستخدم وكلمة المرور في Session ثم سنقوم بعرض القيم المخزنة في Session. 
    ننتقل الى View المسمى StudentInfo أضف الكود التالي لاستقبال Session 

    var userContent = HttpContext.Session.Get<LoginModel>("UserDetails");
    ViewBag.UserName = userContent.UserName;

    نفهم الكود:
    عرفنا متغير باسم userContent لاستقبال Session باستخدام function المسمى Get وهذا ال function معرف في ملف SessionExtensions ، ومن ثم استخدمنا ViewBag لإرجاع اسم المستخدم
    يمكن ارجاع اسم المستخدم مباشرة دون استخدام ViewBag 
    قم بتشغيل التطبيق ستكون النتيجة:





    لتخزين Session’s cookie و expiration time يمكن إضافة الكود التالي داخل ()services.AddSession  في ملف Startup

    services.AddSession(options => {
                    options.Cookie.Name = "UserDetails.Session"; // Cookie name
                    options.IdleTimeout = TimeSpan.FromMinutes(30); // Expire Time after 30 min
                });