0% found this document useful (0 votes)
6 views46 pages

07 ASP - NET Core MVC Notes

تتناول الوثيقة أساسيات ASP.NET Core MVC، حيث تشرح المعمارية المعتمدة على نمط Model-View-Controller (MVC) الذي يقسم التطبيق إلى ثلاثة مكونات رئيسية: النماذج (Models) والعرض (Views) ووحدات التحكم (Controllers). كما تتطرق إلى كيفية نشر التطبيقات على الخوادم المختلفة، وتفاصيل حول البروتوكولات المستخدمة مثل HTTP وHTTPS، بالإضافة إلى كيفية إعداد مشروع MVC باستخدام Visual Studio.

Uploaded by

saraelshorbage11
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views46 pages

07 ASP - NET Core MVC Notes

تتناول الوثيقة أساسيات ASP.NET Core MVC، حيث تشرح المعمارية المعتمدة على نمط Model-View-Controller (MVC) الذي يقسم التطبيق إلى ثلاثة مكونات رئيسية: النماذج (Models) والعرض (Views) ووحدات التحكم (Controllers). كما تتطرق إلى كيفية نشر التطبيقات على الخوادم المختلفة، وتفاصيل حول البروتوكولات المستخدمة مثل HTTP وHTTPS، بالإضافة إلى كيفية إعداد مشروع MVC باستخدام Visual Studio.

Uploaded by

saraelshorbage11
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 46

‫‪07 ASP.

NET Core MVCNotes‬‬


‫‪Session 01‬‬
‫‪ASP.NET Core MVC‬‬
‫الـ ‪ .NET‬هو تراك كامل متكامل نقدر من خالله نبني ابلكيشن مختلفة سوء كانت ‪web , desktop,mobile,AI,Gaming,iot,cloud‬‬
‫وعشان اشتغل ‪ web‬عندي ‪ 2‬تكنولوجى وهما ‪ ASP.NET , Blazor‬وانا هستخدم ‪ ASP.NET‬واقدر من خاللها اعمل ‪ 3‬حاجات‬
‫‪Rezor page(MVVM ModelsentInfoToViewViewSentInfoToModel) , web API ,MVC‬‬

‫‪ASP.Net MVC‬‬
‫وهي اختصار ل ‪ Model View Controller‬وهي عبارة عن‬
‫‪architectural pattern separates an application into three main components‬‬
‫يعنى من خاللها بتحدد المعمارية بتاعت البروجكت بيقوم بتقسم البروجكت بتاعى الي ‪ 3‬كومبوننت وهما الـ‬
‫هو الكالس اللى بيمثل الجدول الموجودة عندى ف الداتا بيز ‪Model‬‬
‫هو صفحة ال اتش تي ام ال او الصفحات اللى بيتعرض فيها االبلكيشن بتاعى ‪View‬‬
‫هو المتحكم في البروجكت كله وبيعمل بروسيسنج ‪Controller‬‬
‫‪Client , Server‬‬
‫الـ ‪ Client‬هو الجهاز ال ‪ Installed‬عليه ال ‪ prowser‬زي ‪ . google chrome‬وانا اللى قاعد على الجهاز دا اسمي ‪End User‬‬
‫الـ ‪ Server‬هو جهاز برضو بيكون امكانياته اكبر شوية وهو الجهاز الـ ‪ Deployde‬عليه الـ ‪ web Application‬ف انا لما بخلص عمل‬
‫االبلكيشن بتاعى بروح اعمله ‪ deploye‬علي السيرفر والسيرفر دا يكون له ‪ ip‬يكون متشاف سرو االنترنت ‪.‬‬
‫‪HTTP , HTTPS‬‬
‫يعنى ‪The Hypertext Transfer Protocol is an application protocol for distributed, collaborative, and‬‬
‫‪hypermedia information systems.‬‬

‫يعنى القواعد المتابعة للترنسفير بتاع ال ‪ html‬يعنى بكل بساطة القواعد المتابعة لنقل صفحات ال ‪ html‬من السيرفر لل ‪ client‬ف انا لما ببعت‬
‫‪ request‬بيرد عليا السيرفر ب ‪ . response‬هل دا البروتكول الوحيد الموجود ال فى واحد تانى ‪ FTP‬البروتكول المتبع لنقل الفايل من ال‬
‫‪ client‬للسيرفر ‪.‬عندى واحد تانى اسمه ‪ CTP‬بستخدمه عشان اعمل ‪ real time appllication‬زي مثال عايز اعمل نوتيفكيشن شاتينج زي‬
‫الواتساب ‪ ...‬عندى فيرجن تانيه من ال ‪ http‬اسمها ‪ https‬طب اي الفرق ما بينهم‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 1‬‬


‫عشان نبقا عارفين ان البرتوكول دا بيتكون من ‪ . layers‬فالـ ‪ layer‬بتاعت ال ‪ http‬مفهوش ‪ securty‬انما ‪ https‬دا ‪ encrypted‬بيكون‬
‫في ‪ securty‬ف دا في ‪ layer‬زيادة خاصة بال ‪ securty‬وال ‪ s‬الموجودة فى ال ‪ https‬دي اختصار ل ‪ . Securty‬فاحنا هنشتغل بي‬
‫عشان امين واللى بيروح ي ‪ encrypt‬ال ‪ response‬بتاعى هو جوجل ف انا بكون محتاج اروح اشتري اكستيشن خاص بجوجل وانزله علي‬
‫السيرفر عشان يعملي ‪ encrypt‬واسمه ‪. SSL certificate‬‬

‫صفحة ال ‪ html‬مش بتيجي لوحدها ف ال ‪ response‬اللى جاي من السيرفر بيجي معاها ملفات ‪ css, js‬الحاجات دي اسمها ‪resources‬‬

‫‪URL‬‬
‫هو اختصار ل ‪ Uniform Resource Locator‬ودا اللى بيحدد اللوكيشن بتاع الـ ‪ Resource‬يعنى مثال لو عايز اجيب الفيلم اللى اسمه‬
‫‪ blackAdam‬ف بروح اكتب ‪ www.netfelx.com:80/Movies/GetMovie?id=5&name=BlackAdam‬وهكذا‬

‫‪ ---‬عشان اعمل ‪ deploye‬معنديش غير ‪ 3‬حلول وهما ‪ -1‬ياما استضافة بدفعلها فلوس ‪ -2‬ياما بشتري سيرفر ‪ -3‬ياما بأجر من داتا سنتر‬
‫ومعنديش داتا سنتر ف مصر انما فى فى اوروبا والسعودية واالمارات ‪ ..‬وفي العادى بيكون عندى الماشيين بتاعتنا بتكون خاصة بينا الن بروجكت‬
‫ال ‪ .net‬بتكون كبيرة جدا ف بنروح نشتريلها سيرفر ‪ .‬طب ليه ف االمارات بيرفعو على الفيرشوال ماشين (داتا سنتر) عشان مايكرسوفت بتوفر‬
‫فيتشر مش موجودة فى انك لو اشتريت ماشين خاصة بيك ‪ .‬اي ماشين بيكون ليها ‪ ip‬وعشان استخدم حاجة مرفوعة ع الماشين دي او السيرفر دا‬
‫هكتب ال ‪ Ip‬بس دا مش افضل حاجة النى مش هحفظ ال ‪ ip‬ف كان الحل ان يكون لكل بروجكت ‪ port‬معين ف الريكوست اللى بيروح للسيرفر‬
‫‪Port‬‬ ‫بيروح سرو البورت دا‬
‫ف البورت هو نقطة الكالم بتاعتنا مع االبلكيشن الفالنى ‪ .‬واقدر استخدم اي بورت فوق ال ‪ 1221‬يعنى معايا ‪ 1221‬وهكذا وكمان معايا ‪ 02‬فقط ‪.‬‬
‫ف احنا عشان ننادي على بروجكت معين كنت بكتب ال ‪ ip‬واكتب رقم ال‪ port‬بس دا قولنا مش افضل حاجة ف الحل اننا نسمي الويب سايت ‪.‬‬
‫‪Host‬‬
‫دا اللى بنسمي الـ ‪ host name‬ودا تعويضا عن ال ‪ ip‬وال ‪ port‬ودا بيكون ‪ . uniqe‬ف انا بروح اشتري هوست نيم واشهر االماكن ‪Godaddy‬‬
‫الفرق ما بين ‪ .com‬و ‪.info‬‬
‫بتحدد الكاتيجري بتاعت الويب سايت ف ‪ .com‬خاصة بالحاجات التجارية ام ا‪ .info‬خاصة بالمواقع االخبارية‬
‫‪ ---‬ف انا ممكن اكتب ال ‪ ip‬بتاع الجهاز الموجود عليه الويب سايت بتاعى في السيرش وهيجبهولي وممكن اكتب الهوست نيم مثال ‪Ip‬‬
‫‪ google‬هفتح ال‪ cmd‬واكتب ‪ ping google.com‬هيجبلي ال ‪ ip‬هاخده كوبي وارمي ف السيرش هيجبلي جوجل وممكن اكتب‬
‫‪ google.com‬هيجبلي جوجل برضو ‪.‬‬
‫ملحوظة ‪URL vs URN‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 2‬‬


‫الـ ‪ url‬هيجبلي الصفحة كلها اما ال ‪ urn‬هيجبلي الصفحة كلها برضو بس هيقف عند سيكشن معين داخل الصفحة دي‬
‫‪HTTP Messages‬‬
‫الـ ‪ HTTP‬عندها ‪ Messages 2‬وهما ‪ request , response‬ف اللى بيبعت ال ‪ request message‬هو الـ ‪ browser‬بيبعتها‬
‫للسيرفر والسيرفر بيرد عليه بالـ ‪ response message‬ف اللى بيبني ال‪ request message‬هو ال ‪ browser‬ف انا بكتب اللينك‬
‫وهو بيبني ‪ ..‬وال ‪ request message‬بتتكون من ‪header , body‬‬

‫‪Web Application‬‬

‫‪.Net Core vs .Net Framework‬‬


‫الـ ‪ .net core‬الفرق االكبر هي ‪ cross platform‬يعنى اقدر اعمله ‪ deploye‬علي ‪ mac,windows,linex‬وكان عندنا مشكلة بتاعت‬
‫ال ‪ development‬االول مكنتش بقدر اشتغل غير علي ‪ windows‬ومقدرش اشتغل علي ‪ mac,linex‬بس المشكلة اتحلت في ال ‪core‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 3‬‬


‫الـ ‪ Kestrel‬عبارة عن ‪ console‬ابلكيشن وبيحصله ‪ build‬بيزد اون االوبريتنج سيستم الموجود عليه ‪ .‬وهو اللي بيهندل الريكوست مش‬
‫السيرفر الن هنا ال ‪iis‬او‪Apache‬او‪ Nginx‬هما عبارة عن كوبري ليس اال مابين الكالينت والكيسترال‬

‫والـ ‪ Kestrel‬بيتكون من شوية مراحل (مواسير) فالريكوست بتاعنا بيمر بكذا مرحلة وهما عبارة عن ‪ 0‬مراحل وممكن انا ازود مرحلة ومن‬
‫خالله بنحدد المراحل او المرحلة اللى هيمر بيها الريكوست وبعد كدا يكلم االبلكيشن بتاعنا ‪ .‬انما ايام زمان كان الـ ‪ IIS‬هو اللى بيهندل الريكوست‬

‫‪ASP.NET MVC‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 4‬‬


MVC application will be split into at least three pieces:
Models, which contain or represent the data that users work with.
Views, which are used to render some part of the model as a user interface.
Controllers, which process incoming requests, perform operations on the model, and select views
to render to the user.
Each piece of the MVC architecture is well-defined and self-contained—this is referred to as the
separation of concerns. The logic that manipulates the data in the model is contained only in the
model; the logic that displays data is only in the view, and the code that handles user requests
and input is contained only in the controller. With a clear division between each of the pieces,
your application will be easier to maintain and extend over its lifetime, no matter how large it
becomes.
MVC Model Integrity :
are constraints that can be used by the application's data validation mechanisms for catching
these cases of flawed data. Integrity constraints are logical conditions that must be satisfied by
the data of the business objects stored in the application's database.
MVC Model Consistency :
Ensure from data format which will saved using model.

How to Create MVC Project


Open VS + CreateNewProject + select web + choose ASP.NET Core + next + .net5

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 5


‫هيفتح البروجكت وهتالقي كام حاجة ف الجنب كدا وفي فولدر اسمه ‪ properties‬هتالقي في ملف ‪ launchSettings.json‬ودا خاص بال‬
‫‪ run‬ودا شغال ‪ local‬فقط في وقت الرن علي ال ‪ vs‬وبداخله ‪ 2‬بروبرتي واحدة فيهم االعدادات بتاعت ال ‪ iis‬والتاني ‪ profiles‬ودي خاصة‬
‫بالرن وبداخله ‪ 2‬بروفايل واحد اسمه ‪ iis express‬ودا بيروح يقوم ال ‪ as iis‬سيرفر ‪ ..‬اما التاني وهو ال ‪ kestrel‬واسمه بيكون باسم‬
‫البروجكت‬

‫‪Kestrel‬‬

‫وبيكون عندى ملف اسمه ‪ appSettings‬ودا بيكون عندي منه ‪ 1‬فيرجن واحد لل ‪ development‬اللى هو انا والتاني للتيست والتالت‬
‫للدبلوي والرابع لل برودكشن وبيكون عندى انا بتاع ال ‪ dev‬ودا بيكون في ال ‪ seetings‬او ال ‪ confegration‬بتاعت االبلكيشن ومن‬
‫ضمنها ال ‪ connection string‬اللى هي االتصال بالداتا بيز يعنى ‪.‬‬

