بعد التعرف على تعريف الـ ASP.NET MVC وبدء مشروع ArabicArchive فيها والتعرف على مفهوم المتحكمات، سننتقل في هذه المقالة لتعلم المفهوم الثاني وهو الـ Views، وحسب التعريف السابق فهي: قوالب يستخدمها موقعك لتوليد واجهات HTML.
بداية سوف نقوم بتعديل المتحكم WelcomeController من أجل استخدام ملفات ال View بحيث نولد أول ملف Html.
هذه المقالة جزء من سلسلة لتعلم أساسيات ASP.NET MVC للمبتدئين:
- المقالة الأولى: أول موقع ويب لك باستخدام ASP.NET MVC
- المقالة الثانية: إضافة متحكمات Controllers لموقع ASP.NET MVC
- المقالة الثالثة: إضافة واجهة View لموقع ASP.NET MVC
- المقالة الرابعة: إضافة Model لموقع ASP.NET MVC
- المقالة الخامسة: إضافة Connection String والعمل مع قواعد البيانات LocalDB
- المقالة السادسة: الوصول إلى البيانات عن طريق المتحكم Controller
- المقالة السابعة: شرح وتجريب تابع التعديل Edit Method
- المقالة الثامنة: إضافة ميزة البحث إلى موقع ASP.NET MVC
- المقالة التاسعة: إضافة حقل جديد لقاعدة البيانات انطلاقاً من كود سي شارب Code First Method
- المقالة العاشرة: إضافة التحقق Validation إلى MVC Model وتطبيق مبدأ DRY
- المقالة الحادية عشر: اختبار وشرح توابع Details و Delete
إن تابع index في المتحكم WelcomeController يعيد سلسلة نصية String حالياً، قم بتغيير تابع index ليعيد View كما هو موضح في الكود التالي:
// GET: Welcome public ActionResult Index() { return View(); }
إن تابع Index الذي كتبناه أصبح من نوع Action Method أي أنه أصبح دالة تقوم باستجابة Respond عندما يأتيها طلب من المتصفحات Browsers، والاستجابة هنا تكون بإعادة واجهة View.
سنقوم الآن بإضافة الـواجهة View التي سيعيدها التابع Index:
اضغط بالزر الأيمن على مجلد Views -> Welcome ثم اضغط Add واختر: (MVC 5 View Page with Layout (Razor
سيظهر مربع نص يطلب إدخال اسم ال View، نكتب Index (ينبغي أن يكون مطابق لأسم التابع الذي سيعيده) ثم نضغط OK
في مربع النصي الجديد سيطلب منك اختيار القالب الافتراضي للواجهة Select a Layout Page، اضغط على استغراض واختر القالب _Layout.cshtml الموجود افتراضياً في مجلد Shared ثم اضغط OK
نلاحظ أن الملف ArabicArchive -> Views – > Welcome -> Index.cshtml قد تمت اضافته
قم بإضافة الكود التالي في ملف Index.cshtml
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>Hello from our View Template!</p>
قم بالضغط بزر الفأرة اليميني على الملف Index.cshtml واختار View in Browser
أو يمكنك أيضا تشغيل المشروع والانتقال الى المتحكم Welcome
http://localhost:xxxx/Welcome
نلاحظ أن التابع Index في المتحكم لا يقوم بالكثير من العمل حيث أنه فقط يعيد الواجهة View، وبما أنا أضفنا الواجهة بإسم مطابق للتابع، في المجلد المناسب فإن ASP.NET MVC بشكل افتراضي ستستخدم الملف Index.cshtml الموجود في المجلد Views -> Welcome
قالب التنسيق الافتراضي Layout
قالب التنسيق Layout هو قالب للواجهات، بحيث نضع فيه التعليمات التي سيتكرر استخدامها والأساسية، كالتعليمات الأساسية في صفحة HTML، وذلك لتجنب التكرار ولتحقيق فعالية أكبر. مع التأكيد على أن نضع تابع في هذا القالب بحيث تقوم الواجهات التي تستخدم القالب باستبدال التابع بمحتواها، أي أينما وضعنا التابع في القالب سيتم استبداله بمحتوى الواجهة.
أولا سنقوم بتغيير رابط اسم التطبيق الذي يظهر في أعلى الصفحة حيث أنه يوضع في مكان واحد في المشروع على الرغم أنه يظهر في كل صفحة في التطبيق
قم بالذهاب الى المجلد /Views/Shared في Solution Explorer وقم بفتح الملف Layout.cshtml_
قم بإيجاد السطر()RenderBody@، إن تابع RenderBody هو التابع الذي حدثتكم عنه.
قم بتغيير محتويات التعليمة <title> ، إلى ” MVC Arabic Archive” ملف التنسيق الكامل موضح بالأسفل:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - MVC Arabic Archive</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("Contact", "Contact", "Home")</li> </ul> @Html.Partial("_LoginPartial") </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - MVC Arabic Archive</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
قم بتشغيل المشروع مع ملاحظة اسم المشروع في شريط التصفح هو MVC Arabic Archive، وبالنقر على رابط About نلاحظ أيضا أن اسم التطبيق في شريط التصفح هو MVC Arabic Archive، ومنه نلاحظ أننا قمنا بعمل التعديل لمرة واحدة في قالب التنسيق وانعكس هذا التعديل على جميع صفحات الموقع.
بالعودة إلى الواجهة التي سبق وحضرناها نجد Views -> Welcome – > Index.cshtml أنه يحتوي على الكود التالي:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Index";
}
وهو تحديد أن هذه الواجهة تستخدم القالب _Layout، وفي حال كنت تريد إضافة واجهة بدون قالب فتكون:
@{
Layout = null;
ViewBag.Title = "Index";
}
لكن في حالتنا سنتركها على حالها.
كيف يمكن تمرير البيانات بين الواجهات Views والقالب Layout ؟
يكون باستخدام المتغير ViewBag حيث يمكننا بسهولة تمرير البارمترات بين الواجهات، ومثالاً على ذلك يمكنكم الانتباه إلى الواجهة التي أضفناها:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>Hello from our View Template!</p>
نلاحظ أنه تم تعريف الـ ViewBag، وتم إعطائها إسم Title وقيمة Index، حيث أن هذا المتغير من نوع Dynamic وتعريفه يكون بالصيغة السابقة، وبإمكاننا تعريف عدد كبير من هذه المتغيرات حسب احتياجنا.
سنقوم بتعديل قيمة Title الموجود في متغير ViewBag إلى: “Book List”
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Book List";
}
<h2>Book List</h2>
<p>Hello from our View Template!</p>
ونلاحظ أيضاً أن قالب التنسيق Views -> Shared -> Layout.cshtml يستخدم المتغير ViewBag أيضاً بنفس الاسم في في القسم Head، وبذلك ستنتقل القيمة من الواجهة المفتوحة إلى القالب.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Arabic Archive Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
وعليه عندما نريد نقل شيئ ما من واجهة إلى القالب، سنستخدم ViewBag، قم بتشغيل المشروع ولاحظ عنوان المتصفح.
ملاحظة: اذا لم تستطع رؤية التغيرات في المتصفح ربما يكون ذلك بسبب تحميل المتصفح نسخة مخزنة في ذاكرة الكاش الخاصة به، قم بالضغط على Ctrl+F5 في المتصفح ليتم لإعادة طلب الموقع مع تجاهل الكاش الحالي.
كيف يمكن تمرير البيانات من المتحكم إلى الـ View؟
قبل أن ننتقل إلى قواعد البيانات والتحدث عن المفهوم الثالث في الـ MVC، سنقوم بمراجعة ماتعلمناه بشكل منطقي وسريع، والتعرف على كيفية تمرير بيانات من المتحكم Controller إلى الـ View.
عندما يقوم المستخدم بطلب عنوان الموقع URL عن طريق مستعرض ويب، فيتم توجيه الطلب إلى المتحكم المختص، وبدوره يحتوي عدة أستجابات، منها مايعيد نص، ومنها مايعيد أنواع أخرى، ومنها مايعيد واجهة View.
المتحكم عندما يعيد View، يقوم أيضاً بتحديد العمليات المنطقية و البيانات التي ستحتويها هذه الواجهة، سواء كانت بيانات ثابتة، أو بيانات مجلوبة من قاعدة البيانات، أي بإمكاننا القول بأن الواجهة View لاتقوم بأي عمليات لها علاقة بمنطق العمل أو التواصل مع قواعد البيانات بشكل مباشر، وبدلاً من ذلك فإنها تعمل فقط مع البيانات التي تقدم لها من قبل المتحكم.
بالعودة إلى مشروعنا فإن التابع Greeting في المتحكم WelcomeController يأخذ بارمتران هما name و numTimes ويعيد القيم بشكل مباشر للمتصفح. بدلاً من ذلك سنقوم بتعديل المتحكم ليعيد View، ونريده هذه المرة أن يمرر قيم البارتمرات إلى الواجهة View.
ونستطيع القيام بذلك عن طريق المتحكم ووضع البارامترات التي تحتاجها ال View في Object من نوع ViewBag بحيث تسطيع الواجهة الوصول لهذا ال Object وعرض قيمه.
الكود الكامل للمتحكم WelcomeController.cs هو كما يلي:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace ArabicArchive.Controllers { public class WelcomeController : Controller { // GET: HelloWorld public ActionResult Index() { return View(); } public ActionResult Greeting(string name, int numTimes = 1) { ViewBag.Message = "Hello " + name; ViewBag.NumTimes = numTimes; return View(); } } }
ViewBag هو عبارة عن object ديناميكي وهذا يعني أننا نستطيع أن نضع أي شيء نريده في هذا الـ object.
قم ببناء المشروع، لتحديث ماقمنا بإضافته، وذلك بالضغط على Ctr + B
و الآن سنقوم بإضافة الـ View قم بالنقر بزر الفأرة اليميني على مجلد Views\Welcome ثم انقر Add ثم انقر (MVC 5 View Page with Layout (Razor
في مربع الحوار Specify Name for Item ادخل Greeting ثم اضغط OK
في مربع الحوار Select a Layout Page نترك التنسيق الافتراضي Layout.cshtml_ كما هو ثم نضغط OK
فنلاحظ أن الملف ArabicArchive\Views\Welcome\Greeting.cshtml قد تمت إضافته.
قم باستبدال الكود الموجود في الملف Greeting.cshtml بالكود الموجود بالأسفل، حيث يقوم هذا الكود بعمل حلقة لطباعة العبارة الموجودة في البارامتر name عدد من المرات حسب البارامتر numTimes.
الكود الكامل للملف Greeting.cshtml:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<ul>
@for (int i = 0; i < ViewBag.numTimes; i++)
{
<li>@ViewBag.name</li>
}
</ul>
شغل المشروع وانتقل الى الرابط
http://localhost:xx/HelloWorld/Greeting?name=Student&numtimes=4
وبهذه العملية فإن البيانات تأخذ من الرابط وتمرر للمتحكم باستخدام فيقوم المتحكم بدوره بتجميع البيانات في ViewBag object ويمرر هذا ال object الى ال view ثم تقوم ال view بعرض البيانات للمستخدم
لاحقاً في هذه السلسلة سنستخدم طرق متقدمة أكثر لتمرير البيانات من المتحكم إلى الView كطريقة الـ View Model.
تغذية راجعة
اتمنى عدم التردد في الاستفسار عن أي مفهوم تم ذكره في هذا التدوينة، وأرجو تجربة إضافة الواجهات Views بشكل فعلي وعدم الاكتفاء بالقراءة لتحقيق أكبر فائدة ممكنة، وكالعادة سأكون سعيد إن شاركتموني تجربتكم وتصويباتكم في حال وجود أخطاء كتابية.
هذه المقالة مستندة إلى سلسلة دروس مايكروسوفت الرسمية للـ ASP.NET MVC، وذلك لترتيب الدروس المناسب واعتقادي بسلاستها وأهمية نقلها إلى العربية بأسلوب مناسب وتجربة تتوافق مع الأدوات المتاحة لنا والمتوفرة في منطقتنا.