تعلم ASP.NET MVC


الدرس: محركات العرض


الصفحة السابقة
M ، V و C ، أن ... أكلنا الكثير منه. آمل ألا يكون هضمها صعبًا جدًا لأنه يستغرق كل طاقتك للتغلب عليها! في الواقع ، ASP.NET MVC هو أكثر بقليل من تطبيق نمط تصميم بسيط. سوف نكتشف في هذا الجزء عناصر أخرى تأتي بشكل طبيعي إلى تطبيقات الويب الخاصة بنا والتي يوفر ASP.NET MVC لها حلًا قويًا وقويًا.
سوف تكتشف الكثير من الأشياء الجميلة التي لا أستطيع أن أقتبسها جميعًا ، حتى لا تعرف أي فصل نبدأ به ، مشلولًا بالرغبة في التعلم. 
 بشكل عشوائي ، القليل من Ajax ... القليل من موقع الجوال ... توقف ، لن أقول أكثر وأتيح لك اكتشاف التفاصيل الدقيقة لمحرك العرض.

محرك العرض التاريخي لـ ASPX


حتى الآن ، لكتابة واجهات العرض ، استخدمنا HTML مع C# ، مسبوقًا بالحرف @ . لذلك استخدمت محرك العرض المسمى Razor  لكتابة واجهات العرض.
محرك العرض هذا حديث نوعًا ما منذ إنشائه في عام 2010. كان الهدف من تنفيذ Razor هو توفير بنية محسنة لكتابة طرق عرض ASP.NET MVC باستخدام بناء جملة يشبه بناء جملة محركات القالب. ربما لا تدرك ذلك ، لأنك بدأت للتو في تعلم ASP.NET MVC 5 مع 9 Visual Studio 201 ، لكنك تغادر بميزة كبيرة.  وهي ان تبدأ تعلم Razor !!
لأنه قبل Razor ، في بداية ASP.NET MVC (2008) ، كان هناك محرك عرض ASPX  .
هذا هو محرك العرض التاريخي الموجود منذ بداية ASP.NET MVC . إن بنية محرك عرض ASPX أقدم حتى لأنها هي الصيغة المستخدمة من قبل الإصدار الأول من ASP.NET WebForms ، والتي يعود تاريخها إلى عام 2002 ... نتعرف عليها بسهولة كبيرة لأنها مليئة >٪ و ٪< تحديد المناطق حيث يمكنك كتابة رمز C# .
حتى إصدار 2012 من Visual Studio ، كان من الممكن اختيار إنشاء طريقة عرض باستخدام محرك عرض ASPX أو محرك عرض Razor ؛ يتم تسليط الضوء على الأخير فيما يتعلق بالآخر. دعنا نقول بشكل أكثر دقة أنه من قبل ، عندما أنشأنا طريقة عرض ، كان لدينا قائمة منسدلة سمحت لنا بالاختيار:
ASP.NET framework
اختيار محرك العرض قبل Visual Studio 2013
ومع ذلك ، منذ Visual Studio 2013 ، لم يعد من الممكن إنشاء طريقة عرض باستخدام محرك عرض ASPX . عندما نضيف طريقة عرض جديدة ، نضيف طريقة عرض Razor مباشرة.

نظرة عامة صغيرة على محرك عرض ASPX


وبصراحة ، هذا ليس أسوأ. هيا ، من أجل المتعة ، أقدم لك نظرة عامة صغيرة على ما يعادل ما تعلمناه في Razor في ASPX .
على سبيل المثال لعرض رسالة بسيطة في HTML ، نقوم باستخدام Razor :

<p>@ViewBag.Message</p>
بينما مع ASPX ، كنا سنفعل:

<p><%:ViewBag.Message %></p>
هنا ، ليس الأمر مخيفًا للغاية ، ولكن إذا أردنا جعل HTML أكثر ثراءً ، فسنحصل عليه في Razor :

<p>Bonjour @ViewBag.Prenom vous avez @ViewBag.Age ans</p>
بينما مع ASPX :

<p>Bonjour <%:ViewBag.Prenom%> vous avez <%:@ViewBag.Age%> ans</p>
لقد بدأت بالفعل تزداد ثقلًا.
لذا تخيل الكثير if   أو foreach ... هنا مع Razor :