‫وهنالقي عندنا كالس اسمه ‪ program‬وهو دا ال ‪ kestrel‬هو بروجكت ال ‪ console‬وبيكون بداخله فانكشن ال ‪main‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 6‬‬


‫وكمان عندى كالس اسمه ‪ Starup‬ودا بيكون فى ال ‪ confegration‬بتاعت ال ‪ kestrel‬وبداخله ‪ 2‬فانكشن واللى بيرن الفانكشنز دي الـ‬
‫‪ CLR‬وبداخله بضيف في اي سيرفس انا محتاج اعملها ‪ dependency injection‬داخل كونتينر ال ‪ services‬ودا مهم اوي وكمان عندى‬
‫فانكشن تانيه اسمها ‪ Configure‬ودي بتكونفجر ال ‪ http request pipeline‬وداخل الفانكشن دي بنحدد ال ‪ pipeline‬اللى ريكوست‬
‫بيمر بيها اثناء وجوده في ال ‪ kestrel‬زي مثال ال ‪ IsDevelopment‬ودي لو في مشكلة حصلت بيبعتلي ايرور بيقولي اى المشكلة وممكن بعد‬
‫ما اخلص عمل االبلكيشن اقوله ‪ else‬ويظهرلي جملة او صورة تعبر عن ايرور الن انا مش هظهر لليوزر االيرور يعنى ‪ ..‬وكمان عندى بداخله‬
‫التحديث اللى تم فى ‪ .net6‬هو ان ال ‪ 2‬كالس دول بقو ف كالس واحد (فايل واحد)‬ ‫‪ routing‬ودا هنتكلم عليه تفصيلي تحت ‪.‬‬

‫;)(‪app.UseRouting‬‬
‫بتأخد اللينك وتشوفه بيماتش انهى راوت او طريق من الطرق الموجودة عندى في ال ‪ endpoint.MapGet‬ودى بتكون داخل‬
‫‪ middleWare‬تانيه اسمها ‪ app.UseEndpoints‬وبكتب فيها الروتنج اللى محتاجه‬
‫;)(‪app.UseRouting‬‬

‫>= ‪app.UseEndpoints(endpoints‬‬
‫{‬
‫فهو هنا كدا بقولو لو انا مش كاتب حاجة خالص نفذ الفانكشن دي هيطبع هالوورلد‪endpoints.MapGet("/", async context => //‬‬
‫{‬
‫;)"!‪await context.Response.WriteAsync("Hello World‬‬
‫;)}‬
‫;)}‬

‫ولو قولتله كدا يبقا الزم اكتب فوق ف اللينك اسالش حماده‪endpoints.MapGet("/hamada", async context => //‬‬

‫وممكن اكوبي من ال ‪ endpoints‬بحيث فى االولى اقوله ‪ /hamada‬ويطبعلي ‪ helloWorld‬والتانيه اقوله ‪ /index‬ويطبعلي‬


‫‪ helloIndex‬زي المثال دا كدا‬
‫;)(‪app.UseRouting‬‬

‫>= ‪app.UseEndpoints(endpoints‬‬
‫{‬
‫>= ‪endpoints.MapGet("/hamada", async context‬‬
‫{‬
‫;)"!‪await context.Response.WriteAsync("Hello World‬‬
‫;)}‬
‫>= ‪endpoints.MapGet("/index", async context‬‬
‫{‬
‫;)"!‪await context.Response.WriteAsync("Hello From Index‬‬
‫;)}‬
‫;)}‬

‫وكمان عندى فانكشن اسمها ‪ mapControllerRoute‬ودى من خاللها بقدر اضيف كنترول وميزود و اي دي مثال لو انا عملت كنترول اسمه‬
‫‪ movies‬وبداخله ‪ method‬اسمها ‪ getMovie‬بواسطة ال ‪ id‬ف انا بكتب الروت بتاعها كدا بالشكل اللى تحت دا ودى بكتبها داخل ال‬
‫>= ‪ app.UseEndpoints(endpoints‬بنفس طريقة ال ‪mapGet‬‬
‫(‪endpoints.MapControllerRoute‬‬
‫‪name: "default",‬‬
‫كدا انا بقوله ممكن تبعتلي اي دي او ممكن ال وكذلك ممكن مع االكشن}?‪pattern: "{controller}/{action}/{id}" //{id‬‬
‫;)‬

‫بس هو هنا هيجبلي ايرور عشان خاطر البروجكت دا ‪ empty‬محددتش في هل هو ‪ mvc,razorPage,WebAPI‬فبالتالى محتاج اروح اقوله‬
‫فوق فى ‪ ConfigureServices‬انى هستخدم انهى نوعه ودا بيكون حقن انجيكشن بالشكل دا‬
‫)‪public void ConfigureServices(IServiceCollection services‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 7‬‬


{
services.AddControllersWithViews(); // MVC
} ‫ولو حبيت اقوله انى هشتغل ريزور بيدج او اي بي اي هكتبله كدا او كدا داخل فانكشن الكونفيجريشن سيرفس دي‬

//services.AddRazorPages(); // Rezor Page


//services.AddControllers(); // Web API
‫بس كدا خلصنا من اول ايرور وهيقابلنا ايرور تاني ان اللينك مش شغال ليه النى لسه معملتش كونترولر وال اكشن ميزود وال اى حاجة وعشان‬
‫ والزم يكون‬Controller ‫ وبداخله كالس الزم يكون اسمه بينتهي بكلمة‬controllers ‫احل المشكلة دى هروح اعمل فولدر الزم يكون اسمه‬
‫ بالشكل دا‬GetMovie ‫ وهعمل بداخله ميزود اسمها‬Controller ‫بيورث من كالس اسمه‬
public class MoviesController : Controller
{
public void GetMovie()
{
}
}
‫ اما‬pattern: "hamada/{controller}/{action}/{id?}" ‫ ب ايدي زي كدا‬pattern ‫ يعنى انا بكتب ال‬static ‫ انواع‬3 ‫ودا بيكون له‬
pattern: "/XX{controller}/ ‫ او ميكسد بالشكل دا‬pattern: "hamada/{controller}/{action}/{id?}" Variable ‫النوع التانى‬

‫ يعني لو مكتبش ف اللينك اسم كنترول يروح على كنترول كديفولت وبعمله‬controller ‫ او للـ‬action ‫ للـ‬default value ‫وكمان اقدر اديله‬
‫بالشكل دا ودا القديم‬
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}", //"{controller}/{action=Index}/{id?}"
defaults : new { action = "Index" }
);‫اما الشكل الجديد باجي جنب كلمة اكشن اللى فى الباترن واديله الديفولت بالشكل دا كدا وبمسح ديفولتس دي‬
endpoints.MapControllerRoute(
name: "default",
pattern: "hamada/{controller=Home}/{action=Index}/{id?}",
);
‫ والكونسترينت موجودة ف اللينك دا‬id ‫ دا اقدر احددله النوع بتاعه وعندى شكلين او طريقتين له وافضل طريقة اني اكتب جنب كلمة‬id ‫وكمان ال‬
endpoints.MapControllerRoute(
name: "default",
pattern: "hamada/{controller=Home}/{action=Index}/{id:int?}" //id: alpha? [‫ يعني‬string]//id: bool?
// constraints:new {id = new IntRouteConstraint()}
// defaults : new { action = "Index" }
); https://www.c-sharpcorner.com/blogs/asp-net-core-route-constraints

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 8


Session 02
Retrun Type of Action
‫ وبداخل الفانكشن بكريت‬contentResult ‫فى الحقيقة لو نا عايز االكشن يرجعلي استرينج مبقولوش في الفانكشن ان هي استرنج ال انما بقوله‬
‫منها اوبجكت وبعد كدا برجع اللى محتاجه طب ليه االفه دي كلها بقا عشان من خاللها بقدر اتحكم فى نوع(التايب) بتاع الكونتنت اللى جاي من‬
pdf ‫ وبكدا اتحكمت ف النوع انه‬object/pdf ‫ وانا ممكن اغيره اخلى مثال‬object/html ‫السيرفر والديفلت بتاعه‬
public class MoviesController : Controller
{
public ContentResult index()
{
ContentResult Result = new ContentResult();
Result.Content = "index";
Result.ContentType = "object/pdf";
//ContentResult.Content = "index";
return Result;
}
}

‫ ومن خاللها اقدر اقوله لما تكتبلي اللينك دا يروح على لينك تاني انا بحددهله بالشكل دا‬RedirectResult ‫وكمان ممكن اخلي يرجعلي‬
public class MoviesController : Controller
{
public RedirectResult index()
{
RedirectResult Result = new RedirectResult("https://localhost:44302/index");
return Result;
}
}

‫ف انا كدا بجبره انه يرجع لينك معين بالنسبة للدايركت ريسلت وفى الكونتنت ريسلت بجبره يرجعلي حاجة معينة ودا مش هيكون افضل حاجة ف انا هقوله‬
IactionResult ‫ بتاعه هو‬pernat‫ وال‬Parent ‫ او اي حاجة بتورث من ال‬perant ‫ بتاعه فهو كدا هيقدر يرجعلي ال‬perant ‫رجع من ال‬

public IActionResult index()


{
ContentResult Result = new ContentResult();
Result.Content = "index";
Result.ContentType = "text/html";
return Result;
}

public IActionResult hamada()


{
RedirectResult Result = new RedirectResult("https://localhost:44302/index");
‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 9
‫;‪return Result‬‬
‫}‬

‫وكل ‪ ActionResult‬عندي له ‪ HelperMethod‬بتسهل عليا بدل اكريت اوبجكت واكتب كذا خطوة وبيكون بالشكل دا وعندنا اكشن ريسلت كتير‬
‫‪public class MoviesController : Controller‬‬
‫{‬
‫)(‪public IActionResult index‬‬
‫{‬
‫;)"‪return Content("index‬‬
‫}‬

‫)(‪public IActionResult hamada‬‬


‫{‬
‫;))‪return RedirectToAction(nameof(index‬‬
‫دا اختصار افضل من انى اكتب اللينك النى لما برفع برودكشن مش بيكون على لوكل هوست فهو كدا دينمك معاايا وقولتله نيم اوف عشان لو االسم غلط يجبلي ايرور‪//‬‬
‫}‬
‫}‬

‫وعندي فانكشن اسمها ‪ redirectToRoute‬دى من خاللها بقوله لما تكتب ف اللينك كذا روح علي الروت دا‬
‫)(‪public IActionResult hamada‬‬
‫{‬
‫;)}"‪return RedirectToRoute("default", new {controller="Home" , action = "Index‬‬
‫}‬

‫‪Action Parameters Binding‬‬


‫يعنى عايز اعمل اكشن بيأخد ‪ id‬معين وبيرجعلي استرينج ‪ ..‬وال ‪ parameters‬بتاعت االكشن بتأخد ال ‪ value‬بتاعتها او بتـ‪ Bind‬ال‪ Value‬من‬
‫‪ 4‬اماكن بتدور فيهم وهما ‪ .1‬الـ ‪ submit‬بتاعت ال‪ form‬ودي اول حاجة بتحصل بيروح يدور علي فورم عندي وبيأخد فاليو ال‪ id‬منها لما بعمل‬
‫‪ .2 submit‬تانى حاجة بيروح يدور فيها لو الفورم مفهاش ‪ id‬او لو معنديش فورم اصال هي بيروح يدور فى ال ‪ sigmant‬بتاعت ال ‪ url‬ال‬
‫‪ pathURL‬اللى عندى ‪ .3‬تالت حاجة لو معنديش سيجمنت بيروح يدورفي ال ‪ queryString‬وبتكون فى ال ‪ url‬برضو ‪ .4‬رابع حاجة لو ملقاش‬
‫ف السجمنت بيروح يدور ف ‪ file‬لو انا عندي مثال ‪ input‬وال ‪ Input‬دا بيأخد ‪ file‬بيروح يدور داخل ال ‪ file‬دا على ‪( id‬مش مستخدم كتير)‪.‬‬

‫دلوقتى هنجرب نخلي يدور فى السيجمنت‪ .‬لو انا قولتله كدا ‪ movies/GetMovie/11‬كدا انا باعتله ال ‪ id‬فى السيجمنت وهيطبعهولى فى الصفحة‬
‫‪public class MoviesController : Controller‬‬
‫{‬
‫)‪public IActionResult GetMovie(int id‬‬
‫;)"}‪=> Content($"movie with id : {id‬‬
‫‪}//type in link to test https://localhost:44302/Movies/GetMovie/11 >>result = movie with id : 11‬‬

‫وكمان ال ‪ parameter‬دا ممكن يأخد مني ‪ param3‬مثال ‪ int,string‬و ‪ emplyee‬بالشكل دا (هعمل كالس ‪employee‬االول) ‪.‬‬
‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 10‬‬
public class employee
{
public int id { get; set; }
public string name { get; set; }
}

public class MoviesController : Controller


{
public IActionResult GetMovie(int id, string name)
=> Content($"movie with id : {id} & movie name is {name}");
} //‫ نكتب اللينك بالشكل دا‬https://localhost:44302/Movies/GetMovie?id=11&name=BlackAdam&employee.name=ahmed

How to install Bootstrap


