Разработка приложений ASP.NET Core с использованием наблюдателя файлов

Авторы: Рик Андерсон (Rick Anderson) и Виктор Хурдугачи (Victor Hurdugaci)

dotnet watch — это средство, которое запускает команду .NET Core CLI при изменении исходных файлов. Например, в результате изменения файла может выполняться компиляция, тестирование или развертывание.

В этом руководстве используется уже существующее приложение веб-API с двумя конечными точками, одна из которых возвращает сумму, а другая — произведение. В методе произведения есть ошибка, которая исправлена в этом руководстве.

Скачайте образец приложения. Он содержит два проекта: WebApp (веб-API ASP.NET Core) и WebAppTests (модульные тесты для веб-API).

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

dotnet run

Примечание.

Можно использовать dotnet run --project <PROJECT>, чтобы указать проект для запуска. Например, при выполнении dotnet run --project WebApp из корневой папки примера приложения также будет запущен проект WebApp.

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

$ dotnet run
Hosting environment: Development
Content root path: C:/Docs/aspnetcore/tutorials/dotnet-watch/sample/WebApp
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Откройте браузер и перейдите по адресу http://localhost:<port number>/api/math/sum?a=4&b=5. Должен появиться результат 9.

Перейдите к API продукта (http://localhost:<port number>/api/math/product?a=4&b=5). Он возвращает 9, а не 20, как ожидалось. Эта проблема устраняется далее в этом руководстве.

Добавление dotnet watch в проект

Средство наблюдения за файлами dotnet watch входит в версию 2.1.300 пакета SDK для .NET Core. Выполните следующие действия при использовании более ранней версии пакета SDK для .NET Core.

  1. Добавьте ссылку на пакет Microsoft.DotNet.Watcher.Tools в файл .csproj.

    <ItemGroup>
        <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
    </ItemGroup>
    
  2. Установите пакет Microsoft.DotNet.Watcher.Tools, запустив следующую команду:

    dotnet restore
    

Запуск команд .NET Core CLI с помощью dotnet watch

Любую команду .NET Core CLI можно запустить с dotnet watch. Например:

Команда Команда с контрольным значением
dotnet run dotnet watch run
dotnet run -f netcoreapp3.1 dotnet watch run -f netcoreapp3.1
dotnet run -f netcoreapp3.1 -- --arg1 dotnet watch run -f netcoreapp3.1 -- --arg1
dotnet test dotnet watch test

Запустите dotnet watch run в папке WebApp. В выходных данных консоли будет указано, что запущен watch.

При выполнении dotnet watch run в веб-приложении запускается браузер с переходом по URL-адресу приложения, когда оно будет готово. Для этого dotnet watch считывает выходные данные из консоли приложения и ожидает, когда WebHost выведет сообщение о готовности.

dotnet watch обновляет содержимое в браузере при обнаружении изменений в отслеживаемых файлах. Для этого команда watch вставляет в приложение ПО промежуточного слоя, которое изменяет ответы HTML, создаваемые приложением. ПО промежуточного слоя добавляет на страницу блок скрипта JavaScript, позволяющий dotnet watch давать команду на обновление содержимого в браузере. В настоящее время изменения всех отслеживаемых файлов, включая статическое содержимое, например .html и .css файлы, вызывают перестроение приложения.

dotnet watch:

  • По умолчанию отслеживаются только файлы, которые влияют на сборку.
  • Дополнительные отслеживаемые файлы (указанные в конфигурации) по-прежнему приводят к сборке.

Дополнительные сведения см. в разделе Конфигурация dotnet-watch этой документации.

Примечание.

Можно использовать dotnet watch --project <PROJECT>, чтобы указать проект для наблюдения. Например, при выполнении dotnet watch --project WebApp run из корневой папки примера приложения также будет запущен проект WebApp, в том числе для наблюдения.

Изменения с помощью dotnet watch

Убедитесь, что dotnet watch выполняется.

Исправьте ошибку в методе Product для MathController.cs так, чтобы он возвращал произведение, а не сумму чисел.

public static int Product(int a, int b)
{
    return a * b;
}

Сохраните файл. В выходных данных консоли будет показано, что dotnet watch обнаружил изменение файла и перезапустил приложение.

Убедитесь, что http://localhost:<port number>/api/math/product?a=4&b=5 возвращает правильный результат.

Тестирование с помощью dotnet watch

  1. Измените Product метод MathController.cs обратно на возврат суммы. Сохраните файл.

  2. В командной оболочке перейдите в папку WebAppTests.

  3. Запустите dotnet restore.

  4. Выполните команду dotnet watch test. В выходных данных будет указано, что проверка не пройдена и наблюдатель ожидает изменений в файле:

    Total tests: 2. Passed: 1. Failed: 1. Skipped: 0.
    Test Run Failed.
    
  5. Исправьте код метода Product так, чтобы он возвращал произведение. Сохраните файл.

dotnet watch обнаруживает изменения в файле и повторно запускает тесты. В выходных данных консоли будет указано, что проверка пройдена.

Настройка списка файлов для наблюдения

По умолчанию dotnet-watch отслеживает все файлы, соответствующие следующим стандартным маскам:

  • **/*.cs
  • *.csproj
  • **/*.resx
  • Файлы содержимого: wwwroot/**, **/*.config, **/*.json

Дополнительные элементы можно добавить в список наблюдения, изменив .csproj файл. Элементы можно указывать по отдельности или с помощью стандартной маски.

<ItemGroup>
    <!-- extends watching group to include *.js files -->
    <Watch Include="**\*.js" Exclude="node_modules\**\*;**\*.js.map;obj\**\*;bin\**\*" />
</ItemGroup>

Удаление файлов из списка наблюдения

Можно настроить dotnet-watch так, чтобы игнорировать параметры по умолчанию. Чтобы пропускать определенные файлы, добавьте атрибут Watch="false" в определение элемента в файле .csproj:

<ItemGroup>
    <!-- exclude Generated.cs from dotnet-watch -->
    <Compile Include="Generated.cs" Watch="false" />

    <!-- exclude Strings.resx from dotnet-watch -->
    <EmbeddedResource Include="Strings.resx" Watch="false" />

    <!-- exclude changes in this referenced project -->
    <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" Watch="false" />
</ItemGroup>
<ItemGroup>
     <!-- Exclude all Content items from being watched. -->
    <Content Update="@(Content)" Watch="false" />
</ItemGroup>

Пользовательское наблюдение за проектами

dotnet-watch используется не только с проектами C#. Создайте пользовательское наблюдение за проектами для различных ситуаций. Вы можете использовать следующий макет проекта:

  • test/
    • UnitTests/UnitTests.csproj
    • IntegrationTests/IntegrationTests.csproj

Если вы хотите наблюдать за обоими проектами, создайте пользовательский файл проекта, настроенный для наблюдения за обоими проектами:

<Project>
    <ItemGroup>
        <TestProjects Include="**\*.csproj" />
        <Watch Include="**\*.cs" />
    </ItemGroup>

    <Target Name="Test">
        <MSBuild Targets="VSTest" Projects="@(TestProjects)" />
    </Target>

    <Import Project="$(MSBuildExtensionsPath)\Microsoft.Common.targets" />
</Project>

Чтобы запустить наблюдение за файлами для обоих проектов, внесите изменения в папку test. Выполните следующую команду:

dotnet watch msbuild /t:Test

VSTest выполняется при изменении любого файла в любом из тестовых проектов.

Конфигурация dotnet-watch

Некоторые параметры конфигурации можно передавать в dotnet watch с помощью переменных среды. Доступные переменные:

Параметр Description
DOTNET_USE_POLLING_FILE_WATCHER Если задано значение 1 или true, dotnet watch использует опрашивающий наблюдатель за файлами вместо FileSystemWatcher в CoreFx. Используется при отслеживании файлов в сетевых папках или подключенных томах Docker.
DOTNET_WATCH_SUPPRESS_MSBUILD_INCREMENTALISM По умолчанию dotnet watch оптимизирует сборку, исключая определенные операции, такие как восстановление или повторная оценка набора отслеживаемых файлов при каждом изменении. Если задано значение 1 или true, эти оптимизации отключены.
DOTNET_WATCH_SUPPRESS_LAUNCH_BROWSER dotnet watch run пытается запускать веб-приложения в браузерах с использованием параметра launchBrowser, настроенного в файле launchSettings.json. Если задано значение 1 или true, это поведение подавляется.
DOTNET_WATCH_SUPPRESS_BROWSER_REFRESH dotnet watch run пытается обновлять содержимое в браузерах при обнаружении изменений в файлах. Если задано значение 1 или true, это поведение подавляется. Это поведение также подавляется, если задан параметр DOTNET_WATCH_SUPPRESS_LAUNCH_BROWSER.

Обновление браузера

dotnet watch внедряет в приложение скрипт, который позволяет обновлять браузер при изменении содержимого. В некоторых сценариях, например, когда приложение включает сжатие откликов, у dotnet watch может не быть возможности внедрить скрипт. В таких случаях при разработке вручную вставьте скрипт в приложение. Например, чтобы настроить веб-приложение для ручного внедрения скрипта, обновите файл макета, чтобы он включал _framework/aspnet-browser-refresh.js:

@* _Layout.cshtml *@
<environment names="Development">
    <script src="/_framework/aspnetcore-browser-refresh.js"></script>
</environment>

Символы, отличные от ASCII

Visual Studio 17.2 и более поздних версий включает пакет SDK для .NET 6.0.300 или более поздней версии. В случае пакета SDK для .NET 6.0.300 и более поздней версии dotnet-watch выдает на консоль символы, не входящие в набор ASCII, во время сеанса горячей загрузки. На определенных узлах консоли, таких как размещение Windows, эти символы могут выглядеть искаженными. Чтобы избежать искаженных символов, рассмотрим один из следующих подходов:

  • Настройте переменную среды DOTNET_WATCH_SUPPRESS_EMOJIS=1, чтобы отключить вывод этих значений.
  • Переключитесь на другой терминал, например https://github.com/microsoft/terminal, который поддерживает отображение символов, отличных от ASCII.