<table>
    <tr>
        <th>Nom</th>
        <th>Age</th>
    </tr>
    @{
        int i = 0;
        foreach (HelloWorld.Models.Client client in Model)
        {
            <tr>
            @if (i % 2 == 0)
                {
                    <td style="background-color:gray">@client.Nom</td>
                    <td style="background-color:gray">@client.Age</td>
                }
                else
                {
                    <td style="background-color:darkgray">@client.Nom</td>
                    <td style="background-color:darkgray">@client.Age</td>
                }
            </tr>
            i++;
        }
    }
</table>
ومع ASPX :

<table>
    <tr>
        <th>Nom</th>
        <th>Age</th>
    </tr>
    <% 
        int i = 0;
        foreach (HelloWorld.Models.Client client in Model)
        {
    %>
    <tr>
        <% 
                if (i % 2 == 0)
                {
        %>
        <td style="background-color: gray"><%: client.Nom%></td>
        <td style="background-color: gray"><%: client.Age%></td>
        <%      }   
                else
                {
        %>
        <td style="background-color: darkgray"><%: client.Nom%></td>
        <td style="background-color: darkgray"><%: client.Age%></td>
        <%      }
        %>
    </tr>
    <% 
            i++;
        }
    %>
</table>
ومرة ​​أخرى ، تشك في أنه بمجرد أن نضيف نموذجًا صغيرًا مع بعض المساعدين والتحقق من الصحة ، فسوف تصبح الفوضى بسرعة!

لماذا محرك عرض جديد؟


لقد أدركت جيدًا بقراءة الفقرة السابقة ، فإن محرك عرض ASPX به عيب كبير. إذا بدأنا في تقديم واجهات العرض معقدة إلى حد ما ، فإنها تصبح غير قابلة للقراءة على الفور. هذا واضح بشكل خاص مع مثال الجدول الذي قبله مباشرة وله لون مختلف لكل سطر.

لقد بدأنا بالفعل في الحصول على الكثير من >٪ و٪< ، ناهيك عن المسافة البادئة. نفقد على الفور قابلية القراءة ... حسنًا ، يمكننا أن نفهم ، ولكن أضف القليل إذا كان ذلك سيعرض هذا الجدول أو رسمًا بيانيًا اعتمادًا على اختيار المستخدم ويصبح غير قابل للقراءة تمامًا.
هذه واحدة من الشكاوى الكبيرة التي تم تقديمها إلى ASP.NET MVC مع هذا الشعور بالعودة إلى ASP (قبل ASP.NET! ) أو حتى PHP القديم. هذا هو سبب ولادة Razor . الغرض منه هو جعل من الممكن كتابة طرق العرض بأكثر طريقة سلسة ممكنة دون وجود انطباع عن كتابة HTML و C# . تكون الانتقالات طبيعية قدر الإمكان ، بمجرد أن ترغب في كتابة كود ، عليك فقط استخدام @ وبعد ذلك كل شيء. يتم عمل كل شيء حتى يكون لدى المطور انطباعًا بالكتابة بلغة واحدة.

لذلك من الطبيعي جدًا أن يتم استخدام Razor اليوم بشكل أساسي من قبل الجميع وأن محرك عرض ASPX يتم التخلي عنه أكثر فأكثر. حتى أنك ترى أنه لم يعد من الممكن إنشاء عرض ASPX باستخدام Visual Studio 2013 . ولكن يمكن لمحبي ASPX الاطمئنان ، والتوافق مضمون ، وهو أمر ضروري عند ترحيل موقع الويب. ولكن لا يزال يفكر في Razor ... حاول مرة واحدة ، تم اعتماده. 
لا حاجة للتفكير في شيء معقد ، عليك كتابة واجهات العرض دون التفكير في وجود HTML و Razor ... 

بعض تفاصيل Razor


بشكل عام ، Razor ذكي بما يكفي للقيام بكل ما تريد. هناك بالطبع خفايا بسبب خفة النحو. على سبيل المثال ، لعرض اسم مطعم ، رأينا أنه يمكننا القيام بما يلي:

<table>
    <tr>
        <th>Nom</th>
        <th>Téléphone</th>
    </tr>
    @foreach (var resto in Model)
    {
        <tr>
            <td>@resto.Nom</td>
            <td>@resto.Telephone</td>
        </tr>
    }