‫ كلها زي ملفات البوتستراب وملفات ال‬resources ‫ ودا بحط جواه كل الملفات ال‬wwwroot ‫لو انا شغال ب تمبلت فاضية الزم اعمل فولدر اسمه‬
‫ وبروح اقف ع الفولدر اللى عايز انزل فى المكتبة‬. ‫ اللى ممكن استخدمها‬library ‫ بحط في كل ال‬lib ‫ و ال‬images ‫ وال‬js ‫ وملفات ال‬css
‫ وهكتب اسمها‬cdn ‫ وال هنزل الملفات بتاعته وهنا هختار‬cdn ‫ سوا‬provider ‫ وبحدد ال‬rightclick + add + ClientSideLibrary ‫وادوس‬
‫ وبس كدا‬bootstrap.min.css , bootstrap.min.js , bootstrap.bundle.min.js ‫وهختار ال‬

View
right click+add+controller..+MVC ‫ اللى كنت عامله قبل كدا وادوس‬controllers‫ هروح على فولدر ال‬controller ‫لو عايز اضيف‬
view‫ الـ‬create‫ بعد كدا هـ‬.‫ هتالقي نزل معاك‬Controller-Empty

Home ‫ واسمي‬home ‫ وهنا هعمل فولدر لكنترولر ال‬views ‫ بيكون له فولدر داخل فولدر ال‬controller ‫ وكل‬views ‫هعمل فولدر اسمه‬
rightclick on HomeFolder + add+view+razorView + name=Index+unchick on layout + ‫وهضيف جوا الفيو بتاعها‬
. c#‫و‬html ‫و ريزوربيدج دي معناها انه ملف اقدر اكتب بداخله‬ Add

‫ هقوله }{@ وهكتب الكود بتاعى داخل البراكيتس لو الكود اكتر من سطر ولو سطر واحد هحط @قبل الكود‬html ‫ داخل ال‬C# ‫ولو عايز اكتب‬
<body>
@DateTime.Now @*single line Code*@
@{ // Multi Line Code
int x = 4;
}
</body>
. ‫ وبستخدمها وانا برمط ملفات البوتسترب بالصفحة بتاعتى‬wwwroot *@‫~ *@تعود على فولدر‬

‫ وترن وتروت عليه هتالقي البوتستراب مش شغال والسبب‬html ‫وبعد ما تعمل الفيو وتضيف ملف البوتستراب في وتضيف اي حاجة ف صفحة ال‬
. ‫ بالظبط‬app.routing ‫ فوق ال‬configure ‫ داخل فانكشن ال‬app.UseStaticFiles(); .. startup ‫ان الزم تقوله فى ال‬

‫ وهعملهم فيو بالشكل دا‬about,contact ‫ الفانكشن بتاعت كل زرار‬Home ‫وبعد كدا هضيف داخل الكنتروالر اللى اسمه‬

public class HomeController : Controller


{
public IActionResult Index()
{
return View();
}
public IActionResult About()
{
return View();
}
public IActionResult Contact()

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 11


{
return View();
}
}

//‫ودا الفيو بتاع الهوم‬


@{
Layout = null;
}

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<link rel="styleSheet" href="~/lib/bootstrap/css/bootstrap.min.css" /> @*~‫ فولدر على تعود‬wwwroot *@

<title>Index</title>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/Home/About">About</a>
</li>

<li class="nav-item">
<a class="nav-link" href="/Home/Contact">Contact</a>
</li>
</ul>
</div>
</nav>
</body>
</html>
// ‫ودا الفيو الخاص بال ابوت وزيي بالظبط الخاص بالكونتكت‬
@{
Layout = null;
}

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>About</title>
</head>
<body>
<h1>Welcom to About Container</h1>
</body>
</html>
StartUp ‫ ودا ملف ال‬//
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(); // MVC
//services.AddRazorPages(); // Rezor Page
//services.AddControllers(); // Web API

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 12


}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage(); // MiddleWare [pipeline]
}

app.UseStaticFiles();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
endpoints.MapGet("/index", async context =>
{
await context.Response.WriteAsync("Hello From Index!");
});
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id:int?}"
);
});
}
}

‫ ففي الحالة دي بناخدهم وبنحطهم في ملف واحد طيب بيكون فين دا‬head , footer , navbar ‫ دي مشتركين في ال‬views ‫طيب كل ملفات ال‬
razor ‫ واختار‬layout ‫ نكتب في السيرش‬right click + Add+NewItem+‫ وبدوس‬shared ‫ اسمه‬views ‫بعمل فولدر داخل فولدر ال‬
‫ فانا كل اللى هعمله هأخد الحاجات اللى بتتكرر واحطها في وداخل كل‬. ‫ عادي‬layout ‫ ملحوظة ممكن يكون عندى اكتر من‬.. ‫ وادوس اوك‬Layout
‫ وبس كدا‬Layout = "_Layout"; ‫فيو في بروبرتي عندى فوق اخليها كدا‬

‫ اللى عندى ففى الحالة دى انا بروح اعمل ملف اسمه‬views ‫ مكررة فى كل ال‬layout ‫طيب لو الحظنا هنالقي ان البروبرتي بتاعت ال‬
‫ واقوله اوك وهفتحه‬rightclick+add+newitem+search in view start ‫ ودا بعمل داخل فولدر الفيوز‬ViewStart
‫هالقي حططلي البروبرتي بتاعتى الالي اوت ف انا هروح امسح كل البروبرتي الموجودة فى الفيوز وبس كدا‬

@{ // ViewLayout File
Layout = "_Layout";
}

// _Layout File
<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<link rel="styleSheet" href="~/lib/bootstrap/css/bootstrap.min.css" /> @*~‫ فولدر على تعود‬wwwroot *@

<title>@ViewBag.Title</tItle>
</head>

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 13


<body>
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" href="/Home/Index">Home</a>
</li>

<li class="nav-item">
<a class="nav-link" href="/Home/About">About</a>
</li>

<li class="nav-item">
<a class="nav-link" href="/Home/Contact">Contact</a>
</li>
</ul>
</div>
</nav>

<div>
@RenderBody()
</div>

</body>
</html>
// index View ‫واالبوت والكونتكت فيو زيه بالظبط‬

@{ ViewBag.Title = "Home"; }

<div class="mt-5 text-center">


<h1 class="text-success">Welcome to Home Page</h1>
<p>lorem Ispm ...............</p>
</div>

Tag Helpers | HTML Helper


html ‫ للتسهيل الننا مش عارفين‬html tags ‫مايكروسوفت عملتهم لينا بنستخدمهم بدل الـ‬
@*html Helper*@ //‫ودي رخمة شوية ف كتابتها وهي عبارة عن ميزود‬
@Html.ActionLink("Home" , "Index" , "Home" , null , new {@class="nav-link"})

@*Tag Helper*@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers // ‫الزم تعملها امبورت فوق خالص ف بداية الملف تكتب كدا وهتالقي لونهم تحت اتغير‬
<a asp-controller="Home" asp-action="Index" class="nav-link active">Home</a> //‫طالما لونهم موف يبقا شغالين‬
asp-action-id="10" //‫اسم البراميتر‬-‫اكشن‬-‫لو االكشن بتاعتى بيأخد براميتر هستخدم اسب‬

‫طيب لو انا عامل امبورت فى كل الملفات هالقيني مكرر كتير ودا مش افضل حاجة ف هو سهل عليا ومديني اوبشن احطهم كلهم فى ملف واحد بعمله‬
rightClickOnViewsFolder+Add+newItem+Search on Import + ok ‫_ هعمل‬viewImports ‫ واسمي‬views ‫داخل فولدر ال‬

MVC Project Architecture


‫ افضل او‬MVC ‫ اللى هشتغل بي وهنا فى ال‬Architecture pattern ‫لما باجي اشتغل في اي بروجكت او اي حاجة بكون محتاج انى احدد ال‬
‫ بروجكتس واي هما بقا‬3 ‫ او‬3 Tiers ‫ هو‬Arch..Patt.. ‫اقرب‬

‫ ودا بيكون عبارة عن كالس اليبراري ودا مسئول عن التعامل مع الداتابيز وبيكون بداخله‬data Access Layer ‫ اول بروجكت هو الـ‬.1
Migration ‫ الـ‬.3 ‫ او الكالسيس اللى بتتحول لجداول فى الداتابيز‬Models .2 dbContext .1 ‫ حاجات وهما‬3
‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 14
‫‪ .2‬تانى بروجكت هو الـ ‪ Bussiness Logic Layer‬وجواها ب‪ Inplement‬البيزنيس بتاعنا وهو عبارة عن كالس اليبراري برضو‬
‫وبنستخدم جوا ‪two design pattern‬‬
‫‪ .3‬تالت بروجكت هو الـ ‪ Presentation Layer‬ودي ممكن تكون كذا ‪ layer‬ودي ممكن تكون ‪,webapi mvc project‬‬
‫‪ ,mobile ,desktop‬بمعني لو عندى بروجكت كبير ومطلوب كل الحاجات دي ف بضفهم داخل البرزنتيشن الير ‪.‬‬

‫بعد كدا محتاج اربط ال ‪ 3‬بروجكت دول ببعض الداتا اكسيس بتكلم البيزنيس و البيزنيس بيكلم البرزنتيشن فهأخد ريفرنس من الداتا اكسيس احطه عند‬
‫البيزنس وهأخد ريفرنس من البيزنيس احطه عند ال برزينتيشن بالشكل اللى ف الصورة دا ‪ .‬واالركتيتشر دا مش حاجة ثابتة عادى ممكن نزود او نقلل‬

‫السبب انى اعمل ‪ 3‬بروجكت عشان لو انا شغال على بروجكت كبير ‪ mvc,webAPI‬بدال ما اكرر اللى هعمله ف ‪ mvc‬اكرره ف ‪api‬‬

‫وعندي ديزاين بتيرن تانى اسمه ‪ Onion architecture‬ودا بيكون عبارة عن حلقات او دوائر او حلقة بيكون اسمها ‪ domain layer‬ودي بيكون‬
‫جواها ال ‪ models‬او الكالسيس اللى هتتحول ل جداول تانى حلقة او تانى ‪ layer‬واسمها ‪ repository layer‬وبيكون جواها ‪dbcontext‬‬
‫والديزاين باتيرن اللى اسمه ‪ repository‬ودي معناها مخزن او مستودع وبيكون جواها جزء من البيزنيس وتالت حلقة ودي بيكون جواها ال‬
‫‪ service layer‬وبيكون جواها الجزء التانى من البيزنيس ورابع حلقة هي ال ‪. presentation layers‬وممكن يكون في اكتر من حلقة عادى‬

‫هنبدأ نشتغل بال ‪ tiers 3‬وهنكريت البروجكت‬

‫هعمل بروجكت جديد المرة دي هختار التمبلت الجاهزة )‪ ASP.NET Core Wep App (Model-View-Controller‬وهسمي ‪Demo.PL‬‬
‫وهي اختصار ل ‪ presentation Layer‬وهنا عندى هيكون بروجكت ال ‪ MVC‬فقط ‪ .‬بعد كدا هضيف ‪ new project‬وهيكون نوعه ‪Library‬‬
‫وهختار ‪ class Library‬وهسمي ‪ Demo.DAL‬اختصار ل ‪ data access layer‬هيعملهولي وهمسح ملف الكالس اللى هو عمله دا وانا هعمل‬
‫واحد جديد بعدين ‪ .‬تالت حاجة هضيف ‪ new project‬وهيكون نوعه ‪ Library‬وهختار ‪ class Library‬وهسمي ‪ Demo.BLL‬اختصار‬
‫‪ Bussiness Logic Layer‬وبرضو همسح ملف الكالس دا ‪ ..‬بعد كدا هربط البروجكتيس دي ببعض هروح على ال ‪ BLL‬وهقف ع‬
‫‪ dependance‬و ‪ right click+addReference+selectDEMO.DAL‬وبعد كدا هروح على ال ‪ DEMO.PL‬وهقف على‬
‫‪ dependance‬و ‪ rightClick+AddRefer+selectOnDEMO.BLL‬وبس كدا ‪.‬‬

‫ملحوظة ‪ :‬الـ ‪ string‬فى‪ .net 5‬الديفولت بتاعه ‪ not Required‬اما فى ‪ .net 6‬الديفولت بتاعه ‪ Required‬وعشان اخلي ‪ Not‬هعمله ?‪string‬‬
‫او هحط ال داتا انوتيشن ])"‪ [Required(ErrorMessage ="Name is Required‬ودى بتظهر في ال ‪ html‬مع الفورم تلقائيا ‪.‬‬

‫‪Create First New Module|Service Department‬‬


‫‪ .1‬هداخل بروجكت ‪ DAL‬هضيف في ‪ 2‬فولدر لل ‪ models,contexts‬وهضيف فيهم الكالسات بتاعتهم بالشكل دا‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 15‬‬


‫‪// Department Model in models folder in DAL project‬‬
‫بعمله بابليك عشان اقدر اشوفه ف بروجكت اللى هيكون في االنترفيسس ‪public class Department //‬‬
‫{‬
‫} ;‪public int Id { get; set‬‬
‫])"‪[Required(ErrorMessage ="Code is Required‬‬
‫} ;‪public int Code { get; set‬‬
‫} ;‪public string Name { get; set‬‬
‫} ;‪public DateTime DateOfCreation { get; set‬‬

‫}‬

