Как развертывается Asp Net Core
Asp Net Core - это как Проктор энд Гэмбл т.е. два в одном флаконе: фрэймворк и Web-сервер, а само веб приложение имеет вид консольного приложения, развертываемого через IWebHost с предварительной настройкой сервисов, миддлваре и т.п. Все относительно просто в случаях, когда разработка идет на машине с установленной Visual Studio. Для запуска веб приложений в Asp Net Core используется веб-сервер Kestrel. И, казалось, бы нет никаких сложностей для запуска веб-приложения на IIS. Но, столкнувшись с такой задачей я набил кучу шишек, о чем и хочу рассказать в этом посте.
Создание Net Core пула и подключение модуля AspNetCore
Как известно в IIS имеются пулы, которые, используются во-первых, для изоляции одних приложений от других, а, во-вторых, для простоты настройки однотипных приложений. И если запустить настройку пула приложения на IIS, то можно увидеть, что Net Core в нем напрочь отсутствует (предварительно я установил Net Core Sdk), всего 3 варианта таргет фрэймворка для пула: 2.0, 4.0 и неуправляемый код. Для Asp Net Core нужно выбрать последний.
Но и это еще не все: выше я писал, что Asp Net Core веб-приложение развертывается на веб-сервере Kestrel, а как же тогда подключить IIS, дело в том, что IIS подключается как прокси: все запросы, пришедшие на HTTP порт приложения, развернутого на IIS, маршрутизируются через модуль AspNetCore в Kestrel, обрабатываются приложением, а ответ направляется в IIS. За это взаимодействие отвечает AspNetCore модуль, который необходимо установить в IIS отдельно от Net Core Sdk!!!! (https://docs.microsoft.com/ru-ru/aspnet/core/fundamentals/servers/aspnet-core-module). После инсталляции в списке модулей должна быть эта строка (предварительно (сначала) необходимо установить VS2015 C++ Redistributable Package):
Кроме всего этого в Web.config необходимо указать использование этого модуля и путь к целевой сборке (приложению), например, мое приложение - E3App.Web.dll и Web.Config имеет следующий вид:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore
processPath="dotnet"
arguments=".\E3App.Web.dll"
stdoutLogEnabled="true"
stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore
processPath="dotnet"
arguments=".\E3App.Web.dll"
stdoutLogEnabled="true"
stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
Этот файл, как и многое другое, генерируется в процессе публикации проекта (Publish), однако, я не думал, что он играет роль, т.к. он в явном виде отсутствует в проекте. Но он очень важный! Особенно атрибут stdoutLogEnabled, по умолчанию этот атрибут имеет значение false, что для разработчика означает следующее: любое исключение произошедшее при запуске приложение будет "проглочено", а в качестве результата мы увидим на странице что-то вроде: "Оопс, а что-то сломалось". Включаем и идем дальше.
Старая добрая БД и EF Core
Следующим приколом на пути к запуску приложения стала сама БД: я поставил Sql Server 2012, предполагая, что EF нет дела до версии SQL сервера, но не тут-то было (хотя мне казалось, что ву меня был рабочий проект под 12 версию сервера). Текст исключения в стандартном выводе мне ничего не говорил о том, почему у меня ломается приложение при старте. Однако, подозрительным было то, что при отладке приложение стартовало без каких-либо проблем, а на IIS - ломалось. Тогда я решил заменить 12 SQL Server на SQL Server 2016 и вуаля, текст ошибки стал другим. Теперь приложение жаловалось на то, что нет прав на создании новой БД при подключении к таблице master (тут все тривиально, нужна роль sysadmin для пользователя под которым выполняется подключение). Хотелось бы сделать ремарку о том, что EF работает с БД по парадигме Code First (сам создает скрипт для создания БД, всех таблиц и связей между ними). Тут тоже пришлось помучиться, т.к. можно сделать строку подключения с полным указаниям логина и пароля (в appsettings.json):
"ConnectionStrings": {
"Storage": "Server=DEV-HOST\\SQLEXPRESS;Database=e3app;
User ID=developer;Password=123;MultipleActiveResultSets=true"
}
Но это не всегда удобно использовать заранее созданную учетную запись, иногда необходимо использовать Windows-аутентификацию, казалось бы просто выдал права (роль sysadmin) своей Windows учетной записи:
"ConnectionStrings": {
"Storage": "Server=DEV-HOST\\SQLEXPRESS;Database=e3app;
Integrated Security=SSPI;MultipleActiveResultSets=true"
}
но нет в БД, оказывается, EF лезет через другую учетку. Экспериментальным способом включая данную роль у логинов по очереди, определил, что это учетная запись BULTIN\Users (а если посмотреть, кто создал БД - IIS APPPOOL/AspNetCore).
Заключение
Казалось бы тривиальная задача, но она отняла у меня кучу времени, я убил, наверное, пару дней чистого времени пытаясь понять, что происходит и почему все работает не так, как нужно. Надеюсь, что этот пост поможет тем, кто столкнулся с такой же проблемой: деплоя на IIS Asp Net Core веб приложения.
Как обновлять такое приложение? При попытке заменить файлы в папке развертывания, они оказываются заблокироаанными IIS
ОтветитьУдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьДля этого необходимо остановить приложение в списке приложений IIS, после этого можно заменить файлы и запустить приложение. Наш блог переехал сюда - https://zen.yandex.ru/id/5f9bbb6eb5987b74e7014a6f
ОтветитьУдалить