</table>
باستخدام الصيغة @resto.Nom ، يستنتج Razor أننا نريد عرض خاصية الاسم لكائن المطعم ؛ بفضل النقطة ، كما سنفعل في C# . ولكن ماذا لو أردنا عرض نقطة بعد اسم المطعم مباشرة ، بحيث يكون لدينا شيء مثل: « Le nom du restaurant est Resto Pinière. » يكفي أن تكتب:

<td>Le nom est : @resto.Nom.</td>
لا مشكلة. هنا ، فهم Razor بشكل طبيعي تمامًا أن نقطة النهاية لا تُستخدم للوصول إلى خاصية لأنه خلفها علامة HTML بينما يتم استخدام النقطة الأولى للوصول إلى خاصية المطعم.
من ناحية أخرى ، إذا اتبعنا على الفور بالحرف ، بهذه الطريقة:

<td>Le nom est : @resto.Nom.Voilà !</td>
لدينا مشكلة لأنها Voilà  ليست خاصية Nom  . حسنًا ، في الأوقات العادية لم نكن لنفعل ذلك أبدًا لأن لغتنا الجميلة تتطلب وضع مسافة بعد نقطة . ولكن لأسباب X ، يمكننا العثور على شيء مثل هذا. في هذه الحالة ، يمكننا تأطير التعبير بين قوسين:

<td>Le nom est : @(resto.Nom).Voilà !</td>
لحل المشكلة.
وبالمثل ، يكتشف Razor بعض التعبيرات المحددة. حالة البريد الإلكتروني على سبيل المثال ، وجود @ في المنتصف. لا شيء يجب أن يكون مميزًا ، يمكننا أن نكتب:

<p>Envoyez-moi un mail sur mail@domaine.com</p>
هنا ، يفهم Razor أنه عنوان بريد إلكتروني وليس كائن مجال حيث نريد عرض خاصية com ... ! 
بالإضافة إلى ذلك ، إذا أردنا فقط عرض @ ، فسوف نضطر إلى مضاعفته:

<p>Ça ne marche pas !!! @@#!{?@@# !</p>
الذي سيعرض:
أنها لا تعمل !!! @#!{?@# !
بشكل عام ، Razor قوية جدًا وستتمكن من اكتشاف ما تريد القيام به. إذا لم يكن الأمر كذلك ، فأنت بين قوسين و @ مزدوج.
من ناحية أخرى ، غالبًا ما تكتشف Razor الانتقال بين بناء الجملة و HTML بفضل علامات HTML . لذلك ، هذا صحيح تمامًا:

    @if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    <div>C'est le week-end</div>
}
else
{
    <div>C'est la semaine</div>
}
كنت أعتقد أن تكون قادرة على تجنب اثنين div من نقلهم div من if ، من شأنه أن:

<div>
@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    C'est le week-end
}
else
{
    C'est la semaine
}
</div>
باستثناء أن هناك ، لم يعد يعمل. بالطبع ، يعتقد Razor أنه C# ... وأن C# غير صالح تمامًا. 
لإصلاح ذلك ، هناك حلان. الأول هو استخدام العلامة الخاصة <text>   لإخبار Razor أننا نريد عرض النص:

<div>
@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    <text>C'est le week-end</text>
}
else
{
    <text>C'est la semaine</text>
}
</div>
هذه العلامة خاصة ، ولا يتم عرضها في HTML النهائي (لأنها ليست علامة حقيقية) ، وسيكون لدينا:

<div>
C’est le week-end
</div>
الحل الآخر هو بادئة النص بـ @: للحصول على:

<div>
@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    @:C'est le week-end
}
else
{
    @:C'est la semaine
}
</div>
لمعلوماتك ، للحصول على نفس الشيء مع محرك عرض ASPX ، كنا سنفعل:

<div>
    <% if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
        {
    %>
    C'est le week-end
    <%}
        else
        {
    %>
    C'est la semaine
    <%
        } %>
