عنوان:

‫T4MVC : یکی از الزامات مدیریت پروژه‌های ASP.NET MVC


نویسنده: وحید نصیری
تاریخ: ۱۳۹۱/۰۴/۱۱ ۹:۴۵
آدرس: www.dntips.ir
تعریف ActionLink زیر را درنظر بگیرید:
@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);
اینجا دیگر نیازی به ذکر کلاس MVC نبوده و می‌توان کار را با کلاس جدید Views شروع کرد. یا اگر نیازی به ذکر نام اکشن متدی در کنترلر جاری بود می‌توان از ActionNames مستقیما استفاده کرد.
و یا بجای:
return RedirectToAction(actionName: "Index", controllerName: "Menu");
می‌توان نوشت:
return RedirectToAction(actionName: MVC.Menu.ActionNames.Index, controllerName: MVC.Menu.Name);
و یا حتی به صورت خلاصه‌تر به نحو زیر:
return RedirectToAction(result: MVC.Menu.Index());
این overload جدیدی است که با T4MVC به پروژه اضافه می‌شود و یک Action Result را می‌تواند بپذیرد. به این ترتیب به صورت خودکار نام کنترلر و متد Index آن تنها در یک پارامتر لحاظ می‌شوند. اگر نیاز به ارسال پارامتری هم به متد Index وجود داشت، همینجا می‌توان اینکار را انجام داد (بجای استفاده از anonymously typed objects متداول).

و یا بجای مسیر دهی به شکل زیر:
return PartialView("~/Views/CommentsArchive/_LatestCommentsInfo.cshtml", data);
می‌توان نوشت:
return PartialView(MVC.CommentsArchive.Views._LatestCommentsInfo, data);
همچنین برای مسیر دهی viewهای قرار گرفته در پوشه shared می‌توان از MVC.Shared.Views شروع کرد.


امکان معرفی بهتر عناصر استاتیک سایت

این مورد نیز بسیار جالب توجه است. توسط کلاس 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))
در overload جدیدی که ملاحظه می‌کنید، هم دسترسی به متد Index یک کنترلر از نوع strongly typed است و هم امکان تعریف پارامترهای آن به نحو منطقی‌تری فراهم شده است (متد Comments.Index واقعا وجود خارجی داشته و پارامتری از نوع userName را می‌پذیرد).


چند نکته جانبی
-این ابزار بر اساس Reflection کار می‌کند (البته فقط در حین تشکیل خودکار کلاس‌های مورد نیاز؛ وگرنه ثوابتی را که ایجاد می‌کند کامپایل شده و در زمان اجرا سرباری را به برنامه اضافه نمی‌کنند). بنابراین اگر کلاسی به پروژه اضافه شده است، کامپایل کردن آن‌را فراموش نکنید.
-اگر تغییری در فایل‌های View، در تعداد و نام آن‌ها صورت گرفت، روی فایل T4MVC.tt کلیک راست کرده و گزینه‌ی اجرای آن‌را انتخاب کنید. پس از این‌کار، مجددا کامپایل پروژه را فراموش نکنید.
-در فایل T4MVC.tt.settings.t4 یک سری تنظیمات پیش فرض قرار دارند. برای مثال اگر علاقمندید که به این فایل‌های تولید شده خودکار، فضای نام سفارشی خاصی را اضافه کنید می‌شود آرایه ReferencedNamespaces آن‌را مقدار دهی کرد.
- overloadهای جدید ActionResult دار آن نسبت به نمونه‌های استاندارد موجود، بسیار منطقی‌تر به نظر می‌رسند.
- توضیحات کامل امکانات T4MVC را در مستندات رسمی آن می‌توانید مطالعه کنید.


و ... اگر یک مدت با آن کار کنید خواهید گفت: «من قبلا چطور با ASP.NET MVC کار می‌کردم؟!»

