در ادامه، مراحل ارتقاء پروژههای قدیمی MVC3 را به ساختار جدید پروژههای MVC4 مرور خواهیم کرد.
1) نصب پیشنیاز
الف) نصب VS 2012
و یا
ب) نصب بسته MVC4 مخصوص VS 2010 (این مورد جهت سرورهای وب نیز توصیه میشود)
پس از نصب باید به این نکته دقت داشت که پوشههای زیر حاوی اسمبلیهای جدید MVC4 هستند و نیازی نیست الزاما این موارد را از NuGet دریافت و نصب کرد:
پس از نصب پیشنیازها
2) نیاز است نوع پروژه ارتقاء یابد
به پوشه پروژه MVC3 خود مراجعه کرده و تمام فایلهای csproj و web.config موجود را با یک ادیتور متنی باز کنید (از خود ویژوال استودیو استفاده نکنید، زیرا نیاز است محتوای فایلهای پروژه نیز دستی ویرایش شوند).
در فایلهای csproj (یا همان فایل پروژه؛ که vbproj هم میتواند باشد) عبارت
را جستجو کرده و با
جایگزین کنید. به این ترتیب نوع پروژه به MVC4 تبدیل میشود.
3) به روز رسانی شماره نگارشهای قدیمی
سپس تعاریف اسمبلیهای قدیمی نگارش سه MVC و نگارش یک Razor را یافته (در تمام فایلها، چه فایلهای پروژه و چه تنظیمات):
و اینها را با نگارش چهار MVC و نگارش دو Razor جایگزین کنید:
این کارها را با replace in all open documents توسط notepad plus-plus به سادگی میتوان انجام داد.
4) به روز رسانی مسیرهای قدیمی
به علاوه اگر در پروژههای خود از اسمبلیهای قدیمی به صورت مستقیم استفاده شده:
اینها را یافته و به نگارش MVC4 و Razor2 تغییر دهید:
5) به روز رسانی قسمت appSettings فایلهای کانفیگ
در کلیه فایلهای web.config برنامه، webpages:Version را یافته و شماره نگارش آنرا از یک به دو تغییر دهید:
همچنین یک سطر جدید PreserveLoginUrl را نیز مطابق تنظیم فوق اضافه نمائید.
6) رسیدگی به وضعیت اسمبلیهای شرکتهای ثالث
ممکن است در این زمان از تعدادی کامپوننت و اسمبلی MVC3 تهیه شده توسط شرکتهای ثالث نیز استفاده نمائید. برای اینکه این اسمبلیها را وادار نمائید تا از نگارشهای MVC4 و Razor2 استفاده کنند، نیاز است bindingRedirectهای زیر را به فایلهای web.config برنامه اضافه کنید (در فایل کانفیگ ریشه پروژه):
اکنون فایل solution را در VS.NET گشوده و یکبار گزینه rebuild را انتخاب کنید تا پروژه مجددا بر اساس اسمبلیهای جدید معرفی شده ساخته شود.
7) استفاده از NuGet برای به روز رسانی بستههای نصب شده
یک سری از بستههای تشکیل دهنده MVC3 مانند موارد ذیل نیز به روز شدهاند که لازم است از طریق NuGet دریافت و جایگزین شوند:
Unobtrusive.Ajax.2
Unobtrusive.Validation.2
Web.Optimization.1.0.0
و ....
برای اینکار در solution explorer روی references کلیک راست کرده و گزینه Manage NuGet Packages را انتخاب کنید. در صفحه باز شده گزینه updates/all را انتخاب کرده و مواردی را که لیست میکند به روز نمائید (شامل جی کوئری، EF، structureMap و غیره خواهد بود).
8) اضافه کردن یک فضای نام جدید
بسته Web Optimization را از طریق NuGet دریافت کنید (برای یافتن آن bundling را جستجو کنید؛ نام کامل آن Microsoft ASP.NET Web Optimization Framework 1.0.0 است). این مورد به همراه پوشه MVC4 نیست و باید از طریق NuGet دریافت و نصب شود. (البته پروژههای جدید MVC4 شامل این مورد هستند)
در فایل وب کانفیگ، فضای نام System.Web.Optimization را نیز اضافه نمائید:
پس از ارتقاء
اولین مشکلی که مشاهده شد:
بعد از rebuild به مقدار پارامتر salt که به نحو زیر در MVC3 تعریف شده بود، ایراد خواهد گرفت:
Salt را در MVC4 منسوخ شده معرفی کردهاند: (^)
علت هم این است که salt را اینبار به نحو صحیحی خودشان در پشت صحنه تولید و اعمال میکنند. بنابراین این یک مورد را کلا از کدهای خود حذف کنید که نیازی نیست.
مشکل بعدی:
در EF 5 جای یک سری از کلاسها تغییر کرده. مثلا ویژگیهای ForeignKey، ComplexType و ... به فضای نام System.ComponentModel.DataAnnotations.Schema منتقل شدهاند. در همین حد تغییر جهت کامپایل مجدد کدها کفایت میکند.
همچنین فایلهای پروژه موجود را باز کرده و EntityFramework, Version=4.1.0.0 را جستجو کنید. نگارش جدید 4.4.0.0 است که باید اصلاح شود (این موارد را بهتر است توسط یک ادیتور معمولی خارج از VS.NET ویرایش کنید).
در زمان نگارش این مطلب EF Mini Profiler با EF 5 سازگار نیست. بنابراین اگر از آن استفاده میکنید نیاز است غیرفعالش کنید.
اولین استفاده از امکانات جدید MVC4:
استفاده از امکانات System.Web.Optimization که ذکر گردید، میتواند اولین تغییر مفید محسوب شود.
برای اینکه با نحوه کار آن بهتر آشنا شوید، یک پروژه جدید MVC4 را در VS.NET (از نوع basic) آغاز کنید. به صورت خودکار یک پوشه جدید را به نام App_Start به ریشه پروژه اضافه میکند. داخل آن فایل مثال BundleConfig قرار دارد. این کلاس در فایل global.asax برنامه نیز ثبت شدهاست. باید دقت داشت در حالت دیباگ (compilation debug=true در وب کانفیگ) تغییر خاصی را ملاحظه نخواهید کرد.
تمام اینها خوب؛ اما من به نحو زیر از این امکان جدید استفاده میکنم:
کلاس BundleConfig فوق را به مجموعه کلاسهای کمکی خود اضافه کنید.
چند نکته مهم در این کلاس وجود دارد:
الف) توسط AsIsBundleOrderer فایلها به همان ترتیبی که به سیستم اضافه میشوند، در حاصل نهایی ظاهر خواهند شد. حالت پیش فرض مرتب سازی، بر اساس حروف الفباء است و ... خصوصا برای اسکریپتهایی که ترتیب معرفی آنها مهم است، مساله ساز خواهد بود.
ب)BundleTable.EnableOptimizations سبب میشود تا حتی در حالت debug نیز فشرده سازی را مشاهده کنید.
ج) متدهای کمکی تعریف شده این امکان را میدهند تا بدون نیاز به کامپایل مجدد پروژه، به سادگی در کدهای Razor بتوانید اسکریپتها را اضافه کنید.
سپس نحوه جایگزینی تعاریف قبلی موجود در فایلهای Razor با سیستم جدید، به نحو زیر است:
پارامتر اول این متدها، سبب تعریف خودکار routing میشود. برای مثال اولین تعریف، آدرس خودکار زیر را تولید میکند:
بنابراین تعریف دقیق آن مهم است. خصوصا اگر فایلهای شما در پوشهها و زیرپوشههای متعددی قرار گرفته نمیتوان تمام آنها را در طی یک مرحله معرفی نمود. هر سطح را باید از طریق یک بار معرفی به سیستم اضافه کرد. مثلا اگر یک زیر پوشه به نام noty دارید (Content/noty)، چون در یک سطح و زیرپوشه مجزا قرار دارد، باید نحوه تعریف آن به صورت زیر باشد:
این مورد خصوصا در مسیریابی تصاویر مرتبط با اسکریپتها و شیوه نامهها مؤثر است؛ وگرنه این تصاویر تعریف شده در فایلهای CSS یافت نخواهند شد (تمام مثالهای موجود در وب با این مساله مشکل دارند و فرض آنها بر این است که کلیه فایلهای خود را در یک پوشه، بدون هیچگونه زیرپوشهای تعریف کردهاید).
پارامترهای بعدی، محل قرارگیری اسکریپتها و CSSهای برنامه هستند و همانطور که عنوان شد اینبار با خیال راحت میتوانید ترتیب معرفی خاصی را مدنظر داشته باشید؛ زیرا توسط AsIsBundleOrderer به صورت پیش فرض لحاظ خواهد شد.
1) نصب پیشنیاز
الف) نصب VS 2012
و یا
ب) نصب بسته MVC4 مخصوص VS 2010 (این مورد جهت سرورهای وب نیز توصیه میشود)
پس از نصب باید به این نکته دقت داشت که پوشههای زیر حاوی اسمبلیهای جدید MVC4 هستند و نیازی نیست الزاما این موارد را از NuGet دریافت و نصب کرد:
C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies
2) نیاز است نوع پروژه ارتقاء یابد
به پوشه پروژه MVC3 خود مراجعه کرده و تمام فایلهای csproj و web.config موجود را با یک ادیتور متنی باز کنید (از خود ویژوال استودیو استفاده نکنید، زیرا نیاز است محتوای فایلهای پروژه نیز دستی ویرایش شوند).
در فایلهای csproj (یا همان فایل پروژه؛ که vbproj هم میتواند باشد) عبارت
{E53F8FEA-EAE0-44A6-8774-FFD645390401}
{E3E379DF-F4C6-4180-9B81-6769533ABE47}
3) به روز رسانی شماره نگارشهای قدیمی
سپس تعاریف اسمبلیهای قدیمی نگارش سه MVC و نگارش یک Razor را یافته (در تمام فایلها، چه فایلهای پروژه و چه تنظیمات):
System.Web.Mvc, Version=3.0.0.0 System.Web.WebPages, Version=1.0.0.0 System.Web.Helpers, Version=1.0.0.0 System.Web.WebPages.Razor, Version=1.0.0.0
System.Web.Mvc, Version=4.0.0.0 System.Web.WebPages, Version=2.0.0.0 System.Web.Helpers, Version=2.0.0.0 System.Web.WebPages.Razor, Version=2.0.0.0
4) به روز رسانی مسیرهای قدیمی
به علاوه اگر در پروژههای خود از اسمبلیهای قدیمی به صورت مستقیم استفاده شده:
C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 3\Assemblies
C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies
5) به روز رسانی قسمت appSettings فایلهای کانفیگ
در کلیه فایلهای web.config برنامه، webpages:Version را یافته و شماره نگارش آنرا از یک به دو تغییر دهید:
<appSettings> <add key="webpages:Version" value="2.0.0.0" /> <add key="PreserveLoginUrl" value="true" /> </appSettings>
6) رسیدگی به وضعیت اسمبلیهای شرکتهای ثالث
ممکن است در این زمان از تعدادی کامپوننت و اسمبلی MVC3 تهیه شده توسط شرکتهای ثالث نیز استفاده نمائید. برای اینکه این اسمبلیها را وادار نمائید تا از نگارشهای MVC4 و Razor2 استفاده کنند، نیاز است bindingRedirectهای زیر را به فایلهای web.config برنامه اضافه کنید (در فایل کانفیگ ریشه پروژه):
<configuration> <!--... elements deleted for clarity ...--> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="4.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
7) استفاده از NuGet برای به روز رسانی بستههای نصب شده
یک سری از بستههای تشکیل دهنده MVC3 مانند موارد ذیل نیز به روز شدهاند که لازم است از طریق NuGet دریافت و جایگزین شوند:
Unobtrusive.Ajax.2
Unobtrusive.Validation.2
Web.Optimization.1.0.0
و ....
برای اینکار در solution explorer روی references کلیک راست کرده و گزینه Manage NuGet Packages را انتخاب کنید. در صفحه باز شده گزینه updates/all را انتخاب کرده و مواردی را که لیست میکند به روز نمائید (شامل جی کوئری، EF، structureMap و غیره خواهد بود).
8) اضافه کردن یک فضای نام جدید
بسته Web Optimization را از طریق NuGet دریافت کنید (برای یافتن آن bundling را جستجو کنید؛ نام کامل آن Microsoft ASP.NET Web Optimization Framework 1.0.0 است). این مورد به همراه پوشه MVC4 نیست و باید از طریق NuGet دریافت و نصب شود. (البته پروژههای جدید MVC4 شامل این مورد هستند)
در فایل وب کانفیگ، فضای نام System.Web.Optimization را نیز اضافه نمائید:
<pages> <namespaces> <add namespace="System.Web.Optimization" /> </namespaces> </pages>
پس از ارتقاء
اولین مشکلی که مشاهده شد:
بعد از rebuild به مقدار پارامتر salt که به نحو زیر در MVC3 تعریف شده بود، ایراد خواهد گرفت:
[ValidateAntiForgeryToken(Salt = "data123")]
علت هم این است که salt را اینبار به نحو صحیحی خودشان در پشت صحنه تولید و اعمال میکنند. بنابراین این یک مورد را کلا از کدهای خود حذف کنید که نیازی نیست.
مشکل بعدی:
در EF 5 جای یک سری از کلاسها تغییر کرده. مثلا ویژگیهای ForeignKey، ComplexType و ... به فضای نام System.ComponentModel.DataAnnotations.Schema منتقل شدهاند. در همین حد تغییر جهت کامپایل مجدد کدها کفایت میکند.
همچنین فایلهای پروژه موجود را باز کرده و EntityFramework, Version=4.1.0.0 را جستجو کنید. نگارش جدید 4.4.0.0 است که باید اصلاح شود (این موارد را بهتر است توسط یک ادیتور معمولی خارج از VS.NET ویرایش کنید).
در زمان نگارش این مطلب EF Mini Profiler با EF 5 سازگار نیست. بنابراین اگر از آن استفاده میکنید نیاز است غیرفعالش کنید.
اولین استفاده از امکانات جدید MVC4:
استفاده از امکانات System.Web.Optimization که ذکر گردید، میتواند اولین تغییر مفید محسوب شود.
برای اینکه با نحوه کار آن بهتر آشنا شوید، یک پروژه جدید MVC4 را در VS.NET (از نوع basic) آغاز کنید. به صورت خودکار یک پوشه جدید را به نام App_Start به ریشه پروژه اضافه میکند. داخل آن فایل مثال BundleConfig قرار دارد. این کلاس در فایل global.asax برنامه نیز ثبت شدهاست. باید دقت داشت در حالت دیباگ (compilation debug=true در وب کانفیگ) تغییر خاصی را ملاحظه نخواهید کرد.
تمام اینها خوب؛ اما من به نحو زیر از این امکان جدید استفاده میکنم:
using System.Collections.Generic; using System.IO; using System.Web; using System.Web.Optimization; namespace Common.WebToolkit { /// <summary> /// A custom bundle orderer (IBundleOrderer) that will ensure bundles are /// included in the order you register them. /// </summary> public class AsIsBundleOrderer : IBundleOrderer { public IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { return files; } } public static class BundleConfig { private static void addBundle(string virtualPath, bool isCss, params string[] files) { BundleTable.EnableOptimizations = true; var existing = BundleTable.Bundles.GetBundleFor(virtualPath); if (existing != null) return; var newBundle = isCss ? new Bundle(virtualPath, new CssMinify()) : new Bundle(virtualPath, new JsMinify()); newBundle.Orderer = new AsIsBundleOrderer(); foreach (var file in files) newBundle.Include(file); BundleTable.Bundles.Add(newBundle); } public static IHtmlString AddScripts(string virtualPath, params string[] files) { addBundle(virtualPath, false, files); return Scripts.Render(virtualPath); } public static IHtmlString AddStyles(string virtualPath, params string[] files) { addBundle(virtualPath, true, files); return Styles.Render(virtualPath); } public static IHtmlString AddScriptUrl(string virtualPath, params string[] files) { addBundle(virtualPath, false, files); return Scripts.Url(virtualPath); } public static IHtmlString AddStyleUrl(string virtualPath, params string[] files) { addBundle(virtualPath, true, files); return Styles.Url(virtualPath); } } }
چند نکته مهم در این کلاس وجود دارد:
الف) توسط AsIsBundleOrderer فایلها به همان ترتیبی که به سیستم اضافه میشوند، در حاصل نهایی ظاهر خواهند شد. حالت پیش فرض مرتب سازی، بر اساس حروف الفباء است و ... خصوصا برای اسکریپتهایی که ترتیب معرفی آنها مهم است، مساله ساز خواهد بود.
ب)BundleTable.EnableOptimizations سبب میشود تا حتی در حالت debug نیز فشرده سازی را مشاهده کنید.
ج) متدهای کمکی تعریف شده این امکان را میدهند تا بدون نیاز به کامپایل مجدد پروژه، به سادگی در کدهای Razor بتوانید اسکریپتها را اضافه کنید.
سپس نحوه جایگزینی تعاریف قبلی موجود در فایلهای Razor با سیستم جدید، به نحو زیر است:
@using Common.WebToolkit <link href="@BundleConfig.AddStyleUrl("~/Content/blueprint/print", "~/Content/blueprint/print.css")" rel="stylesheet" type="text/css" media="print"/> @BundleConfig.AddScripts("~/Scripts/js", "~/Scripts/jquery-1.8.0.min.js", "~/Scripts/jquery.unobtrusive-ajax.min.js", "~/Scripts/jquery.validate.min.js") @BundleConfig.AddStyles("~/Content/css", "~/Content/Site.css", "~/Content/buttons.css")
http://site/Content/blueprint/print?v=hash
@BundleConfig.AddStyles("~/Content/noty/css", "~/Content/noty/jquery.noty.css", "~/Content/noty/noty_theme_default.css")
پارامترهای بعدی، محل قرارگیری اسکریپتها و CSSهای برنامه هستند و همانطور که عنوان شد اینبار با خیال راحت میتوانید ترتیب معرفی خاصی را مدنظر داشته باشید؛ زیرا توسط AsIsBundleOrderer به صورت پیش فرض لحاظ خواهد شد.