</div>
عيني. 
لقد رأيتها بسرعة في فصل التحقق من الصحة ، لكنني لم أناقشها رسميًا بعد. من السهل جدًا كتابة التعليقات بطريقة عرض Razor . نستخدم @ * لبدء تعليق و * @ لإنهائه:
لذا ، للتعليق على الجزء السابق من الكود ، يمكننا القيام بما يلي:

@*<div>
@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    @:C'est le week-end
}
else
{
    @:C'est la semaine
}
</div>*@
لاحظ أنه مع محرك عرض ASPX ، لسنا بعيدين:

<%--    <div>
        <% if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
           {
        %>
        C'est le week-end
        <%}
           else
           {
        %>
        C'est la semaine
        <%
           } %>
    </div>--%>

التخطيطات layout


حتى الآن ، كانت واجهات العرض مسؤولة عن التعامل مع جميع HTML التي تظهر في المتصفح ، والعلامة  ، والعلامة  ، وما إلى ذلك. لحسن الحظ ، كانت وجهات نظرنا حتى الآن خفيفة نسبيًا من حيث محتوى HTML ، وذلك لتبسيط تعلمنا قدر الإمكان وعدم ازدحام الكثير من الأشياء. ولكن نادرا ما يكون تطبيق الويب. غالبًا ما يكون لديك في أعلى عنوان الصفحة ، شعار ، لافتة ، والتي تتكرر في جميع الصفحات. وبالمثل ، غالبًا ما يكون لديك قائمة للوصول إلى العناصر المختلفة للموقع. نجد عادةً تذييلًا أيضًا يحتوي على إشعارات قانونية وحقوق الطبع والنشر ومعلومات الاتصال وما إلى ذلك.
باختصار ، هناك العديد من الأشياء التي تكرر نفسها على جميع صفحات الموقع. بعضها لا يختلف ، مثل الشعار أو البانر ، أو حتى حقوق النشر. قد يختلف بعضها قليلاً ، مثل القائمة التي غالباً ما تبرز عنصر القائمة الذي نحن فيه.
أسألك:
هل نحن مجانين بما يكفي لتكرار كل هذه العناصر يدويًا من خلال جميع واجهات العرض؟
أؤكد لكم على الفور ، الجواب لا!
حسنًا ، يمكنك نسخه ولصقه ، ولكن إذا اضطررت إلى تغيير شيء ما ، فيجب علي تغييره في كل مكان ... ناهيك عن خطر الخطأ والدافع المضاد الذي يخلقه هذا.
سوف تكون مجنونا ، نعم ... ولكن فقط مجنون بالفرح ، لملاحظة أن ASP.NET MVC لا يتركنا في حالة من الذعر ويقدم لنا مفهومًا لطيفًا للغاية يسمى Layout ، والذي يمكننا ترجمته من خلال "التخطيط" ، الذي لن نقوم به. 
إذا كنت قد قمت بالفعل بتنفيذ بعض نماذج ASP.NET WebForms ، فمن المحتمل أنك تعرف الصفحات الرئيسية. حسنًا ، التخطيطات ، إنه نفس المبدأ ولكن نسخة Razor .
خذ على سبيل المثال موقعًا أحاول فيه التأكد من تكرار المحتوى بين الصفحات. سنأخذ كمثال موقع تعليمي خاص بي ، جميل جدًا لدرجة أنك ستحسد مهاراتي في التلوين واختيار الألوان:
ASP.NET framework
تخطيطات ASP.NET MVC
يجعلك تريده أليس كذلك ؟ 
وكان الهدف هو تحديد المناطق وترسيمها بوضوح. فيما يلي محتوى عرض index الخاص بي:

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <style type="text/css">
            #entete, #menu, #contenu, #footer {
                padding: 1px 0;
            }
    
            #entete {
                background-color: lightcoral;
                text-align: center;
                background: #FF9900 url("/Content/Images/supertuto.png") 5px center no-repeat;
                background-size: 100px;
            }
    
            #main {
                margin: auto;
            }
    
            #menu {
                float: left;
                width: 240px;
                background-color: lightsalmon;
            }
    
            #contenu {
                margin-left: 245px;
                background-color: lightblue;
            }
    
            #footer {
                background-color: lightgreen;
                text-align: center;
                clear: both;
            }
    
            .titre {
                text-align: center;
            }
        </style>
    </head>
    <body>
        <div id="entete">
            <h1>Bienvenue sur Super tuto</h1>
        </div>
    
        <div id="main">
            <div id="menu">
                <ul>
                    <li>@Html.ActionLink("Accueil", "Index")</li>
                    <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
                    <li>@Html.ActionLink("Forum", "Forum")</li>
                </ul>
            </div>
    
            <div id="contenu">
                <h3 class="titre">Accueil du site de tutoriels</h3>
                <p class="contenu">Ici c'est la page d'accueil avec les news du site, etc.</p>
            </div>
        </div>
    
        <div id="footer">
            © @DateTime.Now.Year - Super site de tutoriels, contactez moi sur monmail@supersitetutoriels.com
        </div>
    </body>
    </html>
    