‫‪// in contexts folder add context Class in contexts folder in DAL project‬‬
‫‪public class CompanyContext : DbContext‬‬ ‫بعمله بابليك عشان اقدر اشوفه ف بروجكت اللى هيكون في الريبوستري ‪//‬‬
‫{‬
‫)‪protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder‬‬
‫;‪=> optionsBuilder.UseSqlServer("server=DESKTOP-4EFPBS4\\SQLEXPRESS; database=CompanyMVC‬‬
‫;)";‪Trusted_Connection=true; MultipleActiveResultSets = true‬‬
‫سيتس ريسلت من اكتر جوا نبعت ممكن بتاعنا الريكوست ان معناها ;‪// MultipleActiveResultSets = true‬‬

‫} ;‪public DbSet<Department> Departments { get; set‬‬


‫}‬

‫‪ .2‬بعد كدا داخل بروجكت ‪ BLL‬هعمل في الديزاين بتيرن ‪ repository‬بالطريقة دي هعمل فولدر اسمه ‪ Interfaces‬وفولدر اسمه‬
‫‪ Repositories‬فاللى انا بعمله بروح اعمل انترفيس و ريبو ل اي موديل (كالس|جدول) عندى وهنا هعمل للديبرتمنت فقط واالنترفيس‬
‫بيكون شايل السجنيتشر بتاعت ‪ 5‬حاجات ‪ 5‬ميزود وهما‬
‫‪internal interface IDepartmentRepository‬‬
‫{‬
‫;)(‪IEnumerable<Department> GetAll‬‬
‫;)‪Department Get(int id‬‬
‫;)‪int Add(Department Department‬‬
‫;)‪int Update(Department Department‬‬
‫;)‪int Delete(Department Department‬‬
‫}‬

‫وبروح اعمل كالس ديبرتمنت ريبوستري وهخلي يورث من االنترفيس دا وهخلي ي امبلمنت منه بالشكل دا‬

‫ملحوظة انا عشان اخلي كالس ‪ DepartmentRepository‬يقدر انه يعمل ‪ Add‬فى جدول ال ‪ Department‬محتاج اني اخلي يكلم كالس ال‬
‫‪ dbContext‬النه المسئول عن التعامل مع الداتا بيز ف انا محتاج اني اكريت اوبجكت من ال ‪ dbContext‬وهكريته داخل كالس ال‬
‫‪ DepartmentRepository‬وهخلي برايفت وهخلي ريد اونلي عشان محدش يقدر يعدل عليه وال يشوفه غيره وهعمل كونستراكتور ل‬
‫‪ DepartmentRepository‬وهفتح الكونكشن مع الداتا بيز من خالل الكونستراكتور دا بيروح يسأل ال ‪ CLR‬االول عشان ينشأ االوبجكت النى‬
‫وانا بنفذ ال ‪ Add‬مثال محتاج اني افتح كونكشن مع الداتا بيز عشان هيضيف فيها ففى الوقت دا محتاج انى افتح كونكشن معاها عشان كدا انا انشاءت‬
‫االوبجكت في الكونستراكتور دا وهروح فى ال ‪ startup file‬اخلي ي ‪ allow‬ال ‪ depandency enjection‬بالشكل دا‬
‫;)(>‪services.AddDbContext<CompanyContext‬‬

‫عشان اكريت اوبجكت من ال ‪ DepartmentRepository‬االوبجكت دا بيعتمد علي حقن اوبجكت من كالس ال ‪ dbContext‬ف انا بعمل‬
‫كونستراكتور ومنه بطلب من ال ‪ CLR‬انه يكريتلي اوبجكت من ال ‪ DbContext‬ف ال ‪ CLR‬هيروح يكريت االوبجكت ولما يروح هناك هيالقي‬
‫كونستراكتور انا عاملهوله بالشكل دا‬
‫)‪public CompanyContext(DbContextOptions<CompanyContext> options):base(options‬‬
‫} {‬
‫‪options‬‬ ‫ان الكونستراكتور دا بيعتمد على حقن اوبجكت من كالس اسمه ‪ DbContextOptions‬ودي بنبعتها فى حاجة اسمها‬ ‫ف ال ‪ CLR‬هيالقي‬
‫بنروح نبعتها فى ال ‪ startup‬بقول لل ‪ CLR‬لما تحتاج تكريت اوبجكت من ال ‪ dbContext‬هتحتاج حاجة اسمها اوبشن ف خدها معاك من ال‬
‫‪ startUp‬فهو هيأخدها ويبعتها لل ‪ base‬اللى هو ال ‪ dbContext‬كالس االساسي هيبعتها للكونستراكتور بتاعه وهو عنده فانكشن اسمها‬
‫‪// in Db Context‬‬ ‫‪ OnConfiguring‬بس كدا ففى الطريقة دى انا بعمل كونفيجرينج عنده هو ‪.‬‬
‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 16‬‬
public class CompanyContext : DbContext
{
public CompanyContext(DbContextOptions<CompanyContext> options):base(options)
{ }
public DbSet<Department> Departments { get; set; }
}
// in StartUp file
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// ‫دى انا اللى بعملها‬
services.AddDbContext<CompanyContext>(options =>
{
options.UseSqlServer("server=DESKTOP-4EFPBS4\\SQLEXPRESS; database=CompanyMVC;
Trusted_Connection=true; MultipleActiveResultSets = true;");
});
}
// in DepartmentRepository
internal class DepartmentRepository : IDepartmentRepository
{
private readonly CompanyContext _dbContext;

public DepartmentRepository(CompanyContext dbContext)


{
_dbContext = dbContext;
}
public int Add(Department Department)
{
_dbContext.Departments.Add(Department);
return _dbContext.SaveChanges();
}

public int Delete(Department Department)


{
_dbContext.Departments.Remove(Department);
return _dbContext.SaveChanges();
}

public int Update(Department Department)


{
_dbContext.Departments.Update(Department);
return _dbContext.SaveChanges();
}

public Department Get(int id)


=> _dbContext.Departments.Find(id);

public IEnumerable<Department> GetAll()


=> _dbContext.Departments.ToList();
}

Session 03
‫) ف االفضل انى انقله من مكانه دا عشان بعد كدا بعمل‬startUp file ‫الكونيكشن استرينج مش افضل حاجة انى اضيفه ف الكود بتاعى (الـ‬
‫ ف السيرفر هنا هيتغير ف كل مرة ف انا مش ف كل مرة هعمل فيها دبلوي‬...production ‫ وال‬testing‫ على سيرفر ال‬deploye ‫للبروجكت‬
. ‫ وهضيف فى االستارت اب حاجة بالشكل دا وبس دا‬appsettings.json ‫هروح اغير ف اسم السيرفر اغير ف الكود ف انا هنقله فى ال‬
"ConnectionStrings": {
"defaultConnection": "server=DESKTOP-4EFPBS4\\SQLEXPRESS; database=CompanyMVC;
Trusted_Connection=true; MultipleActiveResultSets = true;"

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 17


} // in StartUp file
services.AddDbContext<CompanyContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("defaultConnection"));
});
‫ بالشكل دا‬Department ‫ علي الـ‬Migration ‫ بعد كدا هعمل خطوة ال‬.3
How to Migration
‫ عشان دا اللى فى ال‬PL ‫ ودي بنزلها فى البروجكت اللى موجود فى الكونيكشن استرينج ودا موجود فى بروجكت‬Tools ‫بنزل الباكيدج اللى اسمها‬
‫ نفسها هتتحط فى‬migration ‫ و الـ‬rightClick+Set as start.. ‫ من خالل‬startUp project ‫ فهخلي ال بروجكت دا هو ال‬appSetting
‫ البروجكت دا‬package manager console ‫ ف هحدد فى ال‬DAL ‫الفولدر الموجود فى‬
startUp ‫ الموجودة فى ال‬Maddle Ware ‫ الـ‬---- ‫ملحوظة‬

‫ تلقائيا‬https ‫ يحولهولي الى‬http ‫دي المسئولة عن ان لو اليوزر كتب اللينك ب‬ app.UseHttpsRedirection(); -

wwwroot ‫ واحد للملف بتاعى والتانى للملفات المربوطة بالبروجكت الموجودة فى‬request 2 ‫ دي بتروح تبعت‬app.UseStaticFiles(); -

‫ عندنا وتمشي في الروت دا والروت عندنا موجود فى الـ‬route ‫ انهى‬match‫ وبتشوفه بيـ‬url ‫دي بتأخد مني الـ‬ app.UseRouting(); -
. app.UseEndpoints ‫ ميدل وير اللى اسمها‬-

Department Controller - Dependency Injection

PL ‫ بقا فهدخل جوا بروجكت ال‬controller ‫ هحتاج اني اعمله‬department‫ احنا كنا جهزنا مودل ال‬.4
‫ تمام كدا وهضيف عنده اتربيوت‬.. rightClickOnFolderController + add +Controller+MVC Controller-Empty‫و‬
‫ و‬DepartmentController ‫ عشان نقدر نكلمه فاصبح ان العالقة بين‬IDepartmentRepository ‫من الـ‬
DepartmentController has a IDepartmentRepository ّ ‫ اذا‬Has a ‫ عالقة‬IDepartmentRepository

// Inheritance : DepartmentController is a Controller

// Aggregation : DepartmentController has a IDepartmentRepository

‫انا قولتله يورث من االنترفيس عشان ميكونش حياته واقفة على الريبوزتري الن بعد كدا وانا بعمل تيستنج هعمل ريبوزتري فمش هاجي هنا اغيره‬

‫ اوبجيكت من ال‬create‫ عشان ا‬depandancy enjiction ‫ وهعمله‬DepartmentController ‫ للـ‬constractor ‫بعد كدا هعمل‬
‫ تسمح لالنجيكشن بالشكل دا‬Allow‫ اعمل سيرفس هناك عشان تـ‬startUp ‫ وهروح في ال‬IdepartmentRepository
public class DepartmentController : Controller
{
private readonly IDepartmentRepository _DepartmentRepository;
public DepartmentController(IDepartmentRepository DepartmentRepository)
{
_DepartmentRepository = DepartmentRepository;
}
public IActionResult Index()
{
var Departments = _DepartmentRepository.GetAll();
return View(Departments);
}
} // in startUp File
services.AddScoped<IDepartmentRepository, DepartmentRepository>();

‫ بتأخد مني اسم الفيو لو‬.2 ‫ مبتأخدش حاجة ودى بترجعلى الفيو لو هو بنفس اسم االكشن بتاعها‬.1 overload 4 ‫ ليها‬View() ‫الفانشكن اللى اسمها‬
‫ بتأخد منى اسم الفيو والموديل‬.4 ‫ وبترجعلي الداتا بتاعته‬Departments ‫ بتأخد مني موديل زي ال‬.3 ‫هو مش بنفس اسم االكشن‬

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 18


return View(); , ret.. View("hamada"); , r... View(Departments); , r... View("hamada" , Departments);

‫ وهختار الجاهز وقوله اوك فقط‬addView ‫ واختار‬Index ‫ على اكشن‬rightClick ‫ هدوس‬DepartmentController ‫ للـ‬view ‫بعد كدا هعمل‬
‫ دي من النوع‬GetAll ‫ ونا عامل ال‬GetAll‫ للمودل بتاعنا وهنا انا بـ‬import ‫وبعد كدا هحتاج انى احدد نوع الداتا اللى هتكون فى الفيو دا فهعمل‬
‫ لموديلز بروجكت الـ‬import ‫@ وهعمل‬model IEnumerable<Department>;‫ فهضفها ف اول الصفحة بالشكل دا‬IEnumerable<Department>
@using DEMO.DAL.Models ‫ عشان يكون جلوبل على كل البروجكت ومقعدش اكرره في كل الفيوز‬ViewImports_ ‫ في ملف ال‬DAL

Department ‫ بتاع الـ‬Index ‫ ودا الـ‬//


@model IEnumerable<Department>;
@{
ViewData["Title"] = "Departments";
}

<h1 class="text-center pb-4">Departments</h1>


<a asp-action="Create" class="btn btn-success mb-4">Create New Department</a>

@if (Model.Count() > 0)


{
<div class="table-responsive">
<table class="table">

<thead>
<tr>
<th scope="col">@Html.DisplayNameFor(d => d.Code)</th>
<th scope="col">@Html.DisplayNameFor(d => d.Name)</th>
<th scope="col">@Html.DisplayNameFor(d => d.DateOfCreation)</th>
<th scope="col">Details</th>
<th scope="col">Update</th>
<th scope="col">Delete</th>
</tr>
</thead>

<tbody>
@foreach (var Department in Model)
{
<tr>
<td>@Department.Code</td>
<td>@Department.Name</td>
<td>@Department.DateOfCreation</td>
<td>
<a asp-controller="Department" asp-action="Details" asp-route-
id="@Department.Id" class="btn btn-warning">
<i class="fas fa-eye"></i> Details
</a>
</td>
<td>
<a asp-controller="Department" asp-action="Details" asp-route-
id="@Department.Id" class="btn btn-warning">
<i class="fa-solid fa-pencil"></i> Update
</a>
</td>
<td>
<a asp-controller="Department" asp-action="Details" asp-route-
id="@Department.Id" class="btn btn-warning">
<i class="fa-solid fa-trash"></i> Delete
</a>
</td>
</tr>

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 19


}
</tbody>
</table>
</div>
}
else
{
<div class="alert alert-warning">
No Department Creation
</div>
}

‫ عليه‬Bind‫ وهعمله فيو له واحدد بداخله الموديل اللى الفيو بيـ‬DepartmentController ‫ هعمله فى الـ‬create ‫بعد كدا محتاج اعمل االكشن‬
[HttpGet]
public IActionResult Create()
{
return View();
}