نظرات

  • امیرحسین جلوداری در ۱۳۹۱/۰۴/۱۱ ۱۱:۱۶
    خیلی ممنون ... واجب شد که ازش استفاده کنیم دیگه :دی
  • یوسف نژاد در ۱۳۹۱/۰۴/۱۱ ۱۲:۵
    با تشکر. عالی بود. مخصوصا بخش «من قبلا چطور با ASP.NET MVC کار می‌کردم؟!» واقعا.
  • مهمان در ۱۳۹۱/۰۴/۱۱ ۱۶:۱
    عاشق روش‌های Refactoring Friendly هستم! در یک پروژه در دست انجام MVC بلافاصله شروع به استفاده از این ابزار کردیم... ابزار خوبی به نظر می‌رسد.
  • شهروز جعفری در ۱۳۹۱/۰۴/۱۱ ۱۹:۳۳
    اگه در routeValues  بخواهیم چند پارامتر بدم چ جوری باید عملل کرد من به صورت زیر میدم syntax error میده 
                    @Html.ActionLink(linkText: item.Name,result: MVC.Word.Details(id : item.ID, name : item.Name.ToSeoUrl() ))
    
    • شهروز جعفری در ۱۳۹۱/۰۴/۱۱ ۱۹:۳۷
      پدا کردم مرسی
      Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID)
          .AddRouteValue("foo", 17)
          .AddRouteValue("bar", "abc"))
  • مهمان در ۱۳۹۱/۰۴/۱۱ ۲۱:۱۴
    سلام یک سوال داشتم
    من از طریق jquery یک iupdatio رو صفحه انجام دادم.
        <script type="text/javascript">
            function LaodWordInfo(id) {
                showProgress();
                $.ajax({
                    type: "Post",
                    url: "test/Info",
                    data: JSON.stringify({ ID: id }),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    complete: function (xhr, status) {
                        var data = xhr.responseText;
                        if (status === 'error' || !data) {
    
                        } else {
                            var dialog = $("#dialog");
                            dialog.html(data);
                            dialog.dialog("open");
                        }
                        hideProgress();
                        return false;
                    }
                }
    );
            }
    
            function showProgress() {
                $('#Progress').css("display", "block");
            }
    
            function hideProgress() {
                $('#Progress').css("display", "none");
            }
            $(function () {
                $("#dialog").dialog({
    
                    autoOpen: false,
                    show: "fade",
                    hide: "fade",
                    width: 550,
                    title: "WordInfo",
                    resizable: false
                });
            });
        </script>
    این باید یه دیالوگ پر کنه نمایش بده.
    ولی از وقتی T4MVC استفاده کردم تو کروم درست نشون میده ولی فایرفاکس  error زیرو میده
    "NetworkError: 404 Not Found - http://localhost:6012/test/test/Info"  
    به آدرس دقت کنید دوبار  test  اورده
    • وحید نصیری در ۱۳۹۱/۰۴/۱۱ ۲۱:۲۴
      در کد فوق که از T4MVC استفاده نشده ولی نحوه تعریف Url شما اشتباه است. قبلا هم در مورد نحوه تعریف صحیح Url در ASP.NET MVC مطلب نوشتم. حتما باید از Url.Action استفاده کنید.
      برای اینکه بتونید از Url.Action در اسکریپت‌های خودتون استفاده کنید پایین View جاری یک section به نام مثلا JavaScript درست کنید. در اینجا می‌شود داخل کدهای جاوا اسکریپتی هم از Razor استفاده کرد. سپس این section را در layout در قسمت header صفحه include کنید (در قسمت 14 سری MVC این سایت در مورد این تکنیک کاملا توضیح دادم).

  • رضا بزرگی در ۱۳۹۱/۰۴/۱۲ ۲:۴۱
    نمونه‌های شبیه این باز هم بودند که مسئله‌ای که سالهاست دات نت با Reflection قابل حل کرده. ولی بازم تو جدیدترین تکنولوژی‌ها از مقادیر رشته‌ای استفاده میکنه. آیا هدف خاصی پشت این منطق هست؟ یا صرفا بی‌توجهی و قصور تیم توسعه هست؟
    • وحید نصیری در ۱۳۹۱/۰۴/۱۲ ۸:۳۶
      Reflection اندکی کند است. در حین توسعه برنامه اگر ویژوال استودیو مرتبا بخواهد کوئری‌های مبتنی بر reflection از اسمبلی‌های شما بگیرد، سرعت کار شما کم خواهد شد و نهایتا ممکن است سبب ناپایداری آن هم بشود (اگر پروژه جاری بزرگ باشد).
  • مهمان در ۱۳۹۱/۰۴/۱۲ ۲۳:۷
    در پروژه ما کنترلرها در یک class library جداگانه نگهداری می‌شوند. در این حالت T4MVC دچار مشکل می‌شود...

    http://forums.asp.net/p/1683368/5049673.aspx

    من T4MVC را به خود class library محل نگهداری Controllerها منتقل کردم و مشکلاتم حل شد.
  • حسین توسلی در ۱۳۹۱/۰۶/۱۰ ۱۷:۱۴
    با سلام و خسته نباشید خدمت دوستان
          آقا من نتونستم این فایل‌ها رو دانلود کنم، خواهش میکنم یه راهی بگین تا منم بتونم دانلودشون کنم.
    با تشکر
    • وحید نصیری در ۱۳۹۱/۰۶/۱۰ ۱۸:۴۷
      از اینجا دریافت کنید.
      • احمد ولی پور در ۱۳۹۳/۰۷/۱۵ ۰:۴۲
        من سه تا فایل T4MVC.tt و T4MVC.tt.settings.xml و حتی T4MVC.tt.hooks.t4  رو تو یه پوشه تو سطح اول میذازم ولی همش خطای زیر رو میده:
        Could not load file or assembly 'System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
          
        • وحید نصیری در ۱۳۹۳/۰۷/۱۵ ۱:۱۸
          تنظیمات فایل‌های کانفیگ برنامه شما (bindingRedirect ها) صحیح نیست یا ناقص است. اطلاعات بیشتر
  • ایلیا اکبری فرد در ۱۳۹۱/۰۸/۲۰ ۸:۵۹
    مهندس سلام.
    من موقع اضافه کردن T4mvc از طریق نوگت تحت mvc4 فایلی که  T4MVC.tt.settings.t4 نام داشته باشد را نمی‌بینم. کجای کارم ایراد دارد؟ با تشکر.
    • وحید نصیری در ۱۳۹۱/۰۸/۲۰ ۹:۱۰
      اگر علاقمند هستید که اخبار آن‌را دنبال کنید نیاز است سورس کنترل آن‌را مرور کنید:
      http://t4mvc.codeplex.com/SourceControl/list/changesets
      24cc121c697f, by Michael Swain, Oct 22 8:39 PM
      
      XmlSettings Patch
      
      Patch to modify T4MVC to use an XML settings file instead of a static
      include. This allows for future compatability as long as setting types
      do not change.
      نام جدید آن T4MVC.tt.settings.xml شده.
      + این فایل به همراه بسته NuGet آن نیست و باید از سورس کنترل دریافت شود (داخل پوشه T4MVCHostMvcApp\T4MVC Files).
      • ایلیا اکبری فرد در ۱۳۹۱/۰۸/۲۰ ۹:۱۹
        سپاس مهندس.
  • مهمان در ۱۳۹۱/۱۲/۱۰ ۱۰:۳۲
    با سلام
    من تو V.S. 2012 تعدادی کنترل جدید به پروژه اضافه کردم ولی T4MVC لیست نمی‌کردشون، کامپایل مجدد کل سولوشن هم کمکی نکرد؛ بعد روی فایل tt راست کلیک و Run Custom Tool  که زدم T4MVC خودشو به روز کرد؛ گفتم شاید به درد دوستانی که به مشکل مشابه برخوردن، بخوره ...
  • cooli در ۱۳۹۱/۱۲/۱۷ ۱۲:۵۰
    دو سوال
    1 - در ورژنی که بنده از NuGet نصب کردم ( 3.5.1 ) ، T4MVCExtensions هم نصب گردید ، کار T4MVCExtensions چیست ؟
    2 - بعد از اجرا ، تمام کلاس‌های Controllerهای پروژه من partial شدند و تمام Actionهای من virtual ، چرا ؟ آیا مشکلی در آینده برای Controllerها و Actionها پیش نخواهد آمد ؟
    • وحید نصیری در ۱۳۹۱/۱۲/۱۷ ۱۲:۵۶
      - یک سری متد کمکی اضافی برای کار با T4MVC که به صورت پیش فرض در MVC وجود ندارد؛ خصوصا برای کار با متدهایی که پارامتر Result دارند و متدهایی مانند MVC.Comments.Index را قبول می‌کنند.
      - خیر. این روش کلی کار کتابخانه T4MVC است برای فراهم آوردن امکان overriding مسایل توکار خودش به همراه افزودن یک سری تعاریف قابل استفاده در کنترلر جاری. مثلا زمانی که می‌نویسند View.MyPartialViewName، نیاز است کنترلر جاری partial تعریف شود تا به رشته یاد شده که توسط T4MVC اضافه می‌شود دسترسی یافت.
      در کل کار کردن با T4MVC علاوه بر دسترسی strongly typed به مسیرها و فایل‌های موجود پروژه، سرعت نهایی رندر شدن را هم بالا می‌برد؛ چون مسیرهایی را که ایجاد می‌کند، نیاز به کمترین حدس‌زدن و سعی و خطا را توسط موتور View جاری برای یافتن منبع مورد نظر دارد.
  • مهمان در ۱۳۹۱/۱۲/۲۰ ۹:۱۶
    فقط من پوشه رو اضافه کردم ولی زمانی که میخام مثل شما تو اکشن لینک بنویسم نمیشناسه مسیرها رو.خودش نمیاره مثل میخام به شاخه ویو دسترسی داشته باشم اصلا نمیشناسه

    • وحید نصیری در ۱۳۹۱/۱۲/۲۰ ۹:۱۹
      run custom tool  رو اجرا کردید؟
  • علی حق جو در ۱۳۹۲/۰۱/۲۶ ۱۱:۵۹
    با سلام.
    من T4MVC را بر روی پروژه اصلی قرار دادم.
    فایل‌های resource من در یک پروژه جدا قرار دارند. مدلهای پروژه من هم در یک پروژه جدا قرار دارند. حال برای تعریف خاصیت اعتبارسنجی روی یکی از خاصیت‌های ویومدل آیا می‌شود T4MVC را بکار برد؟ (بجای استفاده از magic string)
     [StringLength(25, ErrorMessageResourceType = typeof(ValidationErrorsResource), ErrorMessageResourceName = "InvalidStringLength")]
    public string FatherName { get; set; }

    • وحید نصیری در ۱۳۹۲/۰۱/۲۶ ۱۲:۴۰
      از T4ResX استفاده کنید.
      • علی یگانه مقدم در ۱۳۹۴/۰۷/۰۴ ۱۸:۵۷
        روی vs2013 قابل اجرا نیست؟ چون موقع نصب پیام میده روی هیچ یک از محصولات جاری قابل نصب نیست. داخل لاگ هم نسخه‌های پشتیبانی رو به صورت زیر ذکر کرده:
        9/26/2015 6:48:04 PM - Supported Products : 
        9/26/2015 6:48:04 PM - Microsoft.VisualStudio.Ultimate
        9/26/2015 6:48:04 PM - Version : [10.0]
        9/26/2015 6:48:04 PM - Microsoft.VisualStudio.Ultimate
        9/26/2015 6:48:04 PM - Version : [11.0]
        9/26/2015 6:48:04 PM - Microsoft.VisualStudio.Premium
        9/26/2015 6:48:04 PM - Version : [10.0]
        9/26/2015 6:48:04 PM - Microsoft.VisualStudio.Premium
        9/26/2015 6:48:04 PM - Version : [11.0]
        9/26/2015 6:48:04 PM - Microsoft.VisualStudio.Pro
        9/26/2015 6:48:04 PM - Version : [10.0]
        9/26/2015 6:48:04 PM - Microsoft.VisualStudio.Pro
        9/26/2015 6:48:04 PM - Version : [11.0]

        ابزار دیگری در این مورد نیست؟
        • مجتبی دیناروند در ۱۳۹۴/۰۷/۰۴ ۱۹:۱۳
          خیر ، بر روی ویژوال استودیو 2010 و 2012 پشتبانی میشه.
          • علی یگانه مقدم در ۱۳۹۴/۰۷/۰۴ ۱۹:۵۲
            خب ابزار دیگری که بتونه ریسورس‌ها رو  واکشی کند چطور؟
        • وحید نصیری در ۱۳۹۴/۰۷/۰۴ ۲۰:۱۱
          فایل vsix، یک فایل zip است. درون آن فایل extension.vsixmanifest را ویرایش کنید و supported products آن‌را تکمیل کنید:

          شماره‌ی 12.0 مربوط به VS 2013 هست و شماره‌ی 14.0 مربوط به VS 2015.
  • علی حق جو در ۱۳۹۲/۰۱/۳۱ ۱۶:۱۸
    با سلام.
    من پوشه ای با عنوان SiteContent در root پروژه دارم. چگونه می‌توانم از طریق T4MVC به آن دسترسی داشته باشم. درحالت عادی وقتی Links را تایپ میکنم فقط منابع را برای پوشه Content و Scripts شناسایی میکند. باتشکر.
    • وحید نصیری در ۱۳۹۲/۰۱/۳۱ ۱۷:۳۹
      مراجعه کنید به راهنمای مفصل آن. نقل قولی از آن:
      Use StaticFilesFolders to tweak the list of folders from which links are generated
      
      <!-- Folders containing static files for which links are generated (e.g. Links.Scripts.Map_js) -->
      <StaticFilesFolders>
          <FileFolder>Scripts</FileFolder>
          <FileFolder>Content</FileFolder>
      </StaticFilesFolders>
  • مهمان در ۱۳۹۲/۰۴/۱۵ ۱۹:۴۶
    با سلام بنده  داخل پروژه ام از t4mvc  استفاده کردم امروز صبح یک partialview اضافه کردم وقتی روی T4MVC.tt راست کلیک کردم و run custom tool را زدم با خطای :


    Error1Running transformation: System.ArgumentException: The file 'T4MVC.tt' is not open.
       at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
       at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
       at Microsoft.VisualStudio.NativeMethods.ThrowOnFailure(Int32 hr, Int32[] expectedHRFailure)
       at Microsoft.VisualStudio.Shell.RunningDocumentTable.FindDocument(String moniker, IVsHierarchy& hierarchy, UInt32& itemid, UInt32& docCookie)
       at Microsoft.XmlEditor.XmlHelper.GetCanonicalNameWithoutView(IServiceProvider site, String fname)
       at Microsoft.XmlEditor.XmlFileInfoService.RenameOrRemoveCacheFileInfo(String fname)
       at Microsoft.XmlEditor.Package.GetOrCreateFileInfo(String fname, String text)
       at Microsoft.XmlEditor.Package.GetOrCreateFileInfo(String fname, IVsTextLines buffer)
       at Microsoft.XmlEditor.FactoryBase.GetDesignerFactory(String monikerTheFileOnDisk, String monikerToUse, IVsTextLines existingBuffer, Guid logicalView)
       at Microsoft.XmlEditor.Chooser.ChooseEditorFactory(String pszMkDocument, IVsHierarchy pHier, UInt32 itemid, IntPtr punkDocDataExisting, Guid& rguidLogicalView, Guid& pguidEditorTypeActual, Guid& pguidLogicalViewActual)
       at EnvDTE.ProjectItem.Open(String ViewKind)
       at Microsoft.VisualStudio.TextTemplating07E2522337018FCFC0AADC805726764A22758F53E05D3026845E2AA5E0226E57B77322743831B8A035E8EFE18D3CC1F808985A2958CCE46A2085D3520D2EC605.GeneratedTextTransformation.XmlSettings.Init(ITextTemplatingEngineHost host) in e:\Project\GRP\GRP.Web\T4MVC.tt:line 2120
       at Microsoft.VisualStudio.TextTemplating07E2522337018FCFC0AADC805726764A22758F53E05D3026845E2AA5E0226E57B77322743831B8A035E8EFE18D3CC1F808985A2958CCE46A2085D3520D2EC605.GeneratedTextTransformation.XmlSettings.Load[T](ITextTemplatingEngineHost host) in e:\Project\GRP\GRP.Web\T4MVC.tt:line 2093
       at Microsoft.VisualStudio.TextTemplating07E2522337018FCFC0AADC805726764A22758F53E05D3026845E2AA5E0226E57B77322743831B8A035E8EFE18D3CC1F808985A2958CCE46A2085D3520D2EC605.GeneratedTextTransformation.MvcSettings.Load(ITextTemplatingEngineHost host) in e:\Project\GRP\GRP.Web\T4MVC.tt:line 1786
       at Microsoft.VisualStudio.TextTemplating07E2522337018FCFC0AADC805726764A22758F53E05D3026845E2AA5E0226E57B77322743831B8A035E8EFE18D3CC1F808985A2958CCE46A2085D3520D2EC605.GeneratedTextTransformation.TransformText() in e:\Project\GRP\GRP.Web\T4MVC.tt:line 39e:\Project\GRP\GRP.Web\T4MVC.tt21201GRP.Web
    مواجه شدم t4mvc را uninstall کردم دوباره نصب کردم موقع generate  دوباره همین پیغام را میدم. لطفا یکی به من کمک کنه.ممنون
  • محمد آزاد در ۱۳۹۲/۰۴/۱۶ ۱۴:۵۹
    یکی از مشکلاتی که من با این ابزار خوب دارم اینه که بعد از هر تغییر در کنترلر‌ها یا اضافه کردن یک کنترلر جدید حتما بایدrun custom tool   اجرا کنم...می خواستم بدنم آیا راهی نیست که بشه این قضیه خودکار انجام بشه ؟ (مثلا بعد از Build پروژه)
    • وحید نصیری در ۱۳۹۲/۰۴/۱۶ ۱۶:۲۷
      add-in  برای اینکار هست. ولی به شخصه ترجیح می‌دهم خودکار اجرا نشود؛ چون در یک پروژه با تعداد فایل‌های بالا، پردازش آن مدتی زمان می‌برد و ممکن است در این بین، تغییرات انجام شده شامل تغییری در تعداد یا نام فایل‌ها یا اکشن متدها نباشند. تغییرات در سایر لایه‌ها باشند. در این حالت اصلا ضرورتی ندارد که با هر Build یکبار اینکار تکرار شود.
  • کامی در ۱۳۹۲/۰۵/۲۶ ۰:۱۰
    سلام؛ من از T4  استفاده کردم ولی وقتی پروژه رو publish  میکنم و اون رو روی هاست upload  می کنم t4  رو نمی‌شناسه و تمام مواردی رو که از t4  استفاده کردم رو error میده. آیا باید تنظیمات خاصی انجام بدم که این مشکل رو حل کنم؟ لطفا راهنمایی کنید
    • وحید نصیری در ۱۳۹۲/۰۵/۲۶ ۰:۲۶
      کل کاری که T4MVC انجام می‌ده، اضافه کردن یک سری متد الحاقی جدید است به پروژه به علاوه تبدیل یک سری از مسیرها به معادل‌های constant آن و اندکی تغییر در متدهای کنترلرها برای سازگار شدن با متدهای الحاقی جدید. بنابراین حاصل این عملیات به صورت کامپایل شده در پوشه bin پروژه شما موجود است. این پوشه را کلا بر روی سرور ارسال کنید.
  • رضا منصوری در ۱۳۹۲/۰۸/۲۲ ۰:۴۸
    «من قبلا چطور با ASP.NET MVC کار می‌کردم؟!» 
  • رویا حیدری در ۱۳۹۳/۰۳/۰۳ ۱۷:۱۶
    من در پروژم Controller ها رو در یک لایه و View‌ها را در لایه‌ی دیگری دارم. از T4MVC هم در لایه‌ی Controller استفاده کردم. اما بعد از زدن Run Custom Tool مسیرهایی که منتهی به یک view میشه ساخته نمیشه و Error میده! (آنهایی که RedirectToAction هستند به درستی ساخته می‌شه)

    VDoc.Web.Controllers.TopicController.ViewsClass' does not contain a definition for '_Edit' and no extension method '_Edit' accepting a first argument of type 'VDoc.Web.Controllers.TopicController.ViewsClass' could be found (are you missing a using directive or an assembly reference?)

    آیا برای استفاده از T4 در لایه‌های مختلف باید کار خاصی انجام بدم؟
    • وحید نصیری در ۱۳۹۳/۰۳/۰۳ ۱۸:۴
      - ViewsRootFolder داخل فایل تنظیمات آن، قابل تنظیم است.
      - همچنین بحثی هم در اینجا شده با یک چنین راه حلی
  • مهمان در ۱۳۹۳/۰۸/۲۸ ۱۵:۴۳
    با سلام
    T4MVC یکسری تغییرات در برنامه ما ایجاد می‌کنه از جمله مثلا یک کانستراکتور برای کنترلر Home  اضافه می‌کنه و من چگونه باید کدی مثل کد زیر رو داخل کنترل ام بنویسیم که خطای تکراری نگیره؟
    private readonly ICacheService _cacheService;
    public HomeController() : this(MvcApplication.CacheService)
    {            
    }
    public HomeController(ICacheService cacheService)
    {
          _cacheService = cacheService;
    }
    • وحید نصیری در ۱۳۹۳/۰۸/۲۸ ۱۸:۱۳
      - روش «poor man's dependency injection » اساسا زیر سؤال هست. روش صحیح تزریق وابستگی‌ها در برنامه‌های ASP.NET MVC در اینجا بحث شده‌است.
      - اگر نمی‌خواهید T4MVC سازنده‌ی پیش فرض ایجاد کند، فایل‌های T4 آن‌را ویرایش کنید.
  • علی یگانه مقدم در ۱۳۹۴/۰۲/۲۶ ۱۹:۲۰
    گاهی اوقات روی خط زیر
    SmObjectFactory.Container.GetInstance(controllerType) as Controller;


    با خطای زیر روبرو میشم:
    http://localhost:16926/T4MVC_System_Web_Mvc_ActionResult
    • وحید نصیری در ۱۳۹۴/۰۲/۲۶ ۱۹:۴۲
      بررسی کنید چه آدرسی درخواست شده و آیا موجود است یا خیر؟
              protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
              {
                  if (controllerType == null && requestContext.HttpContext.Request.Url != null)
                      throw new InvalidOperationException(string.Format("Page not found: {0}",
                          requestContext.HttpContext.Request.Url.AbsoluteUri.ToString(CultureInfo.InvariantCulture)));
                  return SmObjectFactory.Container.GetInstance(controllerType) as Controller;
              }
      • علی یگانه مقدم در ۱۳۹۴/۰۲/۲۶ ۱۹:۵۸
        در Url‌ها که همین آدرس بالا رو زده بود ولی از اونجا که شما گفتید آدرس درخواستی، قسمت‌های مختلف Layout رو چک کردم و خطا رو پیدا کردم و لینک رو صحیح ارسال نکرده بودم که اصلاح شد
        متشکرم
      • علی یگانه مقدم در ۱۳۹۴/۰۲/۲۶ ۲۰:۹
        یک مورد اینکه من پروژه رو در حال اجرا برای مدتی رها کردم
        وقتی برگشتم با خطای زیر مواجه شدم
        http://localhost:16926/cf05761417b442f293d1cd9f0bffd789/arterySignalR/ping?requestUrl=http%3A%2F%2Flocalhost%3A16926%2F&browserName=Firefox&_=1431790628217
        این خطا توسط کدی که گفتید گزارش شده
        page not found ...
        • سیروان عفیفی در ۱۳۹۴/۰۲/۲۷ ۸:۲۹
          این خط رو به فایل RouteConfig.cs اضافه کنید:
          routes.IgnoreRoute("{*browserlink}", new { browserlink = @".*/arterySignalR/ping" });

  • علی یگانه مقدم در ۱۳۹۴/۰۷/۰۴ ۱۸:۵۹
    این ابزار جهت اجرای خودکار RunCustomTool به کار می‌رود
  • علی یگانه مقدم در ۱۳۹۴/۰۷/۱۷ ۲۱:۷
    این ابزار هم برای ساخت خودکار T4mvc به طور اختصاصی طراحی شده
  • علی یگانه مقدم در ۱۳۹۵/۰۷/۲۸ ۳:۱۹
    در صورتی که پارامتری از اکشن متدها بخواهید در نسخه‌های پیشین سی شارپ قابلیت نال شدن داشته باشه، میشه از روش گفته شده در اینجا برای آدرس دهی استفاده کرد.
  • سامان احمدی در ۱۳۹۷/۱۱/۲۷ ۱۴:۲
    سلام؛ من در Bundle‌ها از این روش استفاده می‌کنم:
    bundles.Add(new StyleBundle("~/Content/Css").Include(
                        //Bootstrap 3.3.7
                        //"~/content/application/AdminLTE/dist/css/bootstrap-theme.css",
                        Links.Content.application.AdminLTE.dist.css.bootstrap_theme_css
                        .
                        .
                        .
                    ));
    هنگامی که می‌خوام از T4MVC برای آدرس دهی Bundle‌ها استفاده کنم با خطای زیر مواجه می‌شم؟

    خطا به این خاطر هست که آدرس دهی با (/~) شروع نمی‌شود. آیا باید برای Bundle‌ها از همان آدرس دهی عادی استفاده کرد؟
    • وحید نصیری در ۱۳۹۷/۱۱/۲۷ ۱۴:۲۹
      اگر رشته‌ای را که تولید کرده مورد تائید است، یک "~" به ابتدای آن + کنید (در نهایت یک رشته‌ی #C که بیشتر نیست) یا سطر VirtualPathUtility.ToAbsolute را حذف کنید.
  • وحید نصیری در ۱۳۹۹/۱۲/۰۷ ۸:۴