ستفهم أنني سأحرص على الاحتفاظ بالمخطط بالكامل وأن منطقة الضوء الأزرق فقط هي التي ستتغير. سيأخذ هذا المحتوى Accueil، ثم محتوى قائمة البرامج التعليمية ، ثم محتوى المنتدى ، اعتمادًا على طريقة العرض التي نعرضها.
أول شيء يمكننا القيام به لتفتيح نسختي ولصقها قليلاً هو وضع كل النمط في ملف CSS منفصل. لذلك قمت بإنشاء ملف supertuto.css بكل CSS هذا في دليل المحتوى ويمكنني حذف علامة النمط الخاصة بي لاستبدالها بـ:

    <link type="text/css" rel="stylesheet" href="~/Content/supertuto.css" />
    
من الممارسات الشائعة وضع CSS والصور في دليل فرعي للمحتوى.
الآن دعونا نجري تغييرات على طريقة عرض Index . ليست هي التي يجب أن تحمل المحتوى الذي لا يتغير. سنفصل هذا النموذج عن بعضها البعض ، وسوف يرثه عرض Index ببساطة. أولاً ، قم بإنشاء مجلد مشترك تحت مجلد المشاهدات وانقر بزر الماوس الأيمن على المجلد المشترك ؛ ثم أضف صفحة تخطيط MVC5 (Razor) ، والتي يمكنك استدعاء LayoutDuSite.cshtml :
ASP.NET framework
أضف صفحة تخطيط
ينشئ Visual Studio المحتوى التالي لنا:

    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>@ViewBag.Title</title>
    </head>
    <body>
        <div>
            @RenderBody()
        </div>
    </body>
    </html>
    
بدأنا نشعر بالمبدأ العام. سوف يكون العنوان ديناميكي من خلال الخاصية Title  لل ViewBag  . وينطبق الشيء نفسه على بقية HTML التي سيتم تغذيته بالطريقة RenderBody  .
سنقوم الآن بتعديل هذا التخطيط لوضع بعض HTML الذي أنشأناه مسبقًا:

    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>@ViewBag.Title</title>
        <link type="text/css" rel="stylesheet" href="~/Content/supertuto.css" />
    </head>
    <body>
        <div id="entete">
            <h1>Bienvenue sur Super tuto</h1>
        </div>
    
        <div id="main">
            <div id="menu">
                <ul>
                    <li>@Html.ActionLink("Accueil", "Index")</li>
                    <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
                    <li>@Html.ActionLink("Forum", "Forum")</li>
                </ul>
            </div>
    
            <div id="contenu">
                @RenderBody()
            </div>
        </div>
    
        <div id="footer">
            © @DateTime.Now.Year - Super site de tutoriels, contactez moi sur monmail@supersitetutoriels.com
        </div>
    </body>
    </html>
    
لا ألمس علامة <title> التي يجب أن تظل ديناميكية وأرى أين أدرجت الطريقة RenderBody()   : بدلاً من المحتوى الذي حجزته للعرض Accueil .
الآن ، علي فقط تعديل عرض Index لحذف كل شيء ووضع هذا فقط:

@{
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
    ViewBag.Title = "Accueil";
}

