Представляем первую из пяти статей, посвященных работе с ASP.NET Core: руководство по развертыванию приложения ASP.NET Core на Nano Server со службами IIS.



Введение


Nano Server — это вариант установки Windows Server 2016, который имеет более компактный размер и более широкие возможности обслуживания и обеспечения безопасности по сравнению с Server Core и полным вариантом установки. Более подробная информация приведена в официальной документации по варианту установки Nano Server. Существует три способа начать с ним работу:

1. Загрузить ISO-файл Windows Server 2016 Technical Preview 5 и создать образ Nano Server.
2. Загрузить Nano Server VHD для разработчиков.
3. Создать виртуальную машину в Azure, используя образ Nano Server из Azure Gallery. Если у вас нет учетной записи Azure, вы можете создать бесплатную учетную запись с 30-дневным пробным периодом.

В данном материале используется заранее созданный Nano Server VHD для разработчиков из Windows Server Technical Preview 5.

Далее вам понадобится созданное и опубликованное 64-битное приложение ASP.NET Core.

Подготовка экземпляра Nano Server


Создайте новую виртуальную машину Hyper-V, используя предварительно загруженный файл VHD. Прежде чем войти в систему, необходимо задать пароль администратора. Для этого нужно нажать клавишу F11 в консоли виртуальной машины.

После создания пароля Nano Server может управляться удаленно при помощи PowerShell.

Удаленное подключение к экземпляру Nano Server при помощи PowerShell


Откройте окно PowerShell с повышенными привилегиями, чтобы добавить удаленный экземпляр Nano Server в список TrustedHosts.

$nanoServerIpAddress = "10.83.181.14"
Set-Item WSMan:\localhost\Client\TrustedHosts "$nanoServerIpAddress" -Concatenate -Force

Примечание: замените переменную $nanoServerIpAddress на используемый IP-адрес.

После добавления экземпляра Nano Server в список TrustedHosts выполните удаленное подключение к нему при помощи PowerShell.

$nanoServerSession = New-PSSession -ComputerName $nanoServerIpAddress -Credential ~\Administrator
Enter-PSSession $nanoServerSession

В случае успешного подключения появится командная строка следующего вида:

[10.83.181.14]: PS C:\Users\Administrator\Documents>

Создание каталога общего доступа


Создайте каталог общего доступа в экземпляре Nano Server, чтобы скопировать в него опубликованное приложение. В удаленном сеансе выполните следующие команды:

mkdir C:\PublishedApps\AspNetCoreSampleForNano
netsh advfirewall firewall set rule group="File and Printer Sharing" new enable=yes
net share AspNetCoreSampleForNano=c:\PublishedApps\AspNetCoreSampleForNano /GRANT:EVERYONE`,FULL

После выполнения указанных команд вы сможете открыть каталог общего доступа, введя адрес \\<nanoserver-ip-address>\AspNetCoreSampleForNano в проводнике на хост-компьютере.

Открытие порта в брандмауэре


Выполните следующие команды в удаленном сеансе, чтобы открыть порт в брандмауэре:

New-NetFirewallRule -Name "AspNet5 IIS" -DisplayName "Allow HTTP on TCP/8000" -Protocol TCP -LocalPort 8000 -Action Allow -Enabled True

Установка IIS


Добавьте поставщика NanoServerPackage, выбрав его в коллекции PowerShell. После установки и импорта поставщика появится возможность устанавливать пакеты Windows.

Выполните следующие команды в PowerShell:

Install-PackageProvider NanoServerPackage
Import-PackageProvider NanoServerPackage
Install-NanoServerPackage -Name Microsoft-NanoServer-Storage-Package
Install-NanoServerPackage -Name Microsoft-NanoServer-IIS-Package

После установки компонента >Microsoft-NanoServer-Storage-Package требуется перезагрузка. Это временная процедура и она не будет нужна в будущем.

Чтобы быстро проверить, корректно ли установлены службы IIS, перейдите по адресу http://<nanoserver-ip-address>/ — должна отобразиться стартовая страница. При установке служб IIS создается веб-сайт по умолчанию под названием Default Web Site, для которого используется порт 80.

Установка модуля ASP.NET Core (ANCM)


Модуль ASP.NET Core — это модуль IIS 7.5+, который отвечает за управление работой прослушивателей (listeners) ASP.NET Core HTTP и передачу запросов к процессам, которыми он управляет. На данный момент установка модуля ASP.NET Core для IIS осуществляется вручную. Потребуется установить пакет .NET Core Windows Server Hosting на устройство с обычной операционной системой (не Nano Server). После установки пакета на компьютер с обычной операционной системой необходимо скопировать следующие файлы в каталог общего доступа, который был создан ранее.

На компьютере с обычной операционной системой (не Nano Server) выполните следующие команды копирования:

copy C:\windows\system32\inetsrv\aspnetcore.dll ``\\<nanoserver-ip-address>\AspNetCoreSampleForNano``
copy C:\windows\system32\inetsrv\config\schema\aspnetcore_schema.xml ``\\<nanoserver-ip-address>\AspNetCoreSampleForNano``

На виртуальной машине Nano Server необходимо скопировать следующие файлы из каталога общего доступа, который был создан ранее, в соответствующее расположение. Выполните следующие команды копирования:

copy C:\PublishedApps\AspNetCoreSampleForNano\aspnetcore.dll C:\windows\system32\inetsrvcopy C:\PublishedApps\AspNetCoreSampleForNano\aspnetcore_schema.xml C:\windows\system32\inetsrv\config\schema

Выполните следующий скрипт в удаленном сеансе:

# Backup existing applicationHost.config
copy C:\Windows\System32\inetsrv\config\applicationHost.config C:\Windows\System32\inetsrv\config\applicationHost_BeforeInstallingANCM.config

Import-Module IISAdministration

# Initialize variables
$aspNetCoreHandlerFilePath="C:\windows\system32\inetsrv\aspnetcore.dll"
Reset-IISServerManager -confirm:$false
$sm = Get-IISServerManager

# Add AppSettings section 
$sm.GetApplicationHostConfiguration().RootSectionGroup.Sections.Add("appSettings")

# Set Allow for handlers section
$appHostconfig = $sm.GetApplicationHostConfiguration()
$section = $appHostconfig.GetSection("system.webServer/handlers")
$section.OverrideMode="Allow"

# Add aspNetCore section to system.webServer
$sectionaspNetCore = $appHostConfig.RootSectionGroup.SectionGroups["system.webServer"].Sections.Add("aspNetCore")
$sectionaspNetCore.OverrideModeDefault = "Allow"
$sm.CommitChanges()

# Configure globalModule
Reset-IISServerManager -confirm:$false
$globalModules = Get-IISConfigSection "system.webServer/globalModules" | Get-IISConfigCollection
New-IISConfigCollectionElement $globalModules -ConfigAttribute @{"name"="AspNetCoreModule";"image"=$aspNetCoreHandlerFilePath}

# Configure module
$modules = Get-IISConfigSection "system.webServer/modules" | Get-IISConfigCollection
New-IISConfigCollectionElement $modules -ConfigAttribute @{"name"="AspNetCoreModule"}

# Backup existing applicationHost.config
copy C:\Windows\System32\inetsrv\config\applicationHost.config C:\Windows\System32\inetsrv\config\applicationHost_AfterInstallingANCM.config

Примечание: удалите файлы aspnetcore.dll и aspnetcore_schema.xml из каталога общего доступа после завершения предыдущего шага.

Установка .NET Core Framework


Если вы опубликовали переносимое приложение, платформа .NET Core должна быть установлена на целевом компьютере. Выполните следующие скрипты в удаленном сеансе Powershell, чтобы установить .NET Framework на виртуальной машине Nano Server:

$SourcePath = "https://go.microsoft.com/fwlink/?LinkID=809115"
$DestinationPath = "C:\dotnet"

$EditionId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'EditionID').EditionId

if (($EditionId -eq "ServerStandardNano") -or
  ($EditionId -eq "ServerDataCenterNano") -or
  ($EditionId -eq "NanoServer") -or
  ($EditionId -eq "ServerTuva")) {

  $TempPath = [System.IO.Path]::GetTempFileName()
  if (($SourcePath -as [System.URI]).AbsoluteURI -ne $null)
  {
    $handler = New-Object System.Net.Http.HttpClientHandler
    $client = New-Object System.Net.Http.HttpClient($handler)
    $client.Timeout = New-Object System.TimeSpan(0, 30, 0)
    $cancelTokenSource = [System.Threading.CancellationTokenSource]::new()
    $responseMsg = $client.GetAsync([System.Uri]::new($SourcePath), $cancelTokenSource.Token)
    $responseMsg.Wait()
    if (!$responseMsg.IsCanceled)
    {
      $response = $responseMsg.Result
      if ($response.IsSuccessStatusCode)
      {
        $downloadedFileStream = [System.IO.FileStream]::new($TempPath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
        $copyStreamOp = $response.Content.CopyToAsync($downloadedFileStream)
        $copyStreamOp.Wait()
        $downloadedFileStream.Close()
        if ($copyStreamOp.Exception -ne $null)
        {
          throw $copyStreamOp.Exception
        }
      }
    }
  }
  else
  {
    throw "Cannot copy from $SourcePath"
  }
  [System.IO.Compression.ZipFile]::ExtractToDirectory($TempPath, $DestinationPath)
  Remove-Item $Temp</code>
Path
}

Публикация приложения


Скопируйте опубликованное приложение в каталог общего доступа. Возможно, потребуется внести изменения в файл web.config, чтобы указать каталог, в который извлечен файл dotnet.exe. Другой способ — скопировать файл dotnet.exe в тот же каталог.

Пример файла web.config в ситуации, когда файл dotnet.exe не скопирован в тот же каталог:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
  <handlers>
   <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
  </handlers>
  <aspNetCore processPath="C:\dotnet\dotnet.exe" arguments=".\AspNetCoreSampleForNano.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true" />
 </system.webServer>
</configuration>

Выполните следующие команды в удаленной сессии, чтобы создать новый веб-сайт в IIS для опубликованного приложения. В этом скрипте для упрощения используется DefaultAppPool. Более подробная информация о работе с пулом приложений приведена в статье Application Pools.

Import-module IISAdministration
New-IISSite -Name "AspNetCore" -PhysicalPath c:\PublishedApps\AspNetCoreSampleForNano -BindingInformation "*:8000:"

Известная проблема в работе .NET Core CLI в Nano Server и способ ее обхода


Если используется Nano Server Technical Preview 5 c .NET Core CLI, необходимо скопировать файлы DLL из каталога c:\windows\system32\forwarders в каталог c:\Program Files\dotnet\shared\Microsoft.NETCore.App\1.0.0\ и в каталог двоичных файлов .NET Core c:\dotnet (в данном примере). Это вызвано ошибкой, которая устранена в более новых версиях.

Если используется команда dotnet publish, скопируйте также файлы DLL из каталога c:\windows\system32\forwarders в каталог публикации.

Если система Nano Server Technical Preview 5 была обновлена или изменена, повторите данную процедуру, так как файлы DLL также могли быть обновлены.

Запуск приложения


Опубликованное веб-приложение должно быть доступно в браузере по адресу http://<nanoserver-ip-address>:8000. Если ведение журнала сконфигурировано так, как указано в разделе Создание и перенаправление логов, все журналы доступны в каталоге C:\PublishedApps\AspNetCoreSampleForNano\logs.

В данном материале используется предварительный выпуск варианта установки Nano Server, который доступен в Windows Server Technical Preview 5. Программное обеспечение на виртуальном образе жесткого диска может использоваться только для целей внутренней демонстрации и тестирования. Данное программное обеспечение не предназначено для использования в производственной среде. Дату окончания действия ознакомительной версии можно узнать здесь.
Поделиться с друзьями
-->

Комментарии (25)


  1. commanderxo
    26.09.2016 13:36
    +2

    Не могли бы вы рассказать поподробнее для каких сценариев предназначается Nano Server?

    В ссылке на официальную документацию в начале статьи говорится об использовании в качестве хоста для Hyper-V, однако в примерах наоборот, сам Nano Server это виртуальная машина.

    В чём по вашему мнению преимущества .NET Core + Nano перед классическим ASP.NET MVC (OWIN) на полновесной ОС, тем более что вы всё равно используете IIS? Какие реальные проблемы решает связка c Nano?

    Некоторые недостатки у Core есть, например пока отсутствует System.Drawing, которой мы используем для масштабирования JPEG-ов. Что оправдывает цену перехода на новую технологию? Может Deployment? Но, как я понимаю, даже облегчённая версия Windows слишком велика чтоб сделать весь образ артефактом который поставляют разработчики — копирование образа займёт слишком много времен.

    Одним словом, чем по вашему мнению интересен Nano Server? Грубо говоря, чем он лучше полновесной Windows с одной стороны и Docker-а с другой?

    /* Сухой маркетинговый язык страниц MSDN уже читал, хочется знать мнение реально работающих с этой технологией */


    1. usarskyy
      26.09.2016 15:13
      +4

      Я не автор заметки, но попробую ответить. Основное преимущество Nano Server это его требования к ресурсам. MS вырезал из этой версии ОС практически всё. На конференции показывали, что в «голом» виде там крутится в памяти что-то около 12-15 процессов :) Процесс установки и управления сервером тоже существенно упростился. Также сменили политику установки обновлений.

      Применять Nano Server стоит ИМХО в связке с Docker или с Win Server Containers (тот же Docker, только в профиль). Применение в качестве хоста Hyper-V имеет смысл, потому что ОС не отъедает полтора ГБ оперативки за «красивые глазки»


      1. kekekeks
        26.09.2016 15:58

        Надо только учитывать, что при применении ASP.NET Core в докер-контейнере IIS в этом самом контейнере нафиг не нужен.


        1. commanderxo
          26.09.2016 16:32

          То-есть область применения можно сформулировать следующим образом:

          Если нужна кросс-платформенность, то надо брать Core. Главная цель — докер, который нам люб за то, что когда программист говорит «готово», то результатом является контейнер, который однозначно описывает систему во всех видах установки, от DEV до Production. Тем самым на корню устраняются проблемы вида «а у меня на компьютере всё работает». Ценой является отказ от бесплатных плюшек IIS вроде gzip-упаковки или Windows-аутентификации.

          Если контейнеры нам пока не светят, например по организационным причинам, то полезность Core в нынешнем его состоянии не очевидна. Да, сегодня разработчики выдают при релизе 20 Мб DLL-ек, которые отдельная Infrastructure-команда устанавливает на заботливо оберегаемом ими Windows Server 2012, а завтра программисты будут выдавать лишь 2 Мб, а остальные 18 Мб сервер сам скачает из NuGet, но правил игры это не меняет. Сервер остаётся «pet, not cattle».

          Замена тяжеловесного сервера на Nano порадует сисадминов, которым мучительно больно смотреть на расходуемые зря гигабайты, но мало что изменит для программистов.

          Или я где-то ошибаюсь?


          1. navion
            26.09.2016 16:37
            +1

            Замена тяжеловесного сервера на Nano порадует сисадминов, которым мучительно больно смотреть на расходуемые зря гигабайты, но мало что изменит для программистов.

            Для админов оно тоже не всегда лучше.


            1. commanderxo
              27.09.2016 10:29
              +1

              Спасибо за ссылку, очень интересно.

              Получается, что с точки зрения программиста (которому всё равно нельзя лазить на Production серверы) Nano Server не отличается от полновесного Windows Server — в обоих есть полноценный IIS.

              А у админов теперь выбор — выучить новые cmdlet-ы и радоваться легковесным виртуальным машинам, или и дальше пользоваться Windows Server, платя, тем самым, «налог на незнание PowerShell».

              Учитывая тенденцию нарезать бизнес-логику маленькими независимыми кусочками микросервисов, перспектива хостить на одном Hyper-V несколько десятков лёгких VM с Nano Server весьма заманчива.


          1. usarskyy
            26.09.2016 17:11
            +2

            Да, в общем верно. ASP.NET Core для того и создавали, чтобы быть кросплатформенными.

            Ну а Docker не панацея от «а у меня на компьютере всё работает», просто проще это все задеплоить (хотя тут тоже спорный момент).

            а завтра программисты будут выдавать лишь 2 Мб, а остальные 18 Мб сервер сам скачает из NuGet


            Подозреваю, это будут те же 20 Мб, только заботливо упакованы в контейнер :D


          1. kekekeks
            26.09.2016 18:09
            +1

            завтра программисты будут выдавать лишь 2 Мб, а остальные 18 Мб сервер сам скачает из NuG
            На самом деле они выкачиваются на этапе сборки, полный бандл достаточно тяжёлый, мегабайт 40. И поддержка IIS там никуда не делась, нужно просто к нему модуль специальный доустановить.

            Так же надо понимать, что переезд со Standard на Nano живёт своей жизнью и туда отлично деплоится обычный ASP.NET. Надо только ввести одно короткое, простое и легко гуглящееся заклинание в консольку:
            Скрытый текст
            DISM.EXE /online /enable-feature /featureName:IIS-WebServerRole /featureName:IIS-WebServer /featureName:IIS-CommonHttpFeatures /featureName:IIS-StaticContent /featureName:IIS-DefaultDocument /featureName:IIS-DirectoryBrowsing /featureName:IIS-HttpErrors /featureName:IIS-HttpRedirect /featureName:IIS-ApplicationDevelopment /featureName:IIS-ASPNET45 /featureName:IIS-NetFxExtensibility45 /featureName:IIS-ASP /featureName:IIS-CGI /featureName:IIS-ISAPIExtensions /featureName:IIS-ISAPIFilter /featureName:IIS-ServerSideIncludes /featureName:IIS-HealthAndDiagnostics /featureName:IIS-HttpLogging /featureName:IIS-LoggingLibraries /featureName:IIS-RequestMonitor /featureName:IIS-HttpTracing /featureName:IIS-CustomLogging /featureName:IIS-ODBCLogging /featureName:IIS-Security /featureName:IIS-BasicAuthentication /featureName:IIS-WindowsAuthentication /featureName:IIS-DigestAuthentication /featureName:IIS-ClientCertificateMappingAuthentication /featureName:IIS-IISCertificateMappingAuthentication /featureName:IIS-URLAuthorization /featureName:IIS-RequestFiltering /featureName:IIS-IPSecurity /featureName:IIS-Performance /featureName:IIS-HttpCompressionStatic /featureName:IIS-HttpCompressionDynamic /featureName:IIS-WebDAV /featureName:IIS-WebServerManagementTools /featureName:IIS-ManagementScriptingTools /featureName:IIS-ManagementService /featureName:IIS-IIS6ManagementCompatibility /featureName:IIS-Metabase /featureName:IIS-WMICompatibility /featureName:IIS-LegacyScripts /featureName:IIS-FTPServer /featureName:IIS-FTPSvc /featureName:IIS-FTPExtensibility /featureName:NetFx4Extended-ASPNET45 /featureName:IIS-ApplicationInit /featureName:IIS-WebSockets /featureName:IIS-CertProvider


        1. usarskyy
          26.09.2016 17:04

          На самом деле не совсем так. Да, в 80% случаев надо смотреть на связку ASP.NET Core + Kestrel, но IIS все еще далеко впереди по «фичам» (вот тут небольшое сравнение).
          IIS прожорлив, но потолок быстродействия у него довольно высокий для большинства проектов. Половина сайтов умирают сами по себе еще на половине пути к этому «потолку» :)


          1. kekekeks
            26.09.2016 18:12
            +1

            По вашей ссылке сравнивают Kestrel и WebListener. Первый работает на libuv и имеет свою реализацию HTTP протокола, второй использует драйвер http.sys. В обоих случаях IIS выступает в качестве проксирующей запросы прокладки, то есть, не нужен. Во втором он вдвойне не нужен, так как WebListener может жить с IIS на одном порту за счёт этого самого http.sys.


            1. usarskyy
              26.09.2016 19:45
              +1

              Сорри за невнимательность, не тот линк вставил. Вот тут полное сравнение.

              Кроме того в IIS еще есть куча фич как dynamic compression, logging, access management, балансировка запросов между процессами и т.д. Поэтому, «проксирующая прокладка» это уж слишком сильное приуменьшение ;)
              Да, все эти фичи сильно снижают мифический показатель RPS, но, как я уже писал, большинство проектов никогда не увидят этот «потолок».

              UPDATE: похоже, это одна и та же таблица, просто на docs.asp.net убрали колонку IIS, так как она почти полностью дублирует WebListener.


              1. Razaz
                26.09.2016 22:26

                Тут тогда еще бы добавить Nginx и Apache ;) И я бы посмотрел, например, на wildcard subdomains… ;)
                Плюс по фичам — часть из них реализована в виде Middleware:
                Buffering — https://github.com/aspnet/BasicMiddleware/tree/dev/src/Microsoft.AspNetCore.Buffering
                Compression — https://github.com/aspnet/BasicMiddleware/tree/dev/src/Microsoft.AspNetCore.ResponseCompression

                Последний линк кстати чутка устарел:) Часть фич уже сделали. Например Connection, RequestLifetime.


                1. usarskyy
                  26.09.2016 23:32
                  +1

                  Скоро они допилят все фичи и назовут это IIS 10 :D


          1. KirillFormado
            27.09.2016 09:28

            Но как бы Kestrel не предназначен для работы в одиночку. Подразумевается его использовать(в продакшене) только за Nginx-ом или IIS-ом. О чем и пишется в документации.


      1. navion
        27.09.2016 01:12

        Забавно, MS сами [пока] не используют Docker, а установщик даже не включен в дистрибутив Windows Server.


        1. usarskyy
          27.09.2016 10:32

          Так мне на докладе о Nano Server & Containers рассказал докладчик. Конкретно: пилят свои контейнеры, но поддержке докера «из коробки» быть (но только в новом сервере, о старых никто не говорил). Рассказывали мне в апреле, с того времени планы могли немного измениться.
          Я лично не совсем понимаю зачем сейчас пилить свой контейнер, лучше бы хорошо интегрировали Docker. Но может там какие-то супер-пупер инновации, о которых нам пока ничего не рассказали :)


          1. dobriykot
            27.09.2016 16:51

            Свой совместимый с докером или несовместимый?


            1. usarskyy
              27.09.2016 19:10

              Вот этого, к сожалению, не помню


    1. Razaz
      26.09.2016 15:33

      Ну MVC(OWIN) vs Core отдельная тема. Drawing, DirectoryServices отсутствуют пока что. Но если нет таких либ в зависимостях, то MVC(OWIN) в принципе теряет смысл сейчас для новых проектов.
      PS. Ну и можно зареференсить их если таргет нужный поставить. И использовать Nginx + Core на WinServer.


      1. kekekeks
        26.09.2016 16:00

        ASP.NET Core умеет работать поверх обычного .NET Framework/Mono. Соответственно, с зависимостями проблем нет.


        1. Razaz
          26.09.2016 16:02

          В PS написал ;) Надо только нужный халай махалай сделать в project.json.


      1. commanderxo
        26.09.2016 16:07

        Как раз OWIN мы уж 2 года используем со старым-добрым .NET 4.5-4.6, вместе с классическим IIS.

        Началось всё с тестирования микросервисов на WEB API 2, приятно когда в две строчки можно поднять в памяти весь сервис и проверять правильность на уровне HTTP Request/Response, в том числе и правильную обработку HTTP-Headers и кодов возврата. А потом как-то незаметно переползло и в обычные веб-приложения. OWIN там не даёт особых преимуществ, но просто приятно убрать всё лишнее из global.asax, в котором отовсюду торчат уши HttpHandler (каковым и являлся ASP.NET в 2002 году).


        1. Razaz
          26.09.2016 16:53
          +1

          OWIN позволяет нормально обрабатывать веб реквест выстраивая цепочки Middlware с прогнозируемым порядком выполнения. До сих пор вспомниаю ахтунг с SessionHttpModule + WSFederationAuthenticationModule.
          Новые проекты уже на Core. ИМХО это большой шаг вперед относительно OWIN(как минимум нет переключений в ASP.NET для того же MVC) и его логическое развитие. Как минимум кастомизируемый роутинг на уровне Middleware и механизм IOptions/IConfiguration. Ну и производительность совершенно другого порядка. Старые проекты уже активно готовятся к переезду.


    1. dimaaan
      27.09.2016 09:28

      пока отсутствует System.Drawing, которой мы используем для масштабирования JPEG-ов

      Возможно это вам поможет:
      https://github.com/antiufo/Shaman.System.Drawing


    1. fedorro
      27.09.2016 11:22

      для масштабирования JPEG-ов.

      Вот ещё обёртка для ImageMagick. Отлично работает под Asp.Net Core — проверено.