EF Code First #7
MVC Scaffolding #2
دو نوع پارامتر حین کار با MVC Scaffolding مهیا هستند:
الف) سوئیچها
مانند پارامترهای boolean عمل کرده و شامل موارد ذیل میباشند. تمام این پارامترها به صورت پیش فرض دارای مقدار false بوده و ذکر هرکدام در دستور نهایی سبب true شدن مقدار آنها میگردد:
Repository: برای تولید کدها بر اساس الگوی مخزن
Force: برای بازنویسی فایلهای موجود.
ReferenceScriptLibraries: ارجاعاتی را به اسکریپتهای موجود در پوشه Scripts، اضافه میکند.
NoChildItems: در این حالت فقط کلاس کنترلر تولید میشود و از سایر ملحقات مانند تولید Viewها، DbContext و غیره صرفنظر خواهد شد.
ب) رشتهها
این نوع پارامترها، رشتهای را به عنوان ورودی خود دریافت میکنند و شامل موارد ذیل هستند:
ControllerName: جهت مشخص سازی نام کنترلر مورد نظر
ModelType: برای ذکر صریح کلاس مورد استفاده در تشکیل کنترلر بکار میرود. اگر ذکر نشود، از نام کنترلر حدس زده خواهد شد.
DbContext: نام کلاس DbContext تولیدی را مشخص میکند. اگر ذکر نشود از نامی مانند ProjectNameContex استفاده خواهد کرد.
Project: پیش فرض آن پروژه جاری است یا اینکه میتوان پروژه دیگری را برای قرار دادن فایلهای تولیدی مشخص کرد. (برای مثال هربار یک سری کد مقدماتی را در یک پروژه جانبی تولید کرد و سپس موارد مورد نیاز را از آن به پروژه اصلی افزود)
CodeLanguage: میتواند cs یا vb باشد. پیش فرض آن زبان جاری پروژه است.
Area: اگر میخواهید کدهای تولیدی در یک ASP.NET MVC area مشخص قرار گیرند، نام Area مشخصی را در اینجا ذکر کنید.
Layout: در حالت پیش فرض از فایل layout اصلی استفاده خواهد شد. اما اگر نیاز است از layout دیگری استفاده شود، مسیر نسبی کامل آنرا در اینجا قید نمائید.
یک نکته:
نیازی به حفظ کردن هیچکدام از موارد فوق نیست. برای مثال در خط فرمان پاورشل، دستور Scaffold را نوشته و پس از یک فاصله، دکمه Tab را فشار دهید. لیست پارامترهای قابل اجرای در این حالت ظاهر خواهند شد. اگر در اینجا برای نمونه Controller انتخاب شود، مجددا با ورود یک فاصله و خط تیره و سپس فشردن دکمه Tab، لیست پارامترهای مجاز و همراه با سوئیچ کنترلر ظاهر میگردند.
MVC Scaffolding و مدیریت روابط بین کلاسها
مثال قسمت قبلی بسیار ساده و شامل یک کلاس بود. اگر آنرا کمی پیچیدهتر کرده و برای مثال روابط one-to-many و many-to-many را اضافه کنیم چطور؟
using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace MvcApplication1.Models { public class Task { public int Id { set; get; } [Required] public string Name { set; get; } [DisplayName("Due Date")] public DateTime? DueDate { set; get; } [ForeignKey("StatusId")] public virtual Status Status { set; get; } // one-to-many public int StatusId { set; get; } [StringLength(450)] public string Description { set; get; } public virtual ICollection<Tag> Tags { set; get; } // many-to-many } public class Tag { public int Id { set; get; } [Required] public string Name { set; get; } public virtual ICollection<Task> Tasks { set; get; } // many-to-many } public class Status { public int Id { set; get; } [Required] public string Name { set; get; } } }
در ادامه دستور تولید کنترلرهای Task، Tag و Status ساخته شده با الگوی مخزن را در خط فرمان پاورشل ویژوال استودیو صادر میکنیم:
PM> Scaffold Controller -ModelType Task -ControllerName TasksController -DbContextType TasksDbContext -Repository -Force PM> Scaffold Controller -ModelType Tag -ControllerName TagsController -DbContextType TasksDbContext -Repository -Force PM> Scaffold Controller -ModelType Status -ControllerName StatusController -DbContextType TasksDbContext -Repository -Force
چند نکته:
- با توجه به اینکه مدلها تغییر کردهاند، نیاز است بانک اطلاعاتی متناظر نیز به روز گردد. مطالب مرتبط با آنرا در مباحث Migrations میتوانید مطالعه نمائید.
- View تولیدی رابطه many-to-many را پشتیبانی نمیکند. این مورد را باید دستی اضافه و طراحی کنید: (^ و ^)
- رابطه one-to-many به خوبی با View متناظری دارای یک drop down list تولید خواهد شد. در اینجا لیست تولیدی به صورت خودکار با مقادیر خاصیت Name کلاس Status پر میشود. اگر این نام دقیقا Name نباشد نیاز است توسط ویژگی به نام DisplayColumn که بر روی نام کلاس قرار میگیرد، مشخص کنید از کدام خاصیت باید استفاده شود.
@Html.DropDownListFor(model => model.StatusId, ((IEnumerable<Status>)ViewBag.PossibleStatus).Select(option => new SelectListItem { Text = (option == null ? "None" : option.Name), Value = option.Id.ToString(), Selected = (Model != null) && (option.Id == Model.StatusId) }), "Choose...") @Html.ValidationMessageFor(model => model.StatusId)
تولید آزمونهای واحد به کمک MVC Scaffolding
MVC Scaffolding امکان تولید خودکار کلاسها و متدهای آزمون واحد را نیز دارد. برای این منظور دستور زیر را در خط فرمان پاورشل وارد نمائید:
PM> Scaffold MvcScaffolding.ActionWithUnitTest -Controller TasksController -Action ArchiveTask -ViewModel Task
نکته مهم آن، عدم حذف یا بازنویسی کامل کنترلر یاد شده است. کاری هم که در تولید متد آزمون واحد متناظر انجام میشود، تولید بدنه متد آزمون واحد به همراه تولید کدهای اولیه الگوی Arrange/Act/Assert است. پر کردن جزئیات بیشتر آن با برنامه نویس است.
و یا به صورت خلاصهتر:
PM> Scaffold UnitTest Tasks Delete
کار مقدماتی با MVC Scaffolding و امکانات مهیای در آن همینجا به پایان میرسد. در قسمتهای بعد به سفارشی سازی این مجموعه خواهیم پرداخت.
آموزش عالی برای کسانی که میخواهند WPF و الگوی MVVM و CODE FIRST رو باهم یاد بگیرند :
At the core of developing a data-driven WPF application is a thorough knowledge of how to use the MVVM Pattern and Entity Framework. In this course, Building an Enterprise App with WPF, MVVM, and Entity Framework Code First, you will learn the skills you need to create high-quality enterprise applications with WPF. First, you'll learn about typical scenarios like communicating between different ViewModels, detecting model changes, and handling many-to-many relations. Next, you'll learn all about creating a tabbed user interface. Finally, you'll explore implementing optimistic concurrency and styling your application. When you're finished with this course, you will have a deep understanding of WPF, MVVM, and Entity Framework that will help you immensely as you move forward and create your own data-driven enterprise application
استفاده از CSS علاوه بر جذابیت و قابلیتهای مفید آن، پیچیدگی هایی دارد و کدهای شما معمولا طولانی میشود و هرچه کدها طولانیتر شوند، مدیریت آن نیز سختتر میگردد. اما با استفاده از SASS ، قابلیت هایی به Css اضافه میشود که قبلا وجود نداشت، از جمله استفاده از varible ها، نوشتن کدهای تو در تو ( nesting ) و … . با استفاده از SASS کدهای CSS کوتاهتر شده و در نتیجه سریعتر اجرا شوند. SASS با CSS3 سازگار است. همچنین امکان مشاهده فایلهای آن (با پسوند .scss ) توسط افزونه Firesass For Firebug وجود دارد.
دو syntax برای SASS وجود دارد: یکی SCSS (Sassy CSS) که شکل توسعه یافته CSS3 می باشدو دیگری که قدیمیتر است، Indented syntax میباشد که در آن به جای استفاده از براکت، از تورفتگی خطهای کد استفاده میشود و همچنین از به جای استفاده از سمی کولن ، باید به خط جدید بروید.
قابلیتهای موجود در SASS :
1- Variables
متغیرها امکان ایجاد تغییرات در کدهای CSS را بسیار راحتتر میسازند. به عنوان مثال یک متغیر برای یک کد رنگ دلخواه تعریف میکنید، از این به بعد به جای استفاده از کد رنگ در کدهای CSS ، از متغیر تعریف شده برای آن بهره میگیرید، به این ترتیب ، چنانچه در آینده نیاز به تغییر این کد رنگ داشته باشید، تنها با تغییر آن در متغیر ، در کل فایل CSS تغییر ایجاد خواهد شد . برای تعریف متغیر ، در ابتدای اسم دلخواه خود از علامت $ استفاده کنید:
$myColor: #ff0000; body { color: $myColor; } .box{ Border-color:$myColor; }
Nesting -2 یا selector های تو در تو:
می توانید selector ها را مانند کدهای html به صورت hirearchy تعریف کنید:
nav { ul { list-style: none; } li { display: inline-block; } a { text-decoration: none; } }
nav ul { list-style: none; } nav li { display: inline-block; } nav a { text-decoration: none; }
3- Partials :
می توانید قطعاتی از کدهای CSS را به صورت Partial SASS تعریف کنید و سپس آن را در فایلهای SASS دیگر استفاده نمایید.همانند Partialview در MVC ، هنگام نام گذاری آن از _ در ابتدای نام استفاده نمایید. فایل partial SASS دارای پسوند .SCSS می باشد : " "_myPartial.scss
برای استفاده از _myPartial.scss در فایل sass دیگر ، از دایرکتیو @import استفاده کنید:
@import "myPartial"
@import "mypartial1","myPartial2"
/*_myPartial1.scss codes…*/ html,body,ul,ol { margin: 0; padding: 0; } /*_myPartial2.scss codes…*/ @import "myPartial1" body, { background-color: #efefef; }
html, body, ul, ol { margin: 0; padding: 0; } body { background-color: #efefef; }
4- Mixins :
از آنجایی که استفاده و نوشتن بعضی property های CSS سخت میباشد، میتوانید از روش mixin استفاده کرده و قطعه کدهایی را ایجاد کنید که بتوانید در کدهایتان از آنها بارها و بارها استفاده کنید. به عنوان مثال قطع کدی برای border-radius ایجاد کنید ، (همانطور که میدانید border-radius برای مرورگرهای مختلف ، حالتهای مختلفی تعریف میشود.). برای ایجاد mixin ، در ابتدای قطع کد از @mixin استفاده نمایید و برای استفاده ازآن ، از @include استفاده نمایید:
@mixin cssProperty $yourCustomName{ … Your css properties… }
نمونه کد:
ایجاد mixin: @mixin border-radius($radius) { -webkit-border-radius: $radius; -moz-border-radius: $radius; -ms-border-radius: $radius; -o-border-radius: $radius; border-radius: $radius; } استفاده از mixin: .box { @include border-radius(10px); }
Extend/Inheritance -5 :
@XETEND به شما این امکان را میدهد تا بخشی از Property های یک selector را برای استفاده در selector های دیگر به اشتراک بگذارید:
.message { border: 1px solid #ccc; padding: 10px; color: #333; } .success { @extend .message; border-color: green; }
کدها بعد از تولید شدن به صورت زیر دیده میشوند:
.message, .success { border: 1px solid #cccccc; padding: 10px; color: #333; } .success { border-color: green; }
6- Operators :
می توانید از عملگرهای ضرب و تقسیم و جمع و تفریق در کدهای CSS خود استفاده نمایید:
article[role="main"] { float: left; width: 600px / 960px * 100%; }
نصب SASS :
حال که با SASS آشنا شدید ، انگیزه کافی برای دانستن روش نصب و استفاده آن خواهید داشت. برای استفاده از SASS می توانید از نرم افزارهایی که برای ویندوز ، مک و لینوکس وجود دارند، استفاده کنید از جمله این نرم افزارها :
CodeKit , Compass.app , Hammer , Koala , LiveReload , Mixture , Prepros , Prepros Pro , Scout
روش دیگر استفاده از command line میباشد:
چنانچه سیستم عامل شما ویندوز میباشد، برای استفاده از sass ابتدا باید rubby را نصب نمایید. سپس در Cmd خط زیر را اجرا کنید:
gem install sass
چنانچه به خطایی برخوردید، ابتدا gem توسط sudo را نصب کنید:
sudo gem install sass
سپس توسط خط زیر چک کنید که SASS نصب شده است یا خیر:
sass -v
Sass 3.2.12 (Media Mark)
برای کسب اطلاعات بیشتر و روش نصب در سایر سیستم عاملها به این لینک مراجعه نمایید.
SassScript :
فایل SASS اسکریپتی برای اجرای یک سری از فانکشنها دارد، از جمله :
- rgb($red, $green, $blue) /* برای ایجاد کد رنگ rgb */
برای مشاهده لیست کامل این فانکشنها به این لینک مراجعه کنید.
منبع
در مواقعی نیاز است تا محتوایی را به صورت داینامیک به کدهای موجود در یک app Angular تزریق کنیم و یا محتوای موجود را تغییر دهیم. اگر این محتوای لود شده دارای دایرکتیوهای Angularباشد بعد از لود محتوا متوجه میشویم که کدهای Angular ما کار نمیکنند. چرا؟ اینجاست که نقش compile$ مشخص میشود. از طریق compile$ محتوای لود شده مجددا در محدوده تحت مدیریت Angular قرار گرفته و مشکل حل میشود. مثال زیر را بررسی میکنیم :
app.directive("otcDynamic", function(){ return { link: function(scope, element){ element.html("<button ng-click='doSomething()'>{{label}}</button>"); } }; });
در کد فوق ما یک دکمه را که در کلیک آن قرار است متدی توسط Angular فراخوانی شود، به صورت داینامیک ایجاد کرده و به المنت مورد نظرمان اضافه کردهایم. دقت داشته باشید که این محتوا ممکن است مثلا توسط درخواستهای Ajax از جایی فراخوانی شود. با کلیک بر روی دکمهی ایجاد شده، متد doSomething اجرا نخواهد شد؛ چرا که Angular قادر به تشخیص HTML تزریق شده نمیباشد و در واقع اصلا از وجود کد ما خبری ندارد. برای حل این مشکل از compile $ استفاده میکنیم:
app.directive("otcDynamic", function($compile){ return{ link: function(scope, element){ var template = "<button ng-click='doSomething()'>{{label}}</button>"; var linkFn = $compile(template); var content = linkFn(scope); element.append(content); } } });
با استفاده از compile $ در واقع ما
کدهای خود را مجددا تحت مدیریت Angular قرار میدهیم.
مثال فوق یک مثال ساده از این مبحث بود. در واقع کدهای تزریق شده میتوانند شامل کل
HTML تحت
مدیریت Angular
باشد که مثلا از طریق درخواستهای Ajax بهروز رسانی میشوند.