<h3 class="titre">Accueil du site de tutoriels</h3>
<p class="contenu">Ici c'est la page d'accueil avec les news du site, etc.</p>
هذا الرأي فجأة أكثر إيجازا. لا يوجد سوى القليل من C# والعلامات التي أريد عرضها فقط في المنطقة المخصصة لها.
يتكون C# من تهيئة الخاصية WebPageBase.Layout   المستخدمة لتحديد مسار صفحة التخطيط.
يكفي هنا للإشارة إلى مسار الصفحة التي أنشأناها للتو. وبالمثل ، فهو المكان المثالي للإشارة إلى عنوان الصفحة التي لا تتحرك أبدًا. إذا كان العنوان أكثر ديناميكية قليلاً ، فقد يكون من الحكمة أن تهيئه في وحدة التحكم ، ولكن هنا نظهر بوضوح نية الصفحة ونستخدم ما ViewBag   يسمح لنا بتضمين محتوى ديناميكي في التخطيط.
لا تنس أن تضيف وحدة التحكم والإجراءات التي تتوافق معها إذا كنت ترغب في اختبار الموقع.
بالطبع ، من أجل عرض List.cshtml الخاص بنا ، سأستخدم نفس المبدأ بالضبط. لذا دعونا ننشئ هذا العرض. من الممكن اختيار التنسيق الذي ستستخدمه طريقة العرض الخاصة بنا بشكل مباشر بفضل المنطقة المنصوص عليها في نافذة إضافة طريقة عرض:
ASP.NET framework
إضافة طريقة عرض مع تخطيط
لذا يقوم Visual Studio بإنشاء عرض لي:

@{
    ViewBag.Title = "Liste";
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
}

< ;h2> ;Liste< ;/h2> ;
وعلي فقط أن أضع ما أريد فيه. مثلا :

@model  List<SuperTuto.Models.Tuto>
@{
    ViewBag.Title = "Liste";
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
}
<h3 class="titre">
    Liste des tutoriels
</h3>
<table>
    <tr>
        <th>Tutoriel</th>
        <th>Lien</th>
    </tr>
    @foreach (var tutoriel in Model)
    {
        <tr>
            <td>@tutoriel.Titre</td>
            <td>@Html.ActionLink(tutoriel.Lien, "AfficheTutoriel", new { id = tutoriel.Id })</td>
        </tr>
    }
</table>
لقد فهمت المبدأ ، عندما أتنقل في عرض قائمة البرامج التعليمية ، سأستفيد تلقائيًا من تخطيط التخطيط الخاص بي. كل شيء يعمل كما كان من قبل. إعلان النموذج واستخدامه ، إلخ.
دعنا نضيف واجهة عرض أخيرة للمنتدى:

@{
    ViewBag.Title = "Forum";
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
}

<h3>En construction...</h3>
هذا أمر جيد ، لقد قللنا بشكل كبير من كود العرض مع التأكد من أنهم جميعًا يستفيدون من نفس التخطيط. لكن .... في كل عرض ، نحن ملزمون بالإشارة إلى التخطيط الذي نرغب في استخدامه. صحيح أن هناك سطر واحد فقط وأنه ليس كثيرًا ، ولكنه فائض إلى حد ما. بشكل عام ، من الشائع أن يكون لديك تخطيط واحد لنفس الموقع وفجأة ، نحن ملزمون بإدخاله في جميع الصفحات.
لحسن الحظ ، يمكننا تبسيط الأشياء بملف جديد يتم تشغيله قبل جميع طرق العرض. يسمى هذا الملف الخاص _ViewStart.cshtml . يجب عليك وضعه في جذر مجلد views . وهذا ليس كل شيء!  يمكنك أيضًا إنشاء العديد منها ووضعها في أدلة مختلفة بحيث تنطبق كل واحدة على جميع طرق العرض الموجودة في هذا المجلد (وفي جميع المجلدات الفرعية بشكل متكرر).
لذا دعنا ننشئ هذا الملف ونضع المحتوى التالي فيه:

@{
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
}
لذا ، سنتمكن ببساطة من حذف هذا السطر من جميع طرق العرض . بفضل _ViewStart ، سيستفيد كل عرض من هذا التخطيط. عملي جدا أليس كذلك؟
ملاحظة: إذا كان العرض الخاص بك في دليل حيث يطبق ViewStart الذي يضع تخطيطًا لا تحتاجه ، فيمكنك دائمًا إعادة تعريف الخاصية Layout  في رأس العرض وتعيينها null  :

@{
    Layout = null;
    ViewBag.Title = "Test";
}

