@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 کار میکردم؟!»