[HttpPost]
// [ValidateAntiForgeryToken] // ‫بستخدمه عشان مخليش اي تول خارجية تقدر تعدل ومحدش يقدر يعدل غير من االبلكيشن بتاعى فقط‬
public IActionResult Create(Department department)
{
if (ModelState.IsValid) // server side Validation [chick validation]
{
_DepartmentRepository.Add(department);
return RedirectToAction(nameof(Index));
}
return View(department);
} // Create View HTML
@model Department
@{
ViewData["Title"] = "Create";
}

<h1 class="pb-4">Create New Department</h1>

<form asp-action="Create">
<div class="mb-3">
<label asp-for="Code" class="form-label"></label>
<input asp-for="Code" class="form-control" placeholder="123">
<span asp-validation-for="Code" class="text-danger"></span>
</div>

<div class="mb-3">
<label asp-for="Name" class="form-label"></label>
<input asp-for="Name" class="form-control" placeholder="HR">
<span asp-validation-for="Name" class="text-danger"></span>
</div>

<div class="mb-3">
<label asp-for="DateOfCreation" class="form-label"></label>
<input asp-for="DateOfCreation" class="form-control" placeholder="04/10/2023 03:26 PM">
<span asp-validation-for="DateOfCreation" class="text-danger"></span>
</div>

<input type="submit" class="btn btn-primary" value="Submit"/>


<a asp-action="Index" class="btn btn-dark" >Back</a>
</form>

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 20


‫ عليه‬Bind‫ وهعمله فيو له واحدد بداخله الموديل اللى الفيو بيـ‬DepartmentController ‫ هعمله اكشن داخل‬Details ‫بعد كدا محتاج اظبط زرار الـ‬

public IActionResult Details(int? id)


{
if (id is null)
return BadRequest();

var department = _DepartmentRepository.Get(id.Value);

if (department is null)
return NotFound();

return View(department);
} // Create Details HTML
@model Department
@{
ViewData["Title"] = "Details";
}

<h1 class="text-primary">Department Details</h1>

<div class="mb-3">
<label asp-for="Code" class="form-label"></label>
<input asp-for="Code" class="form-control" placeholder="123" readonly />
</div>

<div class="mb-3">
<label asp-for="Name" class="form-label"></label>
<input asp-for="Name" class="form-control" placeholder="HR" readonly />
</div>

<div class="mb-3">
<label asp-for="DateOfCreation" class="form-label"></label>
<input asp-for="DateOfCreation" class="form-control" placeholder="04/10/2023 03:26 PM"
readonly />
</div>

<a asp-action="Update" class="btn btn-primary">Edit</a>


<a asp-action="Index" class="btn btn-dark" >Back</a>

‫ عليه‬Bind‫ وهعمله فيو له واحدد بداخله الموديل اللى الفيو بيـ‬DepartmentController ‫ هعمله اكشن داخل‬Edit ‫بعد كدا محتاج اظبط زرار الـ‬
public IActionResult Edit(int? id)
{
if (id is null)
return BadRequest();

var department = _DepartmentRepository.Get(id.Value);

if (department is null)
return NotFound();

return View(department);
}
[HttpPost]
// [ValidateAntiForgeryToken] // ‫بستخدمه عشان مخليش اي تول خارجية تقدر تعدل ومحدش يقدر يعدل غير من االبلكيشن بتاعى فقط‬
public IActionResult Edit([FromRoute]int id , Department department)
{
if (id != department.Id)
{

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 21


return BadRequest();
}
if (ModelState.IsValid) // server side Validation [chick validation]
{
try
{
_DepartmentRepository.Update(department);
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
// 1. Log Exeption
// 2. Friendly Message

ModelState.AddModelError(string.Empty, ex.Message);
}
}
return View(department);
} // Create Edit HTML
@model Department
@{
ViewData["Title"] = "Edit";
}

<h1 class="text-dark">Edit Department</h1>


k
<form asp-action="Edit" method="post">
<div asp-validation-summary="All"></div> @*List the whole form Errors Messages*@
<div class="mb-3">
<label asp-for="Code" class="form-label"></label>
<input asp-for="Code" class="form-control" placeholder="123">
<span asp-validation-for="Code" class="text-danger"></span>
</div>

<div class="mb-3">
<label asp-for="Name" class="form-label"></label>
<input asp-for="Name" class="form-control" placeholder="HR">
<span asp-validation-for="Name" class="text-danger"></span>
</div>

<div class="mb-3">
<label asp-for="DateOfCreation" class="form-label"></label>
<input asp-for="DateOfCreation" class="form-control" placeholder="04/10/2023 03:26 PM">
<span asp-validation-for="DateOfCreation" class="text-danger"></span>
</div>

<input type="submit" class="btn btn-primary" value="Save" />


<a asp-action="Index" class="btn btn-dark">Back</a>
</form>

‫ملحوظة إلختصار الكود لو عندى اكشن شبه االكشن التانى هخلي يروح يريتيرن الفيو بتاع االكشن المتشابه بدل ما اكرر الكود مثل الديتيلز واالديت‬
public IActionResult Details(int? id , string viewName = "Details" )
{
if (id is null)
return BadRequest();

var department = _DepartmentRepository.Get(id.Value);

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 22


if (department is null)
return NotFound();

return View(department);
}
// Edit Action Code
public IActionResult Edit(int? id)
{
if (id is null)
return BadRequest();

var department = _DepartmentRepository.Get(id.Value);

if (department is null)
return NotFound();

return View(department);
} ‫هنا هنالقي ان نفس الكود بالظبط ف بدل ما اكرر هقوله ريتيرت اكشن الديتيلز بالشكل دا‬

public IActionResult Details(int? id)


{
if (id is null)
return BadRequest();

var department = _DepartmentRepository.Get(id.Value);

if (department is null)
return NotFound();

return View(viewName , department);


}
// Edit Action Code
public IActionResult Edit(int? id)
{
return Details(id , "Edit");
}

‫ عليه‬Bind‫ وهعمله فيو له واحدد بداخله الموديل اللى الفيو بيـ‬DepartmentController ‫ هعمله اكشن داخل‬Delet ‫بعد كدا محتاج اظبط زرار الـ‬

public IActionResult Delete(int? id) // Delete Action Code