<h3>Test...</h3>
كل شيء على ما يرام وجيد ، ولكننا لم نقطع سوى نصف الطريق ... قمنا بتسوية حالة جسد المنظر RenderBody()  ، ولكن الباقي؟

الأقسام sections


بالنسبة للباقي ، يتيح لنا ASP.NET MVC تحديد الأقسام المسماة. بدلاً من الاتصال RenderBody  ، سيكون من الضروري استدعاء الطريقة RenderSection   وتزويدها باسم القسم وما إذا كانت إلزامية أم لا. دعونا ننتهز الفرصة لتعديل قائمتنا قليلاً من أجل تسليط الضوء على عنصر القائمة الذي نزوره. على سبيل المثال ، اخترت تمييز المطّة بتغيير لونها:
ASP.NET framework
تحسين المطّة المختارة
لهذا ، أضفت ببساطة CSS التالية:

.selectionne {
    color:red
}
وقمت بتعديل تصميمي ليكون:

<div id="menu">
    <ul>
        <li class="selectionne">@Html.ActionLink("Accueil", "Index")</li>
        <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
        <li>@Html.ActionLink("Forum", "Forum")</li>
    </ul>
</div>
باستثناء ذلك ، وبغض النظر عن العرض ، سيكون لدي دائمًا تمييز في الرابط الأول. ما لم أستخدم الأقسام. دعنا نستبدل التخطيط للحصول على:

        <!DOCTYPE html>
        
        <html>
        <head>
            <meta name="viewport" content="width=device-width" />
            <title>@ViewBag.Title</title>
            <link type="text/css" rel="stylesheet" href="~/Content/supertuto.css" />
        </head>
        <body>
            <div id="entete">
                <h1>Bienvenue sur Super tuto</h1>
            </div>
        
            <div id="main">
                <div id="menu">
                    @RenderSection("Menu")
                </div>
        
                <div id="contenu">
                    @RenderBody()
                </div>
            </div>
        
            <div id="footer">
                © @DateTime.Now.Year - Super site de tutoriels, contactez moi sur monmail@supersitetutoriels.com
            </div>
        </body> ;
        < ;/html> ;
        
ترى أن داخل علامة div القائمة، وأضفت السطر: @RenderSection("Menu") . يجب فقط تعريف هذا القسم في عرض الصفحة الرئيسية:

        @{
            ViewBag.Title = "Accueil";
        }
        
        <h3 class="titre">Accueil du site de tutoriels</h3>
        <p class="contenu">Ici c'est la page d'accueil avec les news du site, etc.</p>
        
        @section Menu
        {
            <ul>
                <li class="selectionne">@Html.ActionLink("Accueil", "Index")</li>
                <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
                <li>@Html.ActionLink("Forum", "Forum")</li>
            </ul>
        }
        
