Обновляем приложение с MVC 2 до MVC 3
- modified:
- reading: 6 minutes
Уже год мой сайт (блог) живет на самописном движке, который я сделал при помощи ASP.NET MVC 2. Конечно же я мог пользоваться бесплатными площадками для блогов, но мне пока интересно развиваться по многим направлениям. И если моя основная специальность сейчас Silverlight/WPF, то я все равно стараюсь не забыть про старый добрый веб, без него никуда в нынешнее время. Ну и нужно быть на гребне волны, потому я и решил что пора бы проапгрейдить свой сайт с MVC2 до MVC3. Зачем? А просто, чтобы было. Чтобы в будущем, когда захочется что-то допилить или доделать, а у меня уже была последняя версия, и я мог использовать последние фичи технологии.
Обновляем проект с MVC2 до MVC3
Первое задание, которое нужно выполнить для обновления на новую версию – это обновить сам проект и библиотеки. Если еще сама платформа не скачена, тогда идем на официальный сайт ASP.NET MVC и качаем третью версию отсюда http://www.asp.net/mvc/mvc3. Дальше нам нужно просто поменять references с библиотек версии 2.0 на версию 3.0. Делается это очень просто, качаем ASP.NET MVC 3 Application Upgrader (все бы производители фреймворков так заботились о разработчиках), запускаем, указываем путь до sln файла проекта и ждем результата. Эта тулза так же положит последние версии файлов jQuery фреймворка вам на сайт, но так как я использую Google jQuery CDN (чего и вам советую), то я просто вынес эти файлы из своего проекта и просто поменял ссылку на версию jQuery файла с 1.4.2 на 1.4.4. Еще эта библиотека заменила references во всех моих проектах этого солюшена с MVC 2.0 на MVC 3.0 (и добавила ссылки на две дополнительные библиотеки), как и должна была, а так же обновила web.config файл, а именно добавила в appSettings пару параметров, предназначения которых я пока не знаю:
<add key="ClientValidationEnabled" value="false" />
<add key="UnobtrusiveJavaScriptEnabled" value="false" />
Потом разберемся, что это значит.
В web.config прописала ссылки на библиотеки (желтым - новое):
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
Добавила пару namespace (чтобы на страницах можно было использовать без подключения этих namespace):
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
Ну и конечно, прописала asssemblyBinding для того, чтобы не было конфликтов версий (в случае, если используются какие-то библиотеки, которые были скомпилированы с версией MVC 2.0):
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Так же был подправлен файл web.config, который находится в папке Views (добавился обработчик Razor, ну и поменяли версию библиотек со второй на третью).
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web>
<httpHandlers>
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler" />
</httpHandlers>
<pages validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<controls>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="BlockViewHandler" />
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
</configuration>
Можем скомпилировать наше приложение и запустить. У меня так все заработало с первого раза. Если не компилируется или не запускается, то читаем документацию по MVC 3 об изменениях.
Выкладываем на хостинг
Очевидно, что сейчас мало хостеров поддерживают ASP.NET MVC 3, потому нужно вместе со своим веб-приложением так же поместить в bin директорию библиотеки MVC 3. Как оказалось выложить просто 3 новых библиотеки System.Web.Mvc, System.Web.Helpers и System.Web.WebPages в bin папку к хостеру не достаточно. Эти библиотеки тянут за собой еще список других. Я не стал разбираться с тем, чтобы понять какой именно список библиотек мне нужен, а просто скопировал в bin к хостеру все из папки:
c:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies\
Предполагаю, что список необходимых библиотек такой:
- Microsoft.Web.Infrastructure.dll
- System.Web.Helpers.dll
- System.Web.Razor.dll
- System.Web.WebPages.dll
- System.Web.WebPages.Deployment.dll
- System.Web.WebPages.Razor.dll
Проблема с MembershipProvider
При запуске приложения у хостера получил ошибку (у меня используется свой MembershipProvider, какой именно - расскажу потом)
This method cannot be called during the application's pre-start initialization stage.
Лечится очень просто, идем на статью ASP.NET MVC 3 Release Notes, находим Known Issues, добавляем:
<appSettings>
<add key="enableSimpleMembership" value="false" />
<add key="autoFormsAuthentication" value="false" />
</appSettings>
Проблема решена.
Обновление представлений с ASPX на Razor
Ну раз переходим на новый фреймворк, то нужно бы использовать новый View Engine под названием Razor, так как с виду он действительно немного удобнее чем ASPX. Когда я обновлял свое приложение, я пытался найти какую-нибудь утилиту для конвертации, нашел я только проект http://aspx2razor.codeplex.com/, у которого до сих пор нет готовой сборки. Я попытался собрать это творение, но там какие-то непонятные reference на библиотеку Antlr3.Runtime.dll, я ее ни разу вроде не использовал, за минуту я не нашел, где мне ее скачать можно, тогда и написал в твиттере:
Выкладывайте в SVN все библиотеки, которые вы скачивали, даже из toolkit! Не все их ставят, и версии бывают разные!
Ну действительно, если уж публикуете код, то делайте его так, чтобы любой 5 летний ребенок мог просто запустить VS и скомпилировать проект, а не вот так вот:
В общем, я просто забил и не стал дальше мучиться с этим проектом, не думаю, что там выйдет что-то хорошее.
Переводил я проект с версии 2.0 на 3.0 уже как пару недель назад, и вот недавно свершилось чудо, Telerik опубликовал код своей библиотеки, которая умеет переводить ASPX страницы в Razor. Для этого идем скачивать исходный код библиотеки с GitHub, компилируем и запускаем проект aspx2razor (консольное приложение). Я его, правда, немного подпилил, чтобы была возможность сразу запустить эту тулзу по всем папкам, и сложить их так же по отдельным папкам, как они и были в исходнике, для этого я поправил строки с 64 по 77 файла Program.cs:
foreach (var file in Directory.GetFiles(inputDirectory, inputFilter, SearchOption.AllDirectories))
{ Console.Write("Converting {0}... ", Path.GetFileName(file));
var webFormsPageSource = File.ReadAllText(file, Encoding.UTF8);
var webFormsDocument = Parser.Parse(webFormsPageSource);
var razorDom = Converter.Convert(webFormsDocument);
var razorPage = Renderer.Render(razorDom);
string directoryName = Path.GetDirectoryName(file).Substring(inputDirectory.Length + 1);
string outDirectory = Path.Combine(outputDirectory, directoryName);
if (!Directory.Exists(outDirectory))
Directory.CreateDirectory(outDirectory);
var outputFile = Path.Combine(outDirectory, Path.GetFileNameWithoutExtension(file) + ".cshtml");
File.WriteAllText(outputFile, razorPage, Encoding.UTF8); Console.WriteLine("done");
}
Код не будет работать, если будут не абсолютные директории и еще может в паре случаях, но вот на таком примере работает отлично:
aspx2razor.exe c:\Projects\PersonalWeb\PersonalWeb\Views\*.aspx c:\Projects\PersonalWeb\Razor\Views\
Он нашел все файлы с расширением aspx и сделал cshtml файлы, причем все разложил так же по папкам, как и было первоначально. Конвертация Master страниц не поддерживается, потому пока не обновил свой блог на Razor (в итоге обновил), с этим отдельно буду разбираться, как там Master страницы при помощи его описываются.
Если существуют еще проблемы и решения
Если существуют еще проблемы или решения, с которыми вы не можете разобраться при обновлении, то можете попробовать спросить меня, постараюсь помочь. А если знаете еще какие-то стандартные проблемы или решения, которые стоит предпринять при обновлении, то поделитесь, пожалуйста, советом-комментарием.