{
return Details(id, "Delete");
}
[HttpPost]
public IActionResult Delete([FromRoute] int id, Department department)
{
if (id != department.Id)
{
return BadRequest();
}
try
{
_DepartmentRepository.Delete(department);
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
return View(department);
‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 23
} // Delete Action View Code
@model Department
@{
ViewData["Title"] = "Delete";
}

<h1 class="text-danger">Ary You Sure Delete This Department ? </h1>

<form asp-action="Delete">
<div asp-validation-summary="All"></div>
<div class="mb-3">
<label asp-for="Code" class="form-label"></label>
<input asp-for="Code" class="form-control" placeholder="123" readonly />
</div>

<div class="mb-3">
<label asp-for="Name" class="form-label"></label>
<input asp-for="Name" class="form-control" placeholder="HR" readonly />
</div>

<div class="mb-3">
<label asp-for="DateOfCreation" class="form-label"></label>
<input asp-for="DateOfCreation" class="form-control" placeholder="04/10/2023 03:26 PM"
readonly />
</div>

<input type="submit" class="btn btn-danger" value="Yes" />


<a asp-action="Index" class="btn btn-dark">Cancle</a>
</form>

wwwroot+lib+ ‫ فهفتح فولدر‬create , edit ‫ الخاص بـ‬view ‫ وهنا هستخدمهم مع‬frontend Validation ‫ بعد كدا هشغل الـ‬.1
min ‫ سكريبت هسيب ال‬2 ‫ هسحبه ف الكود هيضفلي‬jquery.validate.js ‫ هسحب ملف‬jquery-validation+dist+
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
‫ فقط‬min ‫ وهسحبه ف الكود وهسيب ال‬jquery-validation-unobtrusive ‫وهسحب ملف تانى من الفولدر اللى اسمه‬
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
‫بس كدا مش هيكون شغال معايا ليه بقا عشان خاطر انا ضفته ف في االتش تي ام ال بتاعت الكريت مثال فهو بياخد الكود اللى ف الصفحة‬
‫ االصلي موجود‬jquery ‫ من فوق وملف ال‬body ‫@ فهو كدا هيضيفه في ال‬RenderBody() ‫دي ويروح يحطه ف فانكشن ال‬
‫تحت خالص في الالياوت والملفات دي الزم تكون تحت ملف الجيكويري االصلي عشان يشتغلو ف الحل اي بقا‬
@section validationScriptSection{
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
} // In _layout file ‫هنضيفه تحت خالص تحت االسكريبتات الموجودة هناك‬
@await RenderSectionAsync("validationScriptSection", required: false)
. ‫وبس كدا هو كدا هيشتغل معايا ع طول بدون ما اعمل اي حاجة تانيه خالص‬
Generic repositry
‫ هعمل ملف انترفيس جديد وبكدا هيكون داخل فولدر االنترفيس‬Generic ‫محتاجين نحسن الكود بتاعنا ويكون دينامك شوية فهنعدل عليه نخلي‬
‫ ملفات واحد جينارك والتانى للموظفين والتالت لالقسام بالشكل دا‬3 ‫بداخله‬

// IGenericRepository file
public interface IGenericRepository<T> where T : class
{
IEnumerable<T> GetAll();
T Get(int id);

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 24


int Add(T item);
int Update(T item);
int Delete(T item);
} // IemployeeRepository file
public interface IEmployeeRepository : IGenericRepository<Employee>
{
} // IDepartmentRepository file
public interface IDepartmentRepository : IGenericRepository<Department>
{

‫ جديدة داخل فولدر الريبو واحد للجينارك والتاني لل ريبو موظفين والتالت للريبو اقسام بالشكل دا‬Repository ‫ ملفات‬3 ‫وهعمل‬

// GenericRepository file
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly CompanyContext _dbContext;

public GenericRepository(CompanyContext dbContext)


{
_dbContext = dbContext;
}
public int Add(T item)
{
_dbContext.Set<T>().Add(item);
return _dbContext.SaveChanges();
}

public int Delete(T item)


{
_dbContext.Set<T>().Remove(item);
return _dbContext.SaveChanges();
}

public int Update(T item)


{
_dbContext.Set<T>().Update(item);
return _dbContext.SaveChanges();
}

public T Get(int id)


=> _dbContext.Set<T>().Find(id);

public IEnumerable<T> GetAll()


=> _dbContext.Set<T>().ToList();
} // EmployeeRepository file
public class EmployeeRepository : GenericRepository<Employee> , IEmployeeRepository
{
private readonly CompanyContext _dbContext; // ‫عملته عشان فى ميزود تحت زيادة عن المشترك هستخدمه فيها‬

public EmployeeRepository(CompanyContext dbContext):base(dbContext) // Ask CLR Creating


object from dbContext
{
_dbContext = dbContext; //‫معملتوش عند الديبرتمنت عشان مش محتاجه الن مفيش هناك ميزود زياد‬
}

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 25


public IQueryable<Employee> GetEmployeesByage(int age)
{
throw new NotImplementedException();
}
} // DepartmentRepository file
public class DepartmentRepository : GenericRepository<Department> , IDepartmentRepository
{
public DepartmentRepository(CompanyContext dbContext) : base(dbContext) // Ask CLR Creating
object from dbContext
{
}
}

Session 04

ViewData VS ViewBag VS TempData


one way ‫ عندنا هنا هو‬Binding ‫ والـ‬View ‫ الى الـ‬Controller ‫ ودا معناه انه ازاي ابعت معلومة من الـ‬Binding ‫هنتكلم عن الـ‬
‫ وهما‬Binding ‫وعندنا طريقتين عشان نعمل‬

: ‫ مثال‬key value per ‫ بيتكون من‬Dictionary object ‫ هو عبارة عن‬: ViewData .1


public IActionResult Index() // in Employee Controller in index method

{
// Binding is One Way Binding at MVC :
// ----------------------------------

// 1. ViewData is a Dictionary Object (introduced in ASP.NET Framework 3.5)


// => It helps us to Transfar the Data from Controller[Action] to View
ViewData["Message"] = "Hellow View Data";

var employees = _employeeRepository.GetAll();


return View(employees);
}
: ‫ مثال‬key value per ‫ بيتكون من‬Dynamic Property ‫ هو عبارة عن‬: ViewBag .2
public IActionResult Index()
{

// 2. ViewBag is a Dynamic Property(introduced in ASP.NET Framework 4.0 Based on dynamic keyword)


// => It helps us to Transfar the Data from Controller[Action] to View
ViewBag.Message = "Hello View Bag";

var employees = _employeeRepository.GetAll();


return View(employees);
} // in index View file
<div class="text-danger">
@ViewData["Message"]
@ViewBag.Message

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 26


</div>

‫ما الفرق ما بينهم وامتا استخدم كل واحدة فيهم‬


// 1. ViewData
// Enforce Type Safety -> Requires Casting [Strongly Type]
string VDataMessage = ViewData["Meessage"] as String;

// 2. ViewBag
// Can't Enforce Type Safety -> Not Requires Casting [Weekly Type]
string VBagMessage = ViewBag.Meessage;

‫بس الفيوداتا اسرع الن نوعها متحدد من االول‬. ‫واالستخدام على حسب االستخدام وعلى حسب انا محتاج اي والموضوع بيرجعلي انا فى االخر‬

request to request ‫ هي عبارة عن داتا مؤقتة بستخدمها عشان ابعت معلومة من اكشن ل اكشن تاني او من‬: TempData .3
Done ‫ وهنطبق على مثال عند الكريت وانا راجع لالندكس اقوله اظهرلي مسدج توحي بانه‬Dectionary Object ‫وهي عبارة عن‬
public IActionResult Create(Employee employee)
{
if (ModelState.IsValid) // server side Validation [chick validation]
{
int count = _employeeRepository.Add(employee);
if(count > 0)
TempData["checkSuccess"] = "Employee is created Successfully";

return RedirectToAction(nameof(Index));
}
return View(employee);
}

Partial View
‫ وبنعمل الـ‬partial ‫هو جزء من الفيو فلو انا عندي جزء من الفيو بيتكرر فى الكود ف اكتر من فيو ف انا باخد الجزء دا لوحده بحطه في ال‬
‫ فهنا انا‬rightClick+add+view+razorView+checkOnPartialView ‫ بدوس‬Shared ‫ دا فى فولدر الـ‬partial view
: ‫ مثال‬partial ‫عندى زراير مكررة فى الموظفين واالقسام ف انا هعملها‬

@model int // in _ButtonsPartialView


<td>
<a asp-action="Details" asp-route-id="@Model" class="btn btn-warning">
<i class="fas fa-eye"></i> Details
</a>
</td>
<td>
<a asp-action="Edit" asp-route-id="@Model" class="btn btn-primary">
<i class="fa-solid fa-pencil"></i> Edit
</a>
</td>
<td>
<a asp-action="Delete" asp-route-id="@Model" class="btn btn-danger">
<i class="fa-solid fa-trash"></i> Delete
</a>
</td> // in index Employee
@foreach (var Employee in Model)

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 27


{
<tr>
<td>@Employee.Name</td>
<td>@Employee.age</td>
<td>@Employee.salary</td>

<partial name="_ButtonsPartialView" model="@Employee.Id" />

</tr>
} // in index Department
@foreach (var Department in Model)
{
<tr>
<td>@Department.Code</td>
<td>@Department.Name</td>
<td>@Department.DateOfCreation</td>

<partial name="_ButtonsPartialView" model="@Department.Id" />

</tr>
}

‫وكمان عندى اسكريبت الفاليديشن اللى انا بضيفه فى الكريت وااليديت هما عندهم بارشل فيو جاهز ممكن استخدمه وانادي عليه وهطبق دا على اي‬
‫حاجة متشابها عندى بالشكل دا‬

@model Department // in CreateEditDepartmentPartialView


<div class="mb-3">
<label asp-for="Code" class="form-label"></label>
<input asp-for="Code" class="form-control" placeholder="123">
<span asp-validation-for="Code" class="text-danger"></span>
</div>

<div class="mb-3">
<label asp-for="Name" class="form-label"></label>
<input asp-for="Name" class="form-control" placeholder="HR">
<span asp-validation-for="Name" class="text-danger"></span>
</div>

<div class="mb-3">
<label asp-for="DateOfCreation" class="form-label"></label>
<input asp-for="DateOfCreation" class="form-control" placeholder="04/10/2023 03:26 PM">
<span asp-validation-for="DateOfCreation" class="text-danger"></span>
</div> // in Create Department view
<form asp-action="Create">

<partial name="DepartmentPartialViews/CreateEditDepartmentPartialView" />

<input type="submit" class="btn btn-primary" value="Submit"/>


<a asp-action="Index" class="btn btn-dark" >Back</a>
</form> // in Edit Department view
<form asp-action="Edit" method="post">
<div asp-validation-summary="All"></div> @*List the whole form Errors Messages*@

<partial name="DepartmentPartialViews/CreateEditDepartmentPartialView" />

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 28


<input type="submit" class="btn btn-primary" value="Save" />
<a asp-action="Index" class="btn btn-dark">Back</a>
</form> // ‫وهكذا مع الديتلز والدليت وهنطبق نفس الكالم مع الموظفين‬

Relationship
‫هعمل ريليشن شيب ما بين الموظفين واالقسام هروح اضيف نافيجشن بروبرتي وان عند الموظفين وميني عند االقسام وبعد كدا هعمل مايجريشن و‬
‫ عشان‬Selectlist ‫هعمل ابديت للداتا بيز وبعد كدا هعرضهم في الجدول بتاعى هروح فى البارشل فيو بتاع الكريت وااليديت وهضيف في‬
‫اختار منها القسم الفالنى وهروح على الكنترولر بتاع الموظفين هخلي يجبلي االقسام في الليست بتاعتى وبعد كدا هحتاج اظهرهم فى الجدول بتاعى‬
‫بعد الحفظ بالشكل دا‬
// Navigational prop [ONE] in Employee Model
public Department Department { get; set; }

// Navigational prop [Many] in Department Model


public ICollection<Employee> Employees { get; set; } = new HashSet<Employee>();

// add SelectList in CreateEditEmployeePartialView file


@{ // ‫عملتها عشان االسب ايتمز بتاخد حاجة من نوع سليكت ليست وعملتها في بداية الصفحة فوق‬
var departments = new SelectList(ViewBag.Departments, "Id", "Name");
}

<div class="mb-3">
<label asp-for="Department" class="form-label"></label>
<select class="form-control" asp-for="DepartmentId" asp-items="@departments">
<option value="@null">--- Select Department ---</option>
</select>
</div>

// to GetAll Departments in EmployeeController


private readonly IEmployeeRepository _employeeRepository;
private readonly IDepartmentRepository _departmentRepository;

public EmployeeController(IEmployeeRepository employeeRepository , IDepartmentRepository


DepartmentRepository)
{
_employeeRepository = employeeRepository;
_departmentRepository = DepartmentRepository;
}
public IActionResult Create()
{
// to get All Departments in selectList
ViewBag.Departments = _departmentRepository.GetAll();
return View();
} // in Index Employee file

<th scope="col">@Html.DisplayNameFor(e => e.Department)</th> // in Head table

<td>@Html.DisplayFor(e => Employee.Department.Name)</td> // in body Table

‫ وهنا‬loading ‫ واعملها‬GetAll ‫بس لحد هنا مش هالقي ظهر معايا اسم القسم في الجدول فانا محتاج اروح في الجينرك ريبو داخل فانكشن‬
‫ وهستخدم مسكن لحين الحل بعدين‬Include ‫ وهستخدم فانكشن‬EgarLoading ‫ ف هعملها‬employee‫ في ال‬one ‫االقسام عالقتها‬
public IEnumerable<T> GetAll()
{
if (typeof(T) == typeof(Employee))
return (IEnumerable <T>) _dbContext.Employees.Include(E => E.Department).ToList();
else

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 29


‫;)(‪return _dbContext.Set<T>().ToList‬‬
‫}‬

‫‪AddSingletone Vs AddScoped vs AddTransient‬‬


‫هنتكلم شوية عن الـ ‪ service life time in depandance enjiction‬وعندى ‪ 3‬اوبشن وهما‬

‫‪ : AddSingletone .1‬معناها ان انا عايز امنع اي حد يـ‪ create‬مالتى اوبجكت من كالس يعنى يكريت اوبجكت واحد بس وهنا‬
‫االوبجكت هيفضل عايش طول ما اليوزر فاتح االبلكيشن ‪.‬‬
‫‪ : AddScoped .2‬معناها لما حد يطلب من الـ ‪ clr‬يـ‪ create‬اوبجكت من كالس هيـ‪ create‬االوبجكت وهيفضل موجود في ال‬
‫‪ heap‬في الميموري طول ما الـ ‪ request‬شغال ولما الـ‪ request‬يخلص االوبجكت دا هيتشال من الميموري ‪.‬‬
‫‪ : AddTransient .3‬معناها لما حد يطلب من الـ ‪ clr‬يـ‪ create‬اوبجكت من كالس هيـ‪ create‬االوبجكت دا وال‪ life time‬بتكون‬
‫‪ per‬االوبيريشن اول ما نخلص االوبيريشن بتاعتنا االوبجكت دا هيتشال من الـ ‪ heap‬ولو احتاجت اوبجكت هيروح يكريت واحد جديد‬

‫طيب امتا استخدم اي حاجة فيهم دا بيكون علي حسب الحاجة يعنى لو انا عايز اكريت اوبجكت يفضل شغال طول ما االبلكيشن مفتوح هستخدم‬
‫سنجلتون اما لو عايزه ‪ per Al Request‬هستخدم سكوب اما لو عايزه ‪ per Al Operation‬هستخدم ترانسينت ‪ ..‬وعلي سبيل المثال مثال‬
‫هستخدم سنجيلتون لما اجي اعمل كاش ودا هنستخدمه فى ال ‪ API‬بس متجيش مثال تعملي ال ‪ dbContext‬سنجيلتون الن لما يجي حدد يكريت‬
‫منه اوبجكت هيفتح كونيكشن مع الداتا بيز وخالص على كدا فهنا نستخدم سكوب النى محتاج ان يكون الكونيكشن بير الريكوست وفي المعظم احنا‬
‫مع البيزنس سيرفس بنخلي كل حاجة عندنا سكوب ‪.‬‬

‫‪Mapping‬‬
‫في ‪ property‬عندى بيكون ليها تمثيل فى الداتا بيز و‪ property‬بيكون ليها تمثيل كـ ‪ frontEnd‬ف انا محتاج افصل مابينهم اعمل كالس للـ‬
‫‪ propery‬الخاصة بالفرونت وهيكون اسمه ‪ EmployeeViewModel‬وببدأ اخد كل البروبرتي الموجودة عندى ف المودل كوبي واحطها ف‬
‫الكالس الجديد وارجع ل كالس المودل ابدء امسح منه الحاجات اللى ملهاش تمثيل عندي ف الداتا بيز او اللى مش بتريندر في الداتا بيز بالشكل دا‬

‫‪// model‬‬
‫‪public class Employee‬‬
‫{‬
‫} ;‪public int Id { get; set‬‬
‫]‪[Required‬‬
‫])"‪[MinLength(2 , ErrorMessage = "MinLength is 2‬‬
‫} ;‪public string Name { get; set‬‬
‫} ;‪public int? age { get; set‬‬
‫} ;‪public decimal salary { get; set‬‬
‫} ;‪public bool isMarred { get; set‬‬
‫} ;‪public int? DepartmentId { get; set‬‬

‫]‪// Navigational prop [ONE‬‬


‫} ;‪public Department Department { get; set‬‬
‫}‬ ‫‪// ViewModel‬‬
‫‪public class EmployeeViewModel‬‬
‫{‬
‫} ;‪public int Id { get; set‬‬
‫])"!‪[Required(ErrorMessage = "Name is Required‬‬
‫])"‪[MinLength(2, ErrorMessage = "MinLength is 2‬‬
‫])"‪[MaxLength(50, ErrorMessage = "MaxLength is 2‬‬
‫} ;‪public string Name { get; set‬‬
‫])‪[Range(22, 100‬‬
‫} ;‪public int? age { get; set‬‬
‫} ;‪public decimal salary { get; set‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 30‬‬


‫} ;‪public bool isMarred { get; set‬‬

‫} ;‪public int? DepartmentId { get; set‬‬


‫;‪public DateTime creationDate { get; set; } = DateTime.Now‬‬

‫]‪// Navigational prop [ONE‬‬


‫} ;‪public Department Department { get; set‬‬
‫}‬

‫بعد كدا بروح بروح امسك كل الفيوز و البارشل فيو اللى عندى بخليهم يكلمو الفيو مودل بدل ما كانو بيكلمو االمبلوي على طول بالشكل دا‬
‫‪@model EmployeeViewModel‬‬

‫وبعد كدا بروح على االمبلوي كنترولر بخلي الميزود اللى عندى تكلم االمبلوي فيو مودل وهيظهرلي ايرور ومعنى االيرور دا هو انى محتاج اعمل‬
‫‪ mapping‬بقا ليهم وعندى طريقة الـ ‪ manual Mapping‬ودا مش افضل حاجة عشان بعملهم ب ايدي وممكن اعمل ‪explicit casting‬‬
‫بس برضو مش افضل حاجة النه مانويل برضو بس بطريقة شيك شوية والحل االمثل انى استخدم باكيدج جاهزة اسمها ‪ auto mapper‬هروح‬
‫انزلها فى بروجكت ال ‪ PL‬من خالل ‪ nugat‬واسيرش علي ‪AutoMapper.Extensions.Microsoft.DependencyInjection‬‬
‫وانزلها واروح اطلب من ال ‪ clr‬انه يكريتلي اوبجكت بيامبلمنت االنترفيس اللى اسمه ‪ Imapper‬ودا بضيفه ف الكونستراكتور بتاع االمبلوي‬
‫كنترول بالشكل دا ‪.‬‬

‫مثال على الكريت ‪public IactionResult Create(EmployeeViewModel employeeVM) //‬‬


‫{‬
‫]‪if (ModelState.IsValid) // server side Validation [chick validation‬‬
‫{‬
‫;)‪var MappedEmp = _mapper.Map<EmployeeViewModel, Employee>(employeeVM‬‬
‫;)‪_employeeRepository.Add(MappedEmp‬‬
‫;))‪return RedirectToAction(nameof(Index‬‬
‫}‬
‫;)‪return View(employeeVM‬‬
‫}‬

‫بعد كدا هكون محتاج اعمل بروفايل للمابر هعمل فولدر اسمه ‪ Mapper profile‬داخل الـ ‪ PL‬واضيف كالس اسمه ‪EmployeeProfile‬‬
‫واخلي يورث من كالس ‪ Profile‬ودا خاص ببكدج اوتومابر وبعد كدا وهضيف جوا الكالس دا فانكشن ‪ CreateMap‬بالشكل دا‬