نستخدم @section  متبوعًا باسم القسم لإعادة تعريفه. يجب أن أضع هذا القسم في واجهات العرض الخاصة بي الأخرى بتغيير طفيف في HTML . بالنسبة إلى القائمة ، سأقوم فقط بتغيير موقع الصف على العلامة 
  •   :
  • 
                @model  List<TestLayout.Models.Tuto>
                @{
                    ViewBag.Title = "Liste";
                }
                <h3 class="titre">
                    Liste des tutoriels</h3>
                <table>
                    <tr>
                        <th>Tutoriel</th>
                        <th>Lien</th>
                    </tr>
                    @foreach (var tutoriel in Model)
                    {
                        <tr>
                            <td>@tutoriel.Titre</td>
                            <td>@Html.ActionLink(tutoriel.Lien, "AfficheTutoriel", new { id = tutoriel.Id})</td>
                        </tr>
                    }
                </table>
                
                @section Menu
                {
                    <ul>
                        <li>@Html.ActionLink("Accueil", "Index")</li>
                        <li class="selectionne">@Html.ActionLink("Liste des tutoriels", "Liste")</li>
                        <li>@Html.ActionLink("Forum", "Forum")</li>
                    </ul>
                }
                
    ونفسًا لعرض المنتدى:
    
                @{
                    ViewBag.Title = "Forum";
                }
                
                <h3>En construction...</h3>
                
                @section Menu
                {
                    <ul>
                        <li>@Html.ActionLink("Accueil", "Index")</li>
                        <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
                        <li class="selectionne">@Html.ActionLink("Forum", "Forum")</li>
                    </ul>
                }
                
    هذا يسمح لي بوضع عناصر مختلفة في كل طريقة عرض ، وهي عملية جدًا لتكييف القائمة أو التذييل ، أو غيرها ...
    بالإضافة إلى ذلك ، عدد الأقسام غير محدود ، يمكنك تخصيص صفحاتك كما تراه مناسبًا .
    أخبرتك أيضًا أنه من الممكن تحديد ما إذا كان القسم إلزاميًا أم لا. مع الاستخدام الذي قمنا به للتو:
    
                @RenderSection("Menu")
                
    القسم إلزامي. هذا يعني أنه إذا لم نحدد القسم في إحدى طرق العرض وانتقل إلى هذا العرض ، فإن ASP.NET MVC سيثير خطأ:
    ASP.NET framework
    خطأ عندما يكون القسم غير محدد
    من الممكن جعل القسم اختياريًا باستخدام الطريقة RenderSection  بهذه الطريقة:
    
    @RenderSection("Menu", required: false)
    
    وبالتالي ، لم تعد بحاجة إلى تحديد قسم القائمة إذا كان لديك عرض في أي مكان لا تريد عرضه فيه. حسنًا ... في حالتنا ، سيؤدي ذلك إلى إحداث ثقب أبيض كبير ، ولكن يمكننا العثور على الكثير من الأقسام الاختيارية المحتملة.
    يمكننا أيضًا التحقق مما إذا تم تعريف القسم ولماذا لا يتم استبداله بقيمة افتراضية عندما لا يكون هذا هو الحال. فقط استخدم الطريقة IsSectionDefined  . يمكننا على سبيل المثال أن نفعل لتذييل الصفحة:
    
    <div id="footer">
    @if (IsSectionDefined("footer"))
        {
            @RenderSection("footer")
        }
        else
        {
            <text>© @DateTime.Now.Year - Super site de tutoriels, contactez moi sur monmail@supersitetutoriels.com</text>
        }
    </div>
    
    سيتيح لك ذلك الفرصة لتخصيص تذييلك أو أخذ القيمة الافتراضية.
    بالطبع ، يمكنك دمج الأقسام مع قوة واجهات العرض الجزئية. تخيل أنه في موقعك لديك نصف الصفحات حيث عليك تحديد تذييل والنصف الآخر يستخدم الافتراضي ؛ بدلاً من نسخ نفس التذييل X مرة ، يمكنك استدعاء عرض جزئي لعرض التذييل ...
    من الممارسات الشائعة للأقسام تحديد قسم يسمح بتضمين نصوص جافا سكريبت أو CSS من التخطيط وإدراج النصوص البرمجية اللازمة للعرض في هذا القسم. في التخطيط يمكننا وضع:
    
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>@ViewBag.Title</title>
        <link type="text/css" rel="stylesheet" href="~/Content/supertuto.css" />
        <script type="text/javascript" src="~/Scripts/jquery-1.10.2.js"></script>
        @RenderSection("scripts", required: false)
    </head>
    
    ومن العرض ، سيكون لدينا:
    
        @section scripts
    {
    <script type="text/javascript">
        $(function () {
            alert('test');
        });
    </script>
    }
    
    ملاحظة: من المهم هنا تضمين jQuery قبل قسم النصوص البرمجية لأنني أستخدم jQuery في القسم الخاص بي.

    باختصار


    • Razor هو محرك العرض الجديد لـ ASP.NET MVC ، والذي ظهر مع الإصدار 3 من ASP.NET MVC.
    • ASPX هو محرك العرض التاريخي ولم يعد متوفرًا منذ Visual Studio 2013 .
    • تعمل Razor على تبسيط كتابة العروض مقارنة بـ ASPX من خلال الاستفادة من التحولات الخفيفة بين العلامات ورمز C# .
    • يمكنك تحديد قالب لتطبيقه على كافة طرق عرض الموقع باستخدام التخطيطات.
    • تعد الأقسام مكملة للتخطيطات وتسمح لك بإعادة تحديد المناطق المحددة مسبقًا في طرق العرض التي ترث تخطيطًا.