اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
پنج دقیقه
تعریف ActionLink زیر را درنظر بگیرید:
پارامترهای دوم و سوم آن که به نامهای یک اکشن متد و کنترلر آن اشاره میکنند، توسط رشتهها تعریف شدهاند. مشکلاتی هم که با رشتهها در حالت کلی وجود دارند به شرح زیر است:
الف) میتوان نام کنترلر یا نام متد را در برنامه تغییر داد. به این ترتیب تمام ActionLink هایی که در برنامه به این کنترلر اشاره میکردند از کار میافتند (تکرار رشتهها به علاوه refactoring friendly نبودن آنها).
ب) برای نوشتن رشتهها intellisense کارآیی ندارد.
ج) امکان بروز اشتباهات تایپی در این بین بسیار زیاد است.
راه حل متداولی که برای حل این نوع مشکلات وجود دارد، تعریف یک کلاس عمومی و معرفی رشتهها به صورت فیلدهایی ثابت در آنها میباشند و سپس استفاده از این فیلدها بجای استفاده مستقیم از رشتهها.
و ... چقدر خوب میشد اگر ابزاری وجود میداشت که کلاسهای کنترلرهای ما را آنالیز میکرد و خودش این ثوابت رشتهای را از آنها استخراج و کلاسهای عمومی یاد شده را تشکیل میداد!
خوشبختانه نیازی به اختراع مجدد چرخ نیست و اینکار توسط پروژهی سورس بازی به نام T4MVC انجام شده است. برای دریافت آن به سایت زیر مراجعه نمائید:
این پروژه توسط David Ebbo از اعضای تیم ASP.NET MVC تهیه شده است.
پس از دریافت پروژه، تنها به دو فایل زیر از آن نیاز داریم:
T4MVC.tt و T4MVC.tt.settings.t4
دو فایل فوق را به درون پوشهای از پروژه جاری MVC خود کپی کنید (مثلا یک پوشه T4MVC را ایجاد و این دو فایل را به آن اضافه کنید). بلافاصله این فایلهای t4 وارد عمل شده و کلاسهای کنترلرها، Viewها، تصاویر و غیره را آنالیز و ... ثوابت رشتهای معادل آنها را تولید میکنند.
اکنون برای استفاده از این کلاسهای تولید شده میتوان به صورت زیر عمل کرد:
اصلاح ActionLinkها و حذف رشتههای موجود در آنها
اینبار بجای اینکه بنویسیم:
میتوان نوشت:
و یا:
برای دسترسی به امکانات آن با نام کلاس MVC شروع میکنیم و سپس برای مثال به نام کنترلر Home رسیده و توسط ActionNames آن به تمام اکشن متدهای موجود در آن میتوان دسترسی داشت.
البته این پروژه بسیار فراتر از تولید فیلدهای strongly typed معادل رشتهها است. همانطور که ملاحظه میکنید، یک سری overload را هم به متدهای پیش فرض ASP.NET MVC اضافه کرده است و حتی بجای معرفی رشته معادل اکشن متد Index، خود این اکشن متد را میتوان معرفی کرد (آرگومانی از نوع ActionResult را هم اضافه کرده است). نمونه دیگر آن به نحو زیر میتواند باشد:
که بجای مورد متداول ذیل قابل استفاده است:
امکان معرفی بهتر نام Partial Viewها
برای مثال اگر پیشتر یک Partial View را به این شکل تعریف میکردید:
اکنون امکان معرفی آن به نحو زیر فراهم شده است:
همچنین تمام این کلاسها در کنترلرها نیز قابل دسترسی هستند:
اینجا دیگر نیازی به ذکر کلاس MVC نبوده و میتوان کار را با کلاس جدید Views شروع کرد. یا اگر نیازی به ذکر نام اکشن متدی در کنترلر جاری بود میتوان از ActionNames مستقیما استفاده کرد.
و یا بجای:
میتوان نوشت:
و یا حتی به صورت خلاصهتر به نحو زیر:
این overload جدیدی است که با T4MVC به پروژه اضافه میشود و یک Action Result را میتواند بپذیرد. به این ترتیب به صورت خودکار نام کنترلر و متد Index آن تنها در یک پارامتر لحاظ میشوند. اگر نیاز به ارسال پارامتری هم به متد Index وجود داشت، همینجا میتوان اینکار را انجام داد (بجای استفاده از anonymously typed objects متداول).
و یا بجای مسیر دهی به شکل زیر:
میتوان نوشت:
همچنین برای مسیر دهی viewهای قرار گرفته در پوشه shared میتوان از MVC.Shared.Views شروع کرد.
امکان معرفی بهتر عناصر استاتیک سایت
این مورد نیز بسیار جالب توجه است. توسط کلاس Links آن میتوان به محتویات استاتیک (تصاویر، فایلهای css و غیره) پوشههای Content و Scripts هم دسترسی یافت و حتی این موارد را نیز refactor کرد:
امکان تعریف بهتر پارامترها و مقادیر route
بجای اینکه routeValues را همانند سابق با anonymously typed objects مقدار دهی کنیم:
اینبار میتوان نوشت:
در overload جدیدی که ملاحظه میکنید، هم دسترسی به متد Index یک کنترلر از نوع strongly typed است و هم امکان تعریف پارامترهای آن به نحو منطقیتری فراهم شده است (متد Comments.Index واقعا وجود خارجی داشته و پارامتری از نوع userName را میپذیرد).
چند نکته جانبی
-این ابزار بر اساس Reflection کار میکند (البته فقط در حین تشکیل خودکار کلاسهای مورد نیاز؛ وگرنه ثوابتی را که ایجاد میکند کامپایل شده و در زمان اجرا سرباری را به برنامه اضافه نمیکنند). بنابراین اگر کلاسی به پروژه اضافه شده است، کامپایل کردن آنرا فراموش نکنید.
-اگر تغییری در فایلهای View، در تعداد و نام آنها صورت گرفت، روی فایل T4MVC.tt کلیک راست کرده و گزینهی اجرای آنرا انتخاب کنید. پس از اینکار، مجددا کامپایل پروژه را فراموش نکنید.
-در فایل T4MVC.tt.settings.t4 یک سری تنظیمات پیش فرض قرار دارند. برای مثال اگر علاقمندید که به این فایلهای تولید شده خودکار، فضای نام سفارشی خاصی را اضافه کنید میشود آرایه ReferencedNamespaces آنرا مقدار دهی کرد.
- overloadهای جدید ActionResult دار آن نسبت به نمونههای استاندارد موجود، بسیار منطقیتر به نظر میرسند.
- توضیحات کامل امکانات T4MVC را در مستندات رسمی آن میتوانید مطالعه کنید.
و ... اگر یک مدت با آن کار کنید خواهید گفت: «من قبلا چطور با ASP.NET MVC کار میکردم؟!»
@Html.ActionLink("text", "Index", "Home")
پارامترهای دوم و سوم آن که به نامهای یک اکشن متد و کنترلر آن اشاره میکنند، توسط رشتهها تعریف شدهاند. مشکلاتی هم که با رشتهها در حالت کلی وجود دارند به شرح زیر است:
الف) میتوان نام کنترلر یا نام متد را در برنامه تغییر داد. به این ترتیب تمام ActionLink هایی که در برنامه به این کنترلر اشاره میکردند از کار میافتند (تکرار رشتهها به علاوه refactoring friendly نبودن آنها).
ب) برای نوشتن رشتهها intellisense کارآیی ندارد.
ج) امکان بروز اشتباهات تایپی در این بین بسیار زیاد است.
راه حل متداولی که برای حل این نوع مشکلات وجود دارد، تعریف یک کلاس عمومی و معرفی رشتهها به صورت فیلدهایی ثابت در آنها میباشند و سپس استفاده از این فیلدها بجای استفاده مستقیم از رشتهها.
و ... چقدر خوب میشد اگر ابزاری وجود میداشت که کلاسهای کنترلرهای ما را آنالیز میکرد و خودش این ثوابت رشتهای را از آنها استخراج و کلاسهای عمومی یاد شده را تشکیل میداد!
خوشبختانه نیازی به اختراع مجدد چرخ نیست و اینکار توسط پروژهی سورس بازی به نام T4MVC انجام شده است. برای دریافت آن به سایت زیر مراجعه نمائید:
این پروژه توسط David Ebbo از اعضای تیم ASP.NET MVC تهیه شده است.
پس از دریافت پروژه، تنها به دو فایل زیر از آن نیاز داریم:
T4MVC.tt و T4MVC.tt.settings.t4
دو فایل فوق را به درون پوشهای از پروژه جاری MVC خود کپی کنید (مثلا یک پوشه T4MVC را ایجاد و این دو فایل را به آن اضافه کنید). بلافاصله این فایلهای t4 وارد عمل شده و کلاسهای کنترلرها، Viewها، تصاویر و غیره را آنالیز و ... ثوابت رشتهای معادل آنها را تولید میکنند.
اکنون برای استفاده از این کلاسهای تولید شده میتوان به صورت زیر عمل کرد:
اصلاح ActionLinkها و حذف رشتههای موجود در آنها
اینبار بجای اینکه بنویسیم:
@Html.ActionLink("text", "Index", "Home")
@Html.ActionLink("text", result: MVC.Home.Index())
@Html.ActionLink("text", MVC.Home.ActionNames.Index, MVC.Home.Name)
برای دسترسی به امکانات آن با نام کلاس MVC شروع میکنیم و سپس برای مثال به نام کنترلر Home رسیده و توسط ActionNames آن به تمام اکشن متدهای موجود در آن میتوان دسترسی داشت.
البته این پروژه بسیار فراتر از تولید فیلدهای strongly typed معادل رشتهها است. همانطور که ملاحظه میکنید، یک سری overload را هم به متدهای پیش فرض ASP.NET MVC اضافه کرده است و حتی بجای معرفی رشته معادل اکشن متد Index، خود این اکشن متد را میتوان معرفی کرد (آرگومانی از نوع ActionResult را هم اضافه کرده است). نمونه دیگر آن به نحو زیر میتواند باشد:
@Url.Action(result: MVC.Article.Delete())
@Url.Action("Delete", "Article")
امکان معرفی بهتر نام Partial Viewها
برای مثال اگر پیشتر یک Partial View را به این شکل تعریف میکردید:
@{ Html.RenderPartial("_ViewPage1"); }
@{ Html.RenderPartial(MVC.Home.Views._ViewPage1); }
return PartialView(Views._ViewPage1);
و یا بجای:
return RedirectToAction(actionName: "Index", controllerName: "Menu");
return RedirectToAction(actionName: MVC.Menu.ActionNames.Index, controllerName: MVC.Menu.Name);
return RedirectToAction(result: MVC.Menu.Index());
و یا بجای مسیر دهی به شکل زیر:
return PartialView("~/Views/CommentsArchive/_LatestCommentsInfo.cshtml", data);
return PartialView(MVC.CommentsArchive.Views._LatestCommentsInfo, data);
امکان معرفی بهتر عناصر استاتیک سایت
این مورد نیز بسیار جالب توجه است. توسط کلاس Links آن میتوان به محتویات استاتیک (تصاویر، فایلهای css و غیره) پوشههای Content و Scripts هم دسترسی یافت و حتی این موارد را نیز refactor کرد:
<img src="@Links.Content.Images.arrow_right_png" alt="arrow" /> <script src="@Links.Scripts.jquery_1_5_1_min_js" type="text/javascript"></script>
امکان تعریف بهتر پارامترها و مقادیر route
بجای اینکه routeValues را همانند سابق با anonymously typed objects مقدار دهی کنیم:
Html.ActionLink(linkText: "عنوان", actionName: "Index", controllerName: "Comments", routeValues: new { userName = @Model.FriendlyName }, htmlAttributes: null))
Html.ActionLink(linkText: "عنوان", result: MVC.Comments.Index(userName: @Model.FriendlyName) htmlAttributes: null))
چند نکته جانبی
-این ابزار بر اساس Reflection کار میکند (البته فقط در حین تشکیل خودکار کلاسهای مورد نیاز؛ وگرنه ثوابتی را که ایجاد میکند کامپایل شده و در زمان اجرا سرباری را به برنامه اضافه نمیکنند). بنابراین اگر کلاسی به پروژه اضافه شده است، کامپایل کردن آنرا فراموش نکنید.
-اگر تغییری در فایلهای View، در تعداد و نام آنها صورت گرفت، روی فایل T4MVC.tt کلیک راست کرده و گزینهی اجرای آنرا انتخاب کنید. پس از اینکار، مجددا کامپایل پروژه را فراموش نکنید.
-در فایل T4MVC.tt.settings.t4 یک سری تنظیمات پیش فرض قرار دارند. برای مثال اگر علاقمندید که به این فایلهای تولید شده خودکار، فضای نام سفارشی خاصی را اضافه کنید میشود آرایه ReferencedNamespaces آنرا مقدار دهی کرد.
- overloadهای جدید ActionResult دار آن نسبت به نمونههای استاندارد موجود، بسیار منطقیتر به نظر میرسند.
- توضیحات کامل امکانات T4MVC را در مستندات رسمی آن میتوانید مطالعه کنید.
و ... اگر یک مدت با آن کار کنید خواهید گفت: «من قبلا چطور با ASP.NET MVC کار میکردم؟!»