‫‪public class EmployeeProfile : Profile‬‬


‫{‬
‫)(‪public EmployeeProfile‬‬
‫{‬
‫;)(>‪CreateMap<EmployeeViewModel, Employee‬‬
‫}‬
‫فايل هسمح لل سي ال ار انه يكريت اوبجكت من المابر بالشكل دا ‪} //‬‬ ‫بعد كدا فى االستارت اب‬
‫;)))(‪services.AddAutoMapper(M => M.AddProfile(new EmployeeProfile‬‬

‫وفي حالة ان لو اسم البروبرتي في المودل مختلف عن اسمها فى الفيومودل هحتاج انى ف البروفايل استخدم فانكشن ‪ ForMember‬بالشكل دا‬
‫‪public class EmployeeProfile : Profile‬‬
‫{‬
‫)(‪public EmployeeProfile‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 31‬‬


{
CreateMap<EmployeeViewModel, Employee>()
}
} // ‫ودا االمبلوي كنترولر بعد التعديل عليه‬
public class EmployeeController : Controller
{
private readonly IEmployeeRepository _employeeRepository;
private readonly IDepartmentRepository _departmentRepository;
private readonly IMapper _mapper;

public EmployeeController(IEmployeeRepository employeeRepository , IDepartmentRepository


DepartmentRepository , IMapper Mapper)
{
_employeeRepository = employeeRepository;
_departmentRepository = DepartmentRepository;
_mapper = Mapper;
}

public IActionResult Index()


{
var employees = _employeeRepository.GetAll();

var EmpMapped = _mapper.Map<IEnumerable<Employee> , IEnumerable<EmployeeViewModel>


>(employees);

return View(EmpMapped);
}
[HttpGet]
public IActionResult Create()
{
ViewBag.Departments = _departmentRepository.GetAll();
return View();
}

[HttpPost]
// [ValidateAntiForgeryToken]
public IActionResult Create(EmployeeViewModel employeeVM)
{
if (ModelState.IsValid) // server side Validation [chick validation]
{
var MappedEmp = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_employeeRepository.Add(MappedEmp);
return RedirectToAction(nameof(Index));
}
return View(employeeVM);
}
public IActionResult Details(int? id, string viewName = "Details")
{
if (id is null)
return BadRequest();

var employee = _employeeRepository.Get(id.Value);

if (employee is null)
return NotFound();
var EmpMapped = _mapper.Map<Employee , EmployeeViewModel>(employee);
return View(viewName, EmpMapped);
}

public IActionResult Edit(int? id)

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 32


{
return Details(id, "Edit");
}
[HttpPost]
// [ValidateAntiForgeryToken]
public IActionResult Edit([FromRoute] int id, EmployeeViewModel employeeVM)
{
if (id != employeeVM.Id)
{
return BadRequest();
}
if (ModelState.IsValid) // server side Validation [chick validation]
{
try
{
var EmpMapped = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_employeeRepository.Update(EmpMapped);
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
}
return View(employeeVM);
}

public IActionResult Delete(int? id)


{
return Details(id, "Delete");
}
[HttpPost]
public IActionResult Delete([FromRoute] int id, EmployeeViewModel employeeVM)
{
if (id != employeeVM.Id)
{
return BadRequest();
}
try
{
var EmpMapped = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_employeeRepository.Delete(EmpMapped);
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
return View(employeeVM);
}
} // ‫هنطبق نفس الكالم دا على الديبرتمنت‬

Search
‫ حاليا اول حاجة هروح اعمل االنبوت بتاع السيرش وبعد كدا هشغله بالشكل دا‬Employee ‫هنطبق السيرش على الـ‬

<div class="row justify-content-around"> // in index file


<div>
<a asp-action="Create" class="btn btn-success mb-4">Create New Employee</a>
</div>

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 33


<div>
<form asp-action="Index">
<div>
<div class="input-group mb-3">
<input type="text" name="SearchValue" class="form-control" placeholder="Search By Name">
<button class="type="submit" btn btn-outline-secondary">Search</button>
</div>
</div>
</form>
</div>
</div>

IQueryable<Employee> searchByName(string name); // in interface IEmployeeRepository file

// in Reposatries folder EmployeeRepository file


public IQueryable<Employee> searchByName(string name)
=> _dbContext.Employees.Where(e => e.Name.ToLower().Contains(name.ToLower()));

// in EmployeeController in index Method


public IActionResult Index(string SearchValue)
{
IEnumerable<Employee> employees;
if (string.IsNullOrEmpty(SearchValue))
employees = _employeeRepository.GetAll();

else
employees = _employeeRepository.searchByName(SearchValue);

var EmpMapped = _mapper.Map<IEnumerable<Employee>,


IEnumerable<EmployeeViewModel>>(employees);
return View(EmpMapped);
}
Unit of Work Design Pattern
‫ بدل ما اروح اكلم كل حاجة لوحدها‬unitOfWork ‫ البيزنس بتاعى كله في كالس واحد وهو الـ‬Implement‫بمعني وحدة عمل يعنى ببدأ اا‬
‫ كدا‬signature of every repositry ‫ هعمل له انترفس وهيكون بداخله‬. ‫فالهدف منه هو توحيد البيزنس بتاعنا فى كالس واحد فقط‬
public interface IunitOfWork // ‫هعمله بابلك عشان يقرأ معايا فى الكنترولرز‬
{
public IEmployeeRepository EmployeeRepository { get; set; }
public IDepartmentRepository DepartmentRepository { get; set; }
int Complite();
} // ‫بعد كدا هعمل كالس ريبوزتري له في فولدر الريبوزتري بالشكل دا‬

public class UnitOfWork : IUnitOfWork


{
private readonly CompanyContext _dbContext;

public IEmployeeRepository EmployeeRepository { get ; set ; }


public IDepartmentRepository DepartmentRepository { get; set; }

public UnitOfWork(CompanyContext dbContext)


{
EmployeeRepository = new EmployeeRepository(dbContext);
DepartmentRepository = new DepartmentRepository(dbContext);
_dbContext = dbContext;
}

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 34


public int Complite()
=> _dbContext.SaveChanges();
} // ‫والبروبرتي دي بتمثل ال دي بي سيت كدا يعنى‬ ‫وبكدا بالظبط اكني عملت كالس الـ دي بي كونتكست زي اللى عملته زمان‬

‫بعد كدا هروح على الكنترولرز اللى عندى زي االمبلوي وبدل ما اخلى الكونستركتور يكريت اوبجكت من االمبلوي ريبو والديبرت ريبو هخلي يكريت‬
‫اوبجكت من كالس اليونت اوف ورك بالشكل دا ودي كل التعديالت على االمبلوي كنترولر‬
public class EmployeeController : Controller
{
//private readonly IEmployeeRepository _employeeRepository;
//private readonly IDepartmentRepository _departmentRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;

//public EmployeeController(IEmployeeRepository employeeRepository , IDepartmentRepository


DepartmentRepository , IMapper Mapper)
public EmployeeController(IUnitOfWork UnitOfWork, IMapper Mapper)

{
//_employeeRepository = employeeRepository;
//_departmentRepository = DepartmentRepository;
_unitOfWork = UnitOfWork;
_mapper = Mapper;
}

public IActionResult Index(string SearchValue)


{
IEnumerable<Employee> employees;
if (string.IsNullOrEmpty(SearchValue))
employees = _unitOfWork.EmployeeRepository.GetAll();

else
employees = _unitOfWork.EmployeeRepository.searchByName(SearchValue);

var EmpMapped = _mapper.Map<IEnumerable<Employee>,


IEnumerable<EmployeeViewModel>>(employees);
return View(EmpMapped);
}

[HttpGet]
public IActionResult Create()
{
ViewBag.Departments = _unitOfWork.DepartmentRepository.GetAll();
return View();
}

[HttpPost]
// [ValidateAntiForgeryToken]
public IActionResult Create(EmployeeViewModel employeeVM)
{
if (ModelState.IsValid) // server side Validation [chick validation]
{
var MappedEmp = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_unitOfWork.EmployeeRepository.Add(MappedEmp);
_unitOfWork.Complite();
return RedirectToAction(nameof(Index));
}
return View(employeeVM);
}
public IActionResult Details(int? id, string viewName = "Details")
{

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 35


if (id is null)
return BadRequest();

var employee = _unitOfWork.EmployeeRepository.Get(id.Value);

if (employee is null)
return NotFound();
var EmpMapped = _mapper.Map<Employee , EmployeeViewModel>(employee);
return View(viewName, EmpMapped);
}

public IActionResult Edit(int? id)


{
return Details(id, "Edit");
}
[HttpPost]
// [ValidateAntiForgeryToken]
public IActionResult Edit([FromRoute] int id, EmployeeViewModel employeeVM)
{
if (id != employeeVM.Id)
{
return BadRequest();
}
if (ModelState.IsValid) // server side Validation [chick validation]
{
try
{
var EmpMapped = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_unitOfWork.EmployeeRepository.Update(EmpMapped);
_unitOfWork.Complite();
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
// 1. Log Exeption
// 2. Friendly Message

ModelState.AddModelError(string.Empty, ex.Message);
}
}
return View(employeeVM);
}

public IActionResult Delete(int? id)


{
return Details(id, "Delete");
}
[HttpPost]
public IActionResult Delete([FromRoute] int id, EmployeeViewModel employeeVM)
{
if (id != employeeVM.Id)
{
return BadRequest();
}
try
{
var EmpMapped = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_unitOfWork.EmployeeRepository.Delete(EmpMapped);
_unitOfWork.Complite();
return RedirectToAction(nameof(Index));
}
catch (Exception ex)

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 36


{
ModelState.AddModelError(string.Empty, ex.Message);
}
return View(employeeVM);
}
‫ الموجودة هناك النى عملتها مرة واحدة فى الكومبليت بالشكل دا‬saveChanges()‫وهمسح كل ال‬ GenericRepository ‫بعد كدا هروح على‬
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private protected readonly CompanyContext _dbContext;

public GenericRepository(CompanyContext dbContext)


{
_dbContext = dbContext;
}
public void Add(T item)
=> _dbContext.Set<T>().Add(item);

public void Delete(T item)


=> _dbContext.Set<T>().Remove(item);

public void Update(T item)


=> _dbContext.Set<T>().Update(item);

public T Get(int id)


=> _dbContext.Set<T>().Find(id);

public IEnumerable<T> GetAll()


{
if (typeof(T) == typeof(Employee))
return (IEnumerable <T>) _dbContext.Employees.Include(E => E.Department).ToList();
else
return _dbContext.Set<T>().ToList();
}
}

‫ في االستارت اب وهمسح بتوع االقسام والموظفين الن خالص مبقتش محتاجهم كدا‬Dependancy Injection ‫ الـ‬Allow ‫بعد كدا هروح اا‬
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();

services.AddDbContext<CompanyContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("defaultConnection"));
});

services.AddScoped<IUnitOfWork , UnitOfWork>(); // this is target only y a7med

services.AddAutoMapper(M => M.AddProfile(new EmployeeProfile()));


}

‫طول الفترة اللى فاتت دى احنا مكناش بنقفل الكونيكشن مع الداتا بيز ف محتاجين اننا نقفلها بقا فهروح اخلي االنترفيس بتاع اليونيت اخلي يورث‬
. UnitOfWork ‫ داخل كالس‬dispose ‫ ومن خالله هستخدم فانكشن اسمها‬Idisposable ‫من الكالس اللى اسمه‬

public interface IUnitOfWork : Idisposable ……. // ‫دا التعديل الوحيد في االنترفيس دا وبس كدا‬

public void Dispose() // ‫فقط‬ ‫وهضيف دي بس في كالس اليونيت اوف ورك‬


=> _dbContext.Dispose();

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 37


‫‪Session 05‬‬
‫‪Document Settings‬‬
‫وهو اننا ازاي نتعامل مع الـ ‪ Files‬ومن خالله اخلي اليوزر يضيف فايل او يمسح فايل فاللى انا هعمله هعمل فولدر اسمه ‪ Helpers‬داخل‬
‫بروجكت الـ ‪ PL‬والفولدر دا هيكون بداخله ‪ Helper classes‬وهى ‪ classes‬هتكون فيها ‪ functions‬بتساعدني زي مثال كالس اسمه‬
‫‪ Document settings‬وهيكون ‪ static‬كالس وهيكون جوا شوية فانكشن بتادد الفايل وبتدروب الفايل وهكذا مثال‬

‫عندى طريقتين للتعامل مع ال‪ files‬اول طريقة اني اخزنه فى الداتا بيز بس دا بيحتاج انى وانا بخزنه احوله ل باينري عشان يتخزن ولما استدعي‬
‫هحتاج احوله من باينري الى اصله لو كان صورة مثال والطريقة الثانية انى اخزن على السيرفر(الجهاز بتاعى) واسم الفايل اخزنه فى الداتابيز ‪.‬‬
‫فانا هروح على ‪ wwwroot‬واضيف فيها فولدر اسمه ‪ files‬وابدأ اقسم الفولدر دا الى ‪ images,pdfs,..‬وهكذا و هطبق على الـ ‪images‬‬

‫‪To Upload Files‬‬


‫)‪public static string UploadFiles(IFormFile file, string folderName‬‬
‫{‬
‫‪// 1. Get Located Folder Path‬‬
‫‪string folderPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\Files",‬‬
‫;)‪folderName‬‬

‫‪// 2. Get File Name and Make it UNIQUE‬‬


‫;"}‪string fileName = $"{Guid.NewGuid()}{file.FileName‬‬

‫‪// 3. Get File Path‬‬


‫;)‪string filePath = Path.Combine(folderPath, fileName‬‬

‫]‪// 4. Save File as Streams : [Data per Time‬‬


‫جزء مع جزء مع جزء بيلود الوقت مع فهو واحدة مرة هيتحفظ مش يعنى ‪// Streams‬‬
‫;)‪using var fileSave = new FileStream(filePath, FileMode.Create‬‬
‫مثال الصور بداخله هيكون اللى السيرفر على الموجود الفولدر مع الكونكشن نقفل عشان استخدمنها ‪// using‬‬

‫;)‪file.CopyTo(fileSave‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 38‬‬


return fileName;
}

‫ وبعد كدا هروح على البارشل فيو‬EmployeViewModel‫بعد كدا هروح اضيف فيلد يشيل اسم الصور في كالس الموظفين وهظبطه فى ال‬
‫بتاع الكريت وهزود انبوت جديد‬

public string imageName { get; set; } // in Employee Model Class

public IFormFile Image { get; set; } // in EmployeeViewModel Model Class


public string imageName { get; set; } // ‫زودتها عشان المابينج ميحصلش ايرور ويكون في مشاكل‬

<div class="mb-3"> // in CreateEditepartielView


<label asp-for="Image" class="form-label"></label>
<input asp-for="Image" class="form-control">
</div> // in Create View ‫عشان الفورم تفهم ان هي شايلة فايل‬ ‫منساش اكتب االنكريبت‬
<form asp-action="Create" enctype="multipart/form-data"> // encrypt ‫بقول للفورم انك شايله انبوت بيأخد فايل‬

‫بعد كدا داخل االمبلوي كنترولر هضيف السطر دا عشان اكول الفانكشن اللى عملتها اول حاجة هضيفه داخل الكريت بالشكل اللى تحت دا‬
employeeVM.imageName = DocumentSettings.UploadFiles(employeeVM.Image, "images");

[HttpPost] // ‫ميزود الكريت كاملة‬


public IActionResult Create(EmployeeViewModel employeeVM)
{
if (ModelState.IsValid) // server side Validation [chick validation]
{
employeeVM.imageName = DocumentSettings.UploadFiles(employeeVM.Image, "images");
var MappedEmp = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_unitOfWork.EmployeeRepository.Add(MappedEmp);
_unitOfWork.Complite();
return RedirectToAction(nameof(Index));
}
return View(employeeVM);
}

To Delete Files
‫ودي براحتي لو انا عايز امسح الصورة من على السيرفرر لما اجي امسح الموظف فبروح اعمل فانكشن في كالس الدكيومنت سيتنج‬
public static void DeleteFile(string fileName, string folderName)
{
if (fileName is not null && folderName is not null)
{
string filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\Files",
folderName, fileName);
if (File.Exists(filePath))
File.Delete(filePath);
}

} // in delete method in employee controller ‫هضيف السطر دا وبس كدا‬

if (count > 0)
DocumentSettings.DeleteFile(EmpMapped.imageName, "images");

// ‫ميزود الديليت كاملة‬

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 39


public IActionResult Delete([FromRoute] int id, EmployeeViewModel employeeVM)
{
if (id != employeeVM.Id)
{
return BadRequest();
}
try
{
var EmpMapped = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_unitOfWork.EmployeeRepository.Delete(EmpMapped);
int count = _unitOfWork.Complite();

if (count > 0)
DocumentSettings.DeleteFile(EmpMapped.imageName, "images");

return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
return View(employeeVM);
} // ‫وهروح على البارشل فيو بتاع الدليت هضيف فى انبوت السم الصورة وهخلي مخفي بالشكل دا‬
<input asp-for="imageName" type="hidden" />

Asynchronous
await ‫غير متزامن يعنى تعمل االوبريشن بتاعتك بالالريل مع بعض زي الصورة ولو عايز اقول ل فانكشن او عملية تستنا عملية تانية هقولها‬

. ‫ دا المتزامن يعني الزم الفانكشن االولى او العملية االولي تخلص عشان تدخل فى العملية التانية وهكذا‬Synchronous ‫اما الـ‬

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 40


. ‫ هبدأ باالنترفيسيس وهكمل بالشكل دا هحط الكود هنا كمرجع لينا‬. ‫فانا هعمل ريفاكتور للكود بتاعى كله على مستوي البروجكت‬

public interface IGenericRepository<T> where T : class // 1. IGenericRepository


{
Task<IEnumerable<T>> GetAll();
Task<T> Get(int id);
Task Add(T item); // ‫فقط تاسك فبكتب فويد اوف تاسك اقوله مينفعش فويد بترجعلي لو الفانكشن‬
Void Update(T item); //‫عشان الريموف ملهاش كود اي سينكرونس ف هخليها فويد‬
Void Delete(T item); //‫عشان الريموف ملهاش كود اي سينكرونس ف هخليها فويد‬
} // 2. GenericRepository
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private protected readonly CompanyContext _dbContext;

public GenericRepository(CompanyContext dbContext)


{
_dbContext = dbContext;
}
public async Task Add(T item)
=> await _dbContext.Set<T>().AddAsync(item);

public void Delete(T item)


=> _dbContext.Set<T>().Remove(item);

public void Update(T item)


=> _dbContext.Set<T>().Update(item);

public async Task<T> Get(int id)


=> await _dbContext.Set<T>().FindAsync(id);

public async Task<IEnumerable<T>> GetAll()


{
if (typeof(T) == typeof(Employee))
return (IEnumerable <T>) await _dbContext.Employees.Include(E =>
E.Department).ToListAsync();
else
return _dbContext.Set<T>().ToList();
}
} // 2. IUnitOfWork

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 41


Task<int> Complite(); // this only
} // 3. UnitOfWork
public async Task<int> Complite()
=> await _dbContext.SaveChangesAsync();

// 4. In EmployeeController
public class EmployeeController : Controller
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public EmployeeController(IUnitOfWork UnitOfWork, IMapper Mapper)

{
_unitOfWork = UnitOfWork;
_mapper = Mapper;
}

public async Task<IActionResult> Index(string SearchValue)


{
IEnumerable<Employee> employees;
if (string.IsNullOrEmpty(SearchValue))
employees = await _unitOfWork.EmployeeRepository.GetAll();

else
employees = _unitOfWork.EmployeeRepository.searchByName(SearchValue);

var EmpMapped = _mapper.Map<IEnumerable<Employee>,


IEnumerable<EmployeeViewModel>>(employees);
return View(EmpMapped);
}

[HttpGet]
public async Task<IActionResult> Create()
{
ViewBag.Departments = await _unitOfWork.DepartmentRepository.GetAll();
return View();
}

[HttpPost]
public async Task<IActionResult> Create(EmployeeViewModel employeeVM)
{
if (ModelState.IsValid) // server side Validation [chick validation]
{
employeeVM.imageName = await DocumentSettings.UploadFilesAsync(employeeVM.Image,
"images");
var MappedEmp = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
await _unitOfWork.EmployeeRepository.Add(MappedEmp);
await _unitOfWork.Complite();
return RedirectToAction(nameof(Index));
}
return View(employeeVM);
}
public async Task<IActionResult> Details(int? id, string viewName = "Details")
{
if (id is null)
return BadRequest(); // 400

var employee = await _unitOfWork.EmployeeRepository.Get(id.Value);

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 42


if (employee is null)
return NotFound(); // 404
var EmpMapped = _mapper.Map<Employee , EmployeeViewModel>(employee);
return View(viewName, EmpMapped);
}

public async Task<IActionResult> Edit(int? id)


{
return await Details(id, "Edit");
}
[HttpPost]
public async Task<IActionResult> Edit([FromRoute] int id, EmployeeViewModel employeeVM)
{
if (id != employeeVM.Id)
{
return BadRequest();
}
if (ModelState.IsValid) // server side Validation [chick validation]
{
try
{
var EmpMapped = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_unitOfWork.EmployeeRepository.Update(EmpMapped);
await _unitOfWork.Complite();
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
}
return View(employeeVM);
}

public async Task<IActionResult> Delete(int? id)


{
return await Details(id, "Delete");
}
[HttpPost]
public async Task<IActionResult> Delete([FromRoute] int id, EmployeeViewModel employeeVM)
{
if (id != employeeVM.Id)
{
return BadRequest();
}
try
{
var EmpMapped = _mapper.Map<EmployeeViewModel, Employee>(employeeVM);
_unitOfWork.EmployeeRepository.Delete(EmpMapped);
int count = await _unitOfWork.Complite();

if (count > 0)
DocumentSettings.DeleteFile(EmpMapped.imageName, "images");

return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
return View(employeeVM);
}

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 43


} // ‫هطبق نفس الكالم على الديبرتمنت كنترولر الن االبلكيشن مش هيقوم غير لما اعمله تمام‬

Back-End Security Overview

- Security (Authentication - Authorization)

===========================================

Step 0 - Identification (Registration)

=> Have a Account at Web App ‫يعنى اليوزر يكون له اكونت عندنا فى االبلكيشن‬

Step 1 - Authentication

=> 1. Who Are You? ‫هيعمل > االجابة‬Login (Username(email), Password)

=> 2. Where You Come?‫دا سؤال مش بنسأله بس محتاجين نعرف اجابته‬

- Local ‫يعنى هو عامل اكونت على االبلكيشن نفسه مثال امازون‬

- Active Directory ‫عبارة عن سيرفس زي السيكول سيرفر فمن خاللها اقدر احدد ان اللى هيدخل الزم يكون له يوزر زي ابل المحكمة‬

- External Server "External Login (Facebook, Google and etc..)" ‫الدخول بواسطة حاجة تانيه زي الفيس‬

- Federated Server (Souq -> Amazon) ‫مثال عندى اكونت على امازون وامازون اشترت سوق فبكدا اقدر ادخل ع سوق‬

Step 2 - Authorization

=> What Can I Do?

Roles (Each Group Of Users have a Specified Role)

=============================================

- Security at ASP.NET Core => Using Microsoft Identity Package ‫باكيدج جاهزة بستخدمها عشان اعمل السكيورتي‬

- Identification(Registeration) -> UserManager (IdentityUser)‫بتتكون م مجموعة من السيرفس اولهم دي بتمنج اليوزر‬

1. Create User (Sign Up)

2. Update User

3. Delete User

4. Read User Data

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 44


5. Confirm Account

- Authentication -> SignInManager (IdentityUser)

1. Sign In

2. Sign Out

3. IsSigned

4. Reset Password

5. Two Factor Authentication ‫بيتشك عليك مرتين لما بتدخل على االكونت عشان يتحقق منك‬

6. OTP Authentication ‫دقيقة‬33 ‫زي التحقق بتاع فودافون كاش بيبعتلك كود صالح لمدة‬

7. External Login (Facebook, Google)

- Authorization -> RoleManager(IdentityRole)

1. Create Role

2. Update Role

3. Delete Role

Microsoft Identity Package Microsoft.AspNetCore.Identity.EntityFrameworkCore


‫ وهعمل‬dbContext ‫ وبعد كدا هفتح الـ‬leatest 5.0.17 ‫ من الناجت باكيدج وهنزل‬DAL ‫ داخل بروجكت‬install ‫اول حاجة هعملها‬
‫ بالشكل دا ويورثو من كالسات الباكيدج بس بدل ما انا اكتبهم هروح اورث علي طول من كالس‬Roles‫ لل‬DbSet ‫ لليوزر و‬DbSet
‫ تانيه وهما هيعملهملي بس دول اهمهم وهستخدمهم‬DbSet ‫ وهما موجودين بداخله بدل ما نكتبهم وجوا كذا‬identityDbContext
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;

public class CompanyContext : IdentityDbContext //‫هيكون بالشكل دا انا خدت السطر دا بس بدل ما اخد الكود كله وبعد كدا هعمل مايجريشن‬

Account Controller - Register


‫هنا مش محتاجين نعمل ريبو وال انترفيس (سيرفيسس)الن هنا عندنا سيرفس جاهزة مش محتاج انى اعملها فهبدأ اعمل كنترولر بالشكل دا‬
public class AccountController : Controller
{
#region Register
// /Account/Register
public IActionResult Register()
// ‫فقط الرجيستر بتاع الفيو يرجعلي انه مهمته كل‬
{
return View();
}
#endregion

#region Login
// ‫هضيف فيها بعدين‬
#endregion
} // ‫هروح ادور على تمبلت من اللنت وافضل حاجة من اللينك دا‬https://colorlib.com/wp/free-bootstrap-registration-forms/

‫برجاء الدعاء لعمي‬ Ahmeed Mostafa Page 45


‫بعد كدا هعمل الياوت اشيل فى كود ‪ html‬بدل ما اقعد اكتبه من االول وجديد وكود الفورم اللى بتكرر هاخده كله كوبي واروح اعمل فيو للرجيستر‬
‫واضيفه في وبعد كدا هروح اعمل ‪ RegisterViewModel‬النى مش هظهر كل الفيلدات اللى الباكدج عملتهالى ‪.‬‬

‫وقفت عند الدقيقة ‪ 31:13‬متبقي اخر ‪ 2‬فيديو ‪ +‬اخر سيشن (من اول ال ‪. )register‬‬

‫برجاء الدعاء لعمي‬ ‫‪Ahmeed Mostafa‬‬ ‫‪Page 46‬‬

You might also like