Application Types
إيه الفرق بين الـ Desktop Application والـ Web Application؟ ده سؤال مهم جدًا كبداية عشان نفهم إحنا بنبني إيه بالظبط.
الـ Desktop Application:
- بيبقى نازل ومربوط على جهاز واحد بس للعميل.
- التحديثات فيه مش بتتم بشكل تلقائي، يعني لو عملت نسخة جديدة، لازم تروح لكل جهاز وتعمل تحديث بنفسك.
- بيحتاج إنك تعمله تسطيب على جهاز المستخدم عشان يشتغل.
الـ Web Application:
- التحديثات فيه بتحصل في نفس اللحظة للكل. بمجرد ما ترفع التحديث على السيرفر، كل المستخدمين بيشوفوا النسخة الجديدة فورًا.
- مش بيحتاج أي تسطيب على جهاز العميل، كل اللي هو محتاجه متصفح عادي واتصال بالإنترنت.
How Web Applications Work
عشان الـ Web Application بتاعك يشتغل والناس تشوفه، بيحصله عملية استضافة أو Web hosting على جهاز كمبيوتر بمواصفات خاصة اسمه Web Server. وأنت كعميل، عشان تقدر تطلب الويب سايت ده، مش محتاج غير متصفح.
The Hosting Process
الـ Web Server ده جهاز كمبيوتر شغال طول الوقت بيقدم خدمة صفحات الويب، وبيبقى عليه برنامج مخصص لإدارة العملية دي، وأشهرهم:
- الـ IIS: ده السيرفر الرسمي من مايكروسوفت واختصار لـ Internet Information Services.
- الـ Apache: ده أشهر سيرفر في العالم ومفتوح المصدر.
- الـ Nginx: سيرفر قوي جدًا ومشهور بسرعته العالية في التعامل مع الطلبات.
لما بنخلص كتابة الكود، بنرفع المشروع بتاعنا على استضافة عند شركات زي GoDaddy أو منصات سحابية زي AWS و Azure او حتى انك تأجر سيرفر وترفع عليه.
Request-Response Cycle
العملية دي كلها بتتلخص في دورة بسيطة جدًا:
- أنا كعميل بفتح المتصفح وأكتب الرابط.
- المتصفح بيبعت طلب للسيرفر يقوله أنا عايز الرابط ده.
- السيرفر بياخد الطلب، ينفذه، ويبعتلك الرد في شكل صفحة ويب.
sequenceDiagram participant Client participant Server Client->>Server: HTTP Request (e.g., GET /home) Note over Server: Processes the request, fetches data Server-->>Client: HTTP Response (e.g., HTML page)
Development Types
لو قررت تبني تطبيق ويب، عندك طريقين أساسيين:
-
الـ Monolithic Architecture: هنا بتعمل ويب سايت كامل، الكود بتاع الواجهة والخلفية (زي كود C# والـ HTML) بيكونوا مع بعض في مشروع واحد. الأمثلة على ده زي ASP.NET MVC و PHP Laravel.
-
الـ Service-Oriented Architecture (SOA): لو العميل بتاعك عايز ويب سايت وتطبيق موبايل في نفس الوقت، الأفضل هنا إننا نفصل المشروع لجزئين:
- الـ Backend: بنعمله باستخدام Web API، وده مفهوش شاشات خالص، هو بس بيرجع بيانات غالبًا بصيغة JSON.
- الـ Frontend: ممكن يكون تطبيق ويب باستخدام Angular أو تطبيق موبايل باستخدام Flutter، وكلهم بيكلموا نفس الـ Backend عشان ياخدوا منه البيانات.
The Evolution of Web Development
تطور صفحات الويب مر بـ 3 مراحل مهمة:
- الـ Static Page: دي صفحات عبارة عن HTML و CSS بس، محتواها ثابت مش بيتغير.
- الـ Dynamic Page: هنا بدأنا نستخدم JavaScript عشان نعمل شوية حركات وتفاعلات في الصفحة عند المستخدم.
- الـ Active Pages: دي المرحلة اللي ظهرت فيها الحاجة للتفاعل مع قاعدة البيانات. عشان الـ HTML مبيقدرش يكلم قاعدة البيانات مباشرة، ظهرت لغات برمجة بتشتغل على السيرفر زي C# عشان تقوم بالدور ده.
Deep Dive into MVC
الـ MVC (Model-View-Controller) هو نمط تصميم مشهور جدًا في هندسة البرمجيات، وهو اختصار لـ Model-View-Controller.
- الـ Model: ده الجزء المسؤول عن كل حاجة تخص البيانات والمنطق بتاع الشغل.
- بيمثل الجداول اللي في قاعدة البيانات في شكل كلاسات.
- بيبقى جواه العمليات اللي بتحصل على البيانات دي.
- الـ View: دي الواجهة اللي بيشوفها المستخدم وبيتفاعل معاها.
- الـ Controller: ده العقل المدبر أو الوسيط. هو اللي بيستقبل طلب المستخدم، يروح يكلم الـ Model يجيب البيانات، وبعدين يختار View مناسب يعرض فيه البيانات دي.
MVC Request Lifecycle
graph TD A[User Request] --> B[Controller]; B -- Asks for Data --> C[Model]; C -- Interacts with --> D[(Database)]; D -- Returns Data --> C; C -- Returns Data to --> B; B -- Sends Data to --> E[View]; E -- Renders HTML --> F[User Response];
MVC Advantages
- الـ Separation of Concerns: فصل الكود لثلاث أجزاء بيخليه منظم جدًا وسهل في التعديل والصيانة.
- الـ Clean URLs: الروابط بتبقى سهلة القراءة ومناسبة جدًا لمحركات البحث.
- الـ Razor Engine: دي تقنية بتخليك تكتب كود C# جوه صفحات الـ HTML بمنتهى السهولة.
Creating Your First MVC Project
عشان تبدأ أول مشروع ليك:
- افتح برنامج Visual Studio 2022 واختار Create a new project.
- ابحث عن ASP.NET Core Web App (Model-View-Controller).
- حدد اسم المشروع والمكان اللي هتحفظه فيه.
- في الشاشة اللي بعدها:
- اختار الفريم ورك المناسب (يفضل دايما تختار Long Term Support version).
- شيل علامة الصح من على Configure for HTTPS دلوقتي للتبسيط.
- حط علامة صح على Do not use top-level statements عشان يظهرلك ملف
Program.csبشكل كامل وواضح.
- اضغط Create.
Dissecting an ASP.NET Core MVC Project
من أول هنا مهم تكون فاتح مشروع حقيقي عشان تشوف الكلام ده بعينك وتطبق.
Exploring the MVC Project Structure
أول ما المشروع يفتح، هتلاحظ إن فيه 3 فولدرات أساسية: Models و Controllers و Views.
- الـ Model: حاليًا هتلاقيه فاضي، وده اللي هنحط فيه كلاسات البيانات بتاعتنا.
- الـ Controller: الفولدر ده بيبقى فيه الكلاسات المسؤولة عن توجيه الطلبات.
- الـ View: ده الفولدر اللي فيه صفحات الواجهة، وهتلاحظ إن امتدادها
cshtml(يعني C# HTML) عشان بنستخدم جواها الـ Razor Engine.
Dissecting Project Files and Folders
المشروع فيه شوية ملفات وفولدرات تانية مهمة جدا:
الـ Dependencies: ده فولدر بنحط فيه أي مكتبات أو أدوات المشروع بيعتمد عليها عشان يشتغل.
الـ Properties and launchSettings.json:
جوه فولدر Properties هتلاقي ملف launchSettings.json. الملف ده مسؤول بس عن إعدادات تشغيل المشروع على جهازك وقت التطوير، ومش بيترفع على السيرفر الحقيقي. الملف ده بيحدد إنت هتشغل المشروع إزاي، وبيكون فيه خيارين أساسيين:
- الـ IIS Express: دي نسخة خفيفة من سيرفر IIS بتنزل مع الفيجوال ستوديو.
- الـ Kestrel: ده الويب سيرفر الأساسي بتاع دوت نت، وهو سريع جدًا وبيشتغل على أي نظام تشغيل.
الـ wwwroot Folder: ده المكان المخصص للملفات الثابتة اللي السيرفر بيبعتها للمتصفح زي ما هي، زي ملفات CSS و JavaScript والصور.
الـ appsettings.json File: ده ملف الإعدادات الخاص بالتطبيق نفسه، وبيترفع مع المشروع على السيرفر. بنحط فيه الحاجات اللي ممكن نحتاج نغيرها من غير ما نعدل في الكود، وأشهر حاجة بتتحط فيه هي رابط الاتصال بقاعدة البيانات.
الـ Program.cs File: ده نقطة البداية للمشروع. الكود اللي هنا بيتقسم لجزئين مهمين:
- منطقة الـ Service Configuration: دي بنضيف فيها الخدمات اللي التطبيق هيحتاجها، زي التعامل مع قاعدة البيانات أو رفع الملفات.
- منطقة الـ Middleware Pipeline: دي عبارة عن بوابات تفتيش ورا بعض، أي طلب جاي من بره لازم يعدي عليها بالترتيب عشان يتفتش ويتنظف قبل ما يوصل للكود بتاعنا.
// 1. Service Configuration Area
builder.Services.AddControllersWithViews();
var app = builder.Build();
// 2. Middleware Pipeline Configuration Area
app.UseStaticFiles();
app.UseRouting();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();The Controller in Depth
اللينك في الـ MVC متصمم عشان يشاور على method معينة جوه الـ Controller. الدالة دي بنسميها Action Method.
يعني لو عندك رابط زي ده: http://localhost/home/index
- كلمة home بتعبر عن اسم الـ Controller.
- كلمة index بتعبر عن اسم Method.
Rules for Action Methods
عشان أي Method نعتبرها Action Method ونقدر نوصلها من الرابط، لازم يتوفر فيها شروط:
- لازم تكون public.
- لازم تكون non-static.
- مينفعش تعملها Overload بنفس نوع الطلب (يعني مينفعش اتنين بنفس الاسم بياخدوا GET مثلا).
Action Method Return Types
الدالة دي ممكن ترجع حاجات كتير قوي، وكلهم بيورثوا من حاجة أساسية اسمها IActionResult.
- الـ ContentResult: لو عايز ترجع نص عادي.
- الـ ViewResult: لو عايز ترجع صفحة ويب كاملة.
- الـ JsonResult: لو عايز ترجع بيانات جاهزة تتقرأ عن طريق تطبيق موبايل مثلا.
- الـ NotFoundResult: لو عايز ترجع خطأ 404 إن الصفحة مش موجودة.
Passing Parameters to Actions
بنقدر نبعت بيانات للدالة دي عن طريق الرابط. لو عملنا دالة بتاخد رقم وتشوفه زوجي ولا فردي:
public IActionResult ShowMix(int id)
{
if (id % 2 == 0)
{
// Even number, return a view
return View("View1");
}
else
{
// Odd number, return content
return Content("This is an odd number!");
}
}The View and Razor Engine
الـ View هو المكان اللي بنكتب فيه كود الـ HTML وبندمج معاه كود C# بكل سهولة باستخدام الـ Razor Engine.
- عشان تكتب بلوك كامل من C#، بتستخدم القوسين دول
@{ }. - عشان تطبع قيمة متغير جوه الـ HTML، بتحط علامة
@قبل اسمه. - وتقدر تستخدم جمل الشرط والحلقات التكرارية زي if و for بشكل طبيعي جدًا.
لما الـ Controller بيطلب إنه يعرض View معينة، النظام بيدور عليها في مسارين بالترتيب:
- بيدور في الفولدر الخاص بالـ Controller الحالي.
- لو ملقاهاش، بيدور في فولدر اسمه Shared، وده فولدر بنحط فيه الصفحات المشتركة.
Building a Complete MVC Flow
تعالى نطبق الكلام ده بشكل عملي ونبني مثال بيعرض بيانات طلبة.
1. Building the Model
أول حاجة هنعمل الكلاس اللي بيمثل الطالب جوه فولدر Models.
namespace YourProjectName.Models
{
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
public string Address { get; set; }
}
}طرق تخزين الصور Storing Image:
- تخزين مسار الصورة Path في Database والملف نفسه على السيرفر: دي الطريقة الأسرع والأكثر استخدامًا.
- تخزين الصورة نفسها جوه قاعدة البيانات: بنحولها لأرقام، دي طريقة أبطأ بس بتضمن إن الصورة متتشلش بالغلط.
- استخدام Cloud Storage: زي خدمات أمازون أو مايكروسوفت، ودي الأفضل في المشاريع الكبيرة اللي فيها ملفات كتير.
2. Creating the Repository
بدل ما نكتب كود التعامل مع البيانات جوه الـ Controller مباشرة، الأفضل نفصله في كلاس لوحده. النمط ده اسمه Repository Pattern. ميزته الكبيرة هي الـ Reusability (إنك تقدر تستخدم الكود أكتر من مرة) وإنه بيسهل عليك لو حبيت تغير مصدر البيانات بعدين (من الميموري لقاعدة بيانات حقيقية مثلا).
using System.Collections.Generic;
using System.Linq;
namespace YourProjectName.Models
{
public class StudentBusinessLayer
{
// In-memory database simulation
private List<Student> students;
public StudentBusinessLayer()
{
students = new List<Student>()
{
new Student() { Id = 1, Name = "Ahmed", ImageUrl = "1.png" },
new Student() { Id = 2, Name = "Mohamed", ImageUrl = "2.jpg" }
};
}
public List<Student> GetAllStudents()
{
return students;
}
public Student GetStudentById(int id)
{
// Find student by ID or return null
return students.FirstOrDefault(s => s.Id == id);
}
}
}3. Building the Controller
هنعمل الـ Controller اللي هيستقبل الطلبات ويستخدم الـ Repository عشان يجيب البيانات ويبعتها للـ View.
using Microsoft.AspNetCore.Mvc;
using YourProjectName.Models;
namespace YourProjectName.Controllers
{
public class StudentController : Controller
{
// Get all students (Action Method)
public IActionResult ShowAll()
{
StudentBusinessLayer studentBL = new StudentBusinessLayer();
List<Student> studentListModel = studentBL.GetAllStudents();
return View("ShowAll", studentListModel);
}
// Get single student details (Action Method)
public IActionResult Details(int id)
{
StudentBusinessLayer studentBL = new StudentBusinessLayer();
Student studentModel = studentBL.GetStudentById(id);
if (studentModel == null)
{
return Content("Student not found!");
}
return View("Details", studentModel);
}
}
}4. Building the Views
هنعمل فولدر جوه فولدر Views ونسميه Student، ونعمل جواه صفحتين.
صفحة عرض كل الطلبة (ShowAll.cshtml):
@model List<YourProjectName.Models.Student>
<h2>All Students</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Details</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.Id</td>
<td>@item.Name</td>
<td>
<a href="/Student/Details?id=@item.Id">Show Details</a>
</td>
</tr>
}
</tbody>
</table>صفحة تفاصيل الطالب (Details.cshtml):
@model YourProjectName.Models.Student
<h2>Student Details</h2>
<div>
<h4>ID: @Model.Id</h4>
<h4>Name: @Model.Name</h4>
<img src="~/images/@Model.ImageUrl" style="width: 150px;" />
</div>لو شغلت المشروع ورحت للرابط http://localhost:port/Student/ShowAll، هتلاقي جدول بيعرض بيانات الطلبة وكل طالب جنبه لينك للتفاصيل بتاعته.
Note
Why IActionResult not ViewResult
- ليه إحنا بنخلي نوع الدالة يرجع
IActionResultبدل ما نخليها ترجعViewResultوخلاص طالما هي بتعرض صفحة؟ السبب الأساسي هو المرونة. تخيل معايا دالة تفاصيل الطالب؛ لو الطالب موجود هترجع صفحة (يعنيViewResult)، لكن لو الطالب مش موجود (يعني الـ ID غلط) هترجع رسالة نصية (يعنيContentResult). الـIActionResultهي الكلاس الأب اللي بيشمل كل الأنواع دي، فبيسمحلك ترجع أنواع مختلفة من نفس الدالة بناءً على الشروط بتاعتك.