Подготовка приложения для публикации
Мы собираемся развернуть приложение SportsStore, которое создали в первой части этой книги. Мы выбрали SportsStore, потому что оно использует базу данных, а настройка и проверка работы базы данных является важной частью любого процесса развертывания.
Подсказка
Когда мы говорим о развертывании приложения SportsStore, мы имеем в виду проект
SportsStore.WebUI
. Нам не нужно отдельно развертывать два других проекта, которые мы создали вместе с ним. Вывод проектаSportsStore.Domain
включен в проект WebUI, а модульные тесты из проектаSportsStore.UnitTests
не потребуются в рабочем приложении.
Выявляем ошибки представлений
Как мы уже объяснили в главе 18, представления Razor компилируются сервером при запуске приложения, а не когда мы создаем проект в Visual Studio. Как правило, единственный способ обнаружить ошибки компилятора - это систематически обращаться к каждому действию и визуализировать каждое представление. Это утомительная и не всегда успешная техника, особенно если в зависимости от состояния модели визуализируются разные представления.
В проекте можно активировать специальную опцию, которая будет компилировать наши представления и сообщать об ошибках компиляции. Эту функцию нельзя активировать из Visual Studio; откройте файл SportsStore/WebUI/SportsStore.WebUI.csproj
в блокноте. Найдите элемент MvcBuildViews
и измените его значение на true
, как показано в листинге 26-1.
Листинг 26-1: Активируем опцию MvcBuildViews
...
<PropertyGroup>
... other settings omitted ...
<MvcBuildViews>true</MvcBuildViews>
... other settings omitted ...
</PropertyGroup>
...
Сохраните изменения и вернитесь в Visual Studio, которая предложит вам перезагрузить проект. Теперь, когда вы скомпилируете проект, Visual Studio скомпилирует файлы представлений и сообщит об ошибках. Чтобы продемонстрировать, как это работает, мы добавили ошибку в представление /Views/Product/List.cshtml
, как показано в листинге 26-2.
Листинг 26-2: Добавляем ошибку в файл представления
@model SportsStore.WebUI.Models.ProductsListViewModel
@{
ViewBag.Title = "Products";
}
@Model.NotARealProperty
@foreach (var p in Model.Products)
{
Html.RenderPartial("ProductSummary", p);
}
<div class="pager">
@Html.PageLinks(Model.PagingInfo,
x => Url.Action("List", new { page = x, category = Model.CurrentCategory }))
</div>
Как правило, наша попытка визуализировать свойство не будет отображаться, пока мы не запустим приложение и перейдем по ссылке, которая визуализирует представление List.cshtml
. Но, когда опция MvcBuildViews
активирована, мы увидим сообщение об ошибке во время работы над проектом, как показано на рисунке 26-1.
Рисунок 26-1: Ошибка компилятора из-за проблем в представлении

Эта техника позволяет обнаруживать только ошибки компилятора. Она не видит логических ошибок и не может заменить полноценное тестирование, но в качестве предосторожности ее полезно применять перед развертыванием приложения. Мы не сможем развернуть приложение с ошибкой в представлении, так что мы восстановили его до прежнего состояния, как показано в листинге 26-3.
Листинг 26-3: Удаляем ошибку из представления List.cshtml
@model SportsStore.WebUI.Models.ProductsListViewModel
@{
ViewBag.Title = "Products";
}
@foreach (var p in Model.Products)
{
Html.RenderPartial("ProductSummary", p);
}
<div class="pager">
@Html.PageLinks(Model.PagingInfo, x => Url.Action("List",
new { page = x, category = Model.CurrentCategory }))
</div>
Подсказка
Вы можете увидеть сообщение о том, что будет ошибкой будет использовать секцию, которая зарегистрирована как
allowDefinition='MachineToApplication'
вне уровня приложения. Это ошибка, которая возникает после развертывания приложения. Мы нашли только одно надежное решение для этой проблемы: очистить проект в режиме отладки, затем в режиме релиза, а затем построить приложение в режиме отладки.
Дезактивируем режим отладки
Одним из наиболее важных элементов в файле Web.config
, на который вы должны обратить внимание при развертывании приложения, является compilation
, как показано в листинге 26-4.
Листинг 26-4: Элементcompilation
вWeb.config
<system.web>
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880">
Когда атрибут debug
содержит значение true
, поведение компилятора и приложения будет ориентировано на процесс разработки. Например, компилятор будет выполнять следующие действия:
- Опускает некоторые процедуры оптимизации кода, чтобы он мог построчно выполнять код.
- Компилирует каждое представление по запросу, вместо компиляции всех представлений в один прием.
- Отключает лимит времени запроса, чтобы мы могли провести много времени в отладчике.
- Ограничивает способы кэширования контента браузерами.
Кроме того, если вы использовали связки для группировки одновременно и CSS, и JavaScript файлов, браузер получит инструкцию загружать каждый файл по отдельности, и он не получит минимизированные версии этих файлов. (Мы рассмотрели связки в главе 24).
Все эти функции полезны при разработке приложения, но они станут помехой при развертывании. Как вы можете догадаться, решение заключается в изменении значения атрибута debug
на false
:
<compilation debug="false" targetFramework="4.5" />
Чаще всего вам не придется выполнять это изменение перед развертыванием, поскольку изменить конфигурацию приложения можно в утилитах развертывания Visual Studio, или значение в файле Web.config
будет переопределено конфигурацией сервера приложений IIS.
Тем не менее, если поведение приложения меняется, когда атрибут debug
имеет значение false
, то после отключения режима отладки необходимо запустить программу тестирования до того, как выполнять развертывание. Вы должны убедиться, что ваши представления визуализируются так, как вы и планировали, и все связки, использующие маркер {version}
, указывают на файлы, которые существуют и доступны на сервере.
Удаляем неиспользуемые строки подключения
Чаще всего в процессе развертывания ошибки возникают при настройке соединения с базой данных. Как мы знаем из своего опыта, большинство проблем возникают из-за информации о неиспользуемых базах данных в файлеWeb.config
.
Зная, что базы данных проблематичны, разработчики утилит развертывания пытаются автоматизировать процесс настройки баз данных, но они зациклены на конфигурации по умолчанию, которую добавляет в проект Visual Studio. Чтобы избежать этих проблем, можно отредактировать файл Web.config
. В листинге 26-5 показаны два варианта настройки соединения для передачи данных в файле Web.config
в проекте SportsStore.WebUI
. Запись, в которой атрибут name
содержит DefaultConnection
, была создана Visual Studio; она помогает запустить новый проект, и мы не используем ее в приложении SportsStore. Другую запись - EFDbContext
- создали и использовали мы, и она потребуется в развернутом проекте.
Листинг 26-5: Строки подключения в файле Web.config
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="DefaultConnection"
providerName="System.Data.SqlClient"
connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-SportsStore.WebUI-20121003232522;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-SportsStore.WebUI-20121003232522.mdf" />
<add name="EFDbContext"
connectionString="Data Source=(localdb)\v11.0;Initial Catalog=SportsStore;Integrated Security=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
Вы можете просто закомментировать ненужные соединения, но мы предпочитаем вносить более определенные изменения, потому что мы провели много часов за отладкой проблем развертывания, возникших из-за информации о неиспользуемых подключениях. В листинге 26-6 показано, как мы отредактировали файл Web.config
, оставив только запись в EFDbContext
.
Листинг 26-6: Удаляем информацию о неиспользуемых подключениях
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</configSections>
<connectionStrings>
<add name="EFDbContext"
connectionString="Data Source=(localdb)\v11.0;Initial Catalog=SportsStore;Integrated Security=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>