Веб-узел ASP.NET Core

Приложения ASP.NET Core настраивают и запускают узел. Узел отвечает за запуск приложения и управление временем существования. Узел настраивает как минимум сервер и конвейер обработки запросов. Узел также может настроить ведение журнала, внедрение зависимостей и конфигурацию.

В этой статье описывается веб-узел, доступ к которому предоставляется только для обеспечения обратной совместимости. Шаблоны ASP.NET Core создают WebApplicationBuilder и WebApplication, что рекомендуется для веб-приложений. Дополнительные сведения о WebApplicationBuilder и WebApplication см. в статье Миграция с ASP.NET Core 5.0 на 6.0.

Создание узла

Создание узла с помощью экземпляра IWebHostBuilder. Обычно это делается в точке входа приложения, т. е. в методе Main в Program.cs. Типичные вызовы CreateDefaultBuilder приложения для запуска настройки узла:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

Код, который вызывает CreateDefaultBuilder, находится в методе CreateWebHostBuilder, что отделяет его от кода в методе Main, который вызывает Run для объекта построителя. Такое отделение требуется, если вы используете инструменты Entity Framework Core. Эти инструменты используют метод CreateWebHostBuilder, который они могут вызвать во время разработки для настройки узла без необходимости запускать приложение. В качестве альтернативного способа можно использовать реализацию IDesignTimeDbContextFactory. Подробные сведения см. в статье Design-time DbContext Creation (Создание экземпляра DbContext во время разработки).

CreateDefaultBuilder выполняет следующие задачи:

Настройки, определенные CreateDefaultBuilder, можно переопределить и усилить с помощью ConfigureAppConfiguration, ConfigureLogging и других методов и методов расширения IWebHostBuilder. Ниже приведены некоторые примеры:

  • ConfigureAppConfiguration используется для указания дополнительного объекта IConfiguration для приложения. Следующий вызов ConfigureAppConfiguration добавляет делегата, чтобы включить конфигурацию приложения в файл appsettings.xml. ConfigureAppConfiguration можно вызывать несколько раз. Обратите внимание, что эта конфигурация не распространяется на узел (например, URL-адреса серверов или среду). См. раздел Значения конфигурации узла.

    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
        })
        ...
    
  • Следующий вызов ConfigureLogging добавляет делегата, чтобы настроить минимальный уровень ведения журнала (SetMinimumLevel) для LogLevel.Warning. Этот параметр переопределяет параметры в appsettings.Development.json (LogLevel.Debug) и appsettings.Production.json (LogLevel.Error) настроены CreateDefaultBuilder. ConfigureLogging можно вызывать несколько раз.

    WebHost.CreateDefaultBuilder(args)
        .ConfigureLogging(logging => 
        {
            logging.SetMinimumLevel(LogLevel.Warning);
        })
        ...
    
  • При следующем вызове к ConfigureKestrel переопределяется значение по умолчанию Limits.MaxRequestBodySize, равное 30 000 000 байтов, установленное при настройке Kestrel с помощью CreateDefaultBuilder:

    WebHost.CreateDefaultBuilder(args)
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.MaxRequestBodySize = 20000000;
        });
    

Корень содержимого определяет, где узел ищет файлы содержимого, например файлы представлений MVC. При запуске приложения из корневой папки проекта эта папка используется в качестве корня содержимого. Такое поведение по умолчанию принято в Visual Studio и шаблонах dotnet new.

Дополнительные сведения о конфигурации приложения см. в разделе Конфигурация в ASP.NET Core.

Примечание.

Помимо использования статического метода CreateDefaultBuilder, в ASP.NET Core 2.x поддерживается создание узла на основе WebHostBuilder.

При настройке узла Configure и ConfigureServices методов можно предоставить. Если используется класс Startup, в нем должен быть определен метод Configure. Подробные сведения см. в статье Запуск приложения в ASP.NET Core. Несколько вызовов ConfigureServices добавляются друг к другу. При нескольких вызовах Configure или UseStartup в WebHostBuilder предыдущие параметры заменяются.

Значения конфигурации узла

WebHostBuilder использует следующие подходы для задания значений конфигурации узла:

  • конфигурация построителя узла, которая включает в себя переменные среды в формате ASPNETCORE_{configurationKey}, Например, ASPNETCORE_ENVIRONMENT.
  • Расширения, такие как UseContentRoot и UseConfiguration (см. раздел Переопределение конфигурации).
  • UseSetting и связанный ключ. Значение, задаваемое с помощью UseSetting, всегда является строкой независимо от типа.

Хост использует значение, заданное последним. Дополнительные сведения см. в подразделе Переопределение конфигурации следующего раздела.

Ключ приложения (имя)

Свойство IWebHostEnvironment.ApplicationName задается автоматически при вызове UseStartup или Configure во время создания узла. Значение присваивается имени сборки, содержащей точку входа приложения. Чтобы задать значение явным образом, используйте следующую WebHostDefaults.ApplicationKeyкоманду:

Ключ: applicationName
Тип: string
По умолчанию: имя сборки, содержащей точку входа приложения
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_APPLICATIONNAME

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")

Перехват ошибок при загрузке

Этот параметр управляет перехватом ошибок при загрузке.

Ключ: captureStartupErrors
Тип: bool (true или 1)
Значение по умолчанию: false, если только приложение не работает с сервером Kestrel за IIS; в этом случае значение по умолчанию — true.
Задается с помощью: CaptureStartupErrors
переменной среды: ASPNETCORE_CAPTURESTARTUPERRORS

Если задано значение false, ошибки во время запуска приводят к завершению работы узла. Если задано значение true, узел перехватывает исключения во время запуска и пытается запустить сервер.

WebHost.CreateDefaultBuilder(args)
    .CaptureStartupErrors(true)

Корневой каталог содержимого

Этот параметр определяет то, где ASP.NET Core начинает искать файлы содержимого.

Ключ: contentRoot
Тип: string
Значение по умолчанию: папка, в которой находится сборка приложения.
Задается с помощью: UseContentRoot
переменной среды: ASPNETCORE_CONTENTROOT

Корневой каталог содержимого также используется в качестве базового пути для корневого каталога документов. Если путь к корневому каталогу содержимого не существует, узел не запускается.

WebHost.CreateDefaultBuilder(args)
    .UseContentRoot("c:\\<content-root>")

Дополнительные сведения см. в разделе:

Подробные сообщения об ошибках

Определяет, следует ли перехватывать подробные сообщения об ошибках.

Ключ: detailedErrors
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_DETAILEDERRORS

Если этот параметр включен (или если параметр Среда имеет значение Development), приложение перехватывает подробные исключения.

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")

Среда

Задает среду приложения.

Ключ: environment
Тип: string
Значение по умолчанию: Production
Задается с помощью: UseEnvironment
переменной среды: ASPNETCORE_ENVIRONMENT

В качестве среды можно указать любое значение. В платформе определены значения Development, Staging и Production. Регистр символов в значениях не учитывается. По умолчанию значение параметра Среда считывается из переменной среды ASPNETCORE_ENVIRONMENT. При использовании Visual Studio переменные среды могут быть заданы в launchSettings.json файле. Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

WebHost.CreateDefaultBuilder(args)
    .UseEnvironment(EnvironmentName.Development)

Начальные сборки размещения

Задает начальные сборки размещения для приложения.

Ключ: hostingStartupAssemblies
Тип: string
Значение по умолчанию: пустая строка
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES

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

Хотя значением по умолчанию этого параметра конфигурации является пустая строка, начальные сборки размещения всегда включают в себя сборку приложения. Если начальные сборки размещения указаны, они добавляются к сборке приложения для загрузки во время построения приложением общих служб при запуске.

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")

Порт HTTPS

Задайте порт перенаправления HTTPS. Используется при принудительном применении HTTPS.

Ключ: https_port
Тип: string
Значение по умолчанию: значение по умолчанию не задано.
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HTTPS_PORTS

WebHost.CreateDefaultBuilder(args)
    .UseSetting("https_port", "8080")

Исключаемые начальные сборки размещения

Разделенная точками с запятой строка начальных сборок размещения, которые необходимо исключить при запуске.

Ключ: hostingStartupExcludeAssemblies
Тип: string
Значение по умолчанию: пустая строка
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")

Предпочитать URL-адреса размещения

Указывает, должен ли узел ожидать передачи данных по URL-адресам, настроенным с помощью WebHostBuilder, вместо настроенных с помощью реализации IServer.

Ключ: preferHostingUrls
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: PreferHostingUrls
переменной среды: ASPNETCORE_PREFERHOSTINGURLS

WebHost.CreateDefaultBuilder(args)
    .PreferHostingUrls(true)

Запретить запуск размещения

Запрещает автоматическую загрузку начальных сборок размещения, включая начальные сборки размещения, настроенные сборкой приложения. Дополнительные сведения см. в статье Использование начальных сборок размещения в ASP.NET Core.

Ключ: preventHostingStartup
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_PREVENTHOSTINGSTARTUP

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")

URL-адреса сервера

Задает IP-адреса или адреса узлов с портами и протоколами, по которым сервер должен ожидать получения запросов.

Ключ: urls
Тип: string
По умолчанию:http://localhost:5000
Задается с помощью: UseUrls
переменной среды: ASPNETCORE_URLS

Укажите разделенный точками с запятой (;) список префиксов URL-адресов, на которые сервер должен отвечать. Например, http://localhost:123. Используйте символ "*", чтобы указать, что сервер должен ожидать получения запросов через определенный порт и по определенному протоколу по любому IP-адресу или имени узла (например, http://*:5000). Протокол (http:// или https://) должен указываться для каждого URL-адреса. Поддерживаемые форматы зависят от сервера.

WebHost.CreateDefaultBuilder(args)
    .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")

Kestrel имеет собственный API настройки конечных точек. Дополнительные сведения см. в статье KestrelНастройка конечных точек для веб-сервера для ASP.NET Core.

Время ожидания завершения работы

Определяет, как долго необходимо ожидать завершения работы веб-узла.

Ключ: shutdownTimeoutSeconds
Тип: int
Значение по умолчанию: 5
Задается с помощью: UseShutdownTimeout
переменной среды: ASPNETCORE_SHUTDOWNTIMEOUTSECONDS

Хотя ключ принимает значение int с UseSetting (например, .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")), метод расширения UseShutdownTimeout принимает TimeSpan.

Во время ожидания размещение:

  • Активирует IApplicationLifetime.ApplicationStopping.
  • Пытается остановить размещенные службы, записывая в журнал все ошибки для служб, которые не удалось остановить.

Если время ожидания истекает до остановки всех размещенных служб, активные службы останавливаются при завершении работы приложения. Службы останавливаются даже в том случае, если еще не завершили обработку. Если службе требуется дополнительное время для остановки, увеличьте время ожидания.

WebHost.CreateDefaultBuilder(args)
    .UseShutdownTimeout(TimeSpan.FromSeconds(10))

Стартовая сборка

Определяет сборку, в которой необходимо искать класс Startup.

Ключ: startupAssembly
Тип: string
Значение по умолчанию: сборка приложения
Задается с помощью: UseStartup
переменной среды: ASPNETCORE_STARTUPASSEMBLY

На сборку можно ссылаться по имени (string) или типу (TStartup). При вызове нескольких методов UseStartup приоритет имеет последний.

WebHost.CreateDefaultBuilder(args)
    .UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
    .UseStartup<TStartup>()

каталог документов

Задает относительный путь к статическим ресурсам приложения.

Ключ: webroot
Тип: string
По умолчанию: значение по умолчанию — wwwroot. Наличие пути {корневой_каталог_содержимого}/wwwroot обязательно. Если этот путь не существует, используется фиктивный поставщик файлов.
Задается с помощью: UseWebRoot
переменной среды: ASPNETCORE_WEBROOT

WebHost.CreateDefaultBuilder(args)
    .UseWebRoot("public")

Дополнительные сведения см. в разделе:

Переопределение конфигурации

Используйте конфигурацию для настройки веб-узла. В следующем примере конфигурация узла при необходимости указывается в hostsettings.json файле. Любая конфигурация, загруженная из hostsettings.json файла, может быть переопределена аргументами командной строки. Встроенная конфигурация (в config) используется для настройки узла с помощью UseConfiguration. Конфигурация IWebHostBuilder добавляется в конфигурацию приложения, но не наоборот — ConfigureAppConfiguration не влияет на конфигурацию IWebHostBuilder.

Переопределение конфигурации, предоставленной UseUrlshostsettings.json с помощью конфигурации, во-первых, второй аргумент командной строки:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("hostsettings.json", optional: true)
            .AddCommandLine(args)
            .Build();

        return WebHost.CreateDefaultBuilder(args)
            .UseUrls("http://*:5000")
            .UseConfiguration(config)
            .Configure(app =>
            {
                app.Run(context => 
                    context.Response.WriteAsync("Hello, World!"));
            });
    }
}

hostsettings.json:

{
    urls: "http://*:5005"
}

Примечание.

UseConfiguration копирует ключи только из предоставленного объекта IConfiguration для конфигурации конструктора узла. Поэтому указание reloadOnChange: true для файлов JSON, XML и INI не имеет никакого эффекта.

Чтобы указать узел, выполняющийся по определенному URL-адресу, можно передать нужное значение из командной строки при выполнении команды dotnet run. Аргумент командной строки переопределяет urls значение из hostsettings.json файла, а сервер прослушивает порт 8080:

dotnet run --urls "http://*:8080"

Управление узлом

Выполнить

Метод Run запускает веб-приложение и блокирует вызывающий поток до тех пор, пока работа узла не будет завершена.

host.Run();

Начало

Чтобы запустить узел без блокировки, вызовите метод Start.

using (host)
{
    host.Start();
    Console.ReadLine();
}

Если в метод Start передается список URL-адресов, он будет ожидать передачи данных по указанным URL-адресам.

var urls = new List<string>()
{
    "http://*:5000",
    "http://localhost:5001"
};

var host = new WebHostBuilder()
    .UseKestrel()
    .UseStartup<Startup>()
    .Start(urls.ToArray());

using (host)
{
    Console.ReadLine();
}

Приложение может инициализировать и запустить новый узел с использованием предварительно настроенных значений по умолчанию CreateDefaultBuilder с помощью статического удобного метода. Эти методы запускают сервер без выходных данных консоли и ожидают WaitForShutdown перерыва (CTRL-C/SIGINT или SIGTERM):

Start(RequestDelegate app)

Выполните запуск с помощью RequestDelegate:

using (var host = WebHost.Start(app => app.Response.WriteAsync("Hello, World!")))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

Выполните запрос в браузере к http://localhost:5000, чтобы получить ответ "Hello World!" WaitForShutdown блоков до тех пор, пока не будет выполнено прерывание (CTRL-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

Start(string url, RequestDelegate app)

Выполните запуск с помощью URL-адреса и RequestDelegate:

using (var host = WebHost.Start("http://localhost:8080", app => app.Response.WriteAsync("Hello, World!")))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании Start(RequestDelegate app), но приложение отвечает по адресу http://localhost:8080.

Start(Action<IRouteBuilder> routeBuilder)

Используйте экземпляр IRouteBuilder (Microsoft.AspNetCore.Routing) для применения ПО промежуточного слоя маршрутизации:

using (var host = WebHost.Start(router => router
    .MapGet("hello/{name}", (req, res, data) => 
        res.WriteAsync($"Hello, {data.Values["name"]}!"))
    .MapGet("buenosdias/{name}", (req, res, data) => 
        res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
    .MapGet("throw/{message?}", (req, res, data) => 
        throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
    .MapGet("{greeting}/{name}", (req, res, data) => 
        res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
    .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

В этом примере используйте следующие запросы в браузере:

Запросить Response
http://localhost:5000/hello/Martin Hello, Martin!
http://localhost:5000/buenosdias/Catrina Buenos dias, Catrina!
http://localhost:5000/throw/ooops! Вызывает исключение со строкой "ooops!"
http://localhost:5000/throw Вызывает исключение со строкой "Uh oh!"
http://localhost:5000/Sante/Kevin Sante, Kevin!
http://localhost:5000 Hello World!

WaitForShutdown блокируется, пока не будет создано прерывание (Ctrl-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

Start(string url, Action<IRouteBuilder> routeBuilder)

Используйте URL-адрес и экземпляр IRouteBuilder:

using (var host = WebHost.Start("http://localhost:8080", router => router
    .MapGet("hello/{name}", (req, res, data) => 
        res.WriteAsync($"Hello, {data.Values["name"]}!"))
    .MapGet("buenosdias/{name}", (req, res, data) => 
        res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
    .MapGet("throw/{message?}", (req, res, data) => 
        throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
    .MapGet("{greeting}/{name}", (req, res, data) => 
        res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
    .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании Start(Action<IRouteBuilder> routeBuilder), но приложение будет отвечать по адресу http://localhost:8080.

StartWith(Action<IApplicationBuilder> app)

Предоставьте делегат для настройки IApplicationBuilder:

using (var host = WebHost.StartWith(app => 
    app.Use(next => 
    {
        return async context => 
        {
            await context.Response.WriteAsync("Hello World!");
        };
    })))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Выполните запрос в браузере к http://localhost:5000, чтобы получить ответ "Hello World!" WaitForShutdown блоков до тех пор, пока не будет выполнено прерывание (CTRL-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

StartWith(string url, Action<IApplicationBuilder> app)

Предоставьте URL-адрес и делегат для настройки IApplicationBuilder:

using (var host = WebHost.StartWith("http://localhost:8080", app => 
    app.Use(next => 
    {
        return async context => 
        {
            await context.Response.WriteAsync("Hello World!");
        };
    })))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании StartWith(Action<IApplicationBuilder> app), но приложение будет отвечать по адресу http://localhost:8080.

Интерфейс IWebHostEnvironment

Интерфейс IWebHostEnvironment предоставляет сведения о среде веб-размещения приложения. Чтобы получить интерфейс IWebHostEnvironment для использования его свойств и методов расширения, воспользуйтесь внедрением конструктора:

public class CustomFileReader
{
    private readonly IWebHostEnvironment _env;

    public CustomFileReader(IWebHostEnvironment env)
    {
        _env = env;
    }

    public string ReadFile(string filePath)
    {
        var fileProvider = _env.WebRootFileProvider;
        // Process the file here
    }
}

Для настройки приложения при запуске в соответствии со средой можно применять подход на основе соглашения. Кроме того, можно внедрить интерфейс IWebHostEnvironment в конструктор Startup для использования в ConfigureServices:

public class Startup
{
    public Startup(IWebHostEnvironment env)
    {
        HostingEnvironment = env;
    }

    public IWebHostEnvironment HostingEnvironment { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        if (HostingEnvironment.IsDevelopment())
        {
            // Development configuration
        }
        else
        {
            // Staging/Production configuration
        }

        var contentRootPath = HostingEnvironment.ContentRootPath;
    }
}

Примечание.

Помимо метода расширения IsDevelopment, интерфейс IWebHostEnvironment предоставляет методы IsStaging, IsProduction и IsEnvironment(string environmentName). Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

Службу IWebHostEnvironment также можно внедрять непосредственно в метод Configure для настройки конвейера обработки:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        // In Development, use the Developer Exception Page
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // In Staging/Production, route exceptions to /error
        app.UseExceptionHandler("/error");
    }

    var contentRootPath = env.ContentRootPath;
}

IWebHostEnvironment можно внедрить в метод Invoke при создании пользовательского ПО промежуточного слоя:

public async Task Invoke(HttpContext context, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        // Configure middleware for Development
    }
    else
    {
        // Configure middleware for Staging/Production
    }

    var contentRootPath = env.ContentRootPath;
}

Интерфейс IHostApplicationLifetime

Интерфейс IHostApplicationLifetime позволяет выполнять действия после запуска и завершения работы. Три свойства этого интерфейса представляют собой токены отмены, которые служат для регистрации методов Action, определяющих события запуска и завершения работы.

Токен отмены Условие инициации…
ApplicationStarted Узел полностью запущен.
ApplicationStopped Заканчивается нормальное завершение работы узла. Все запросы должны быть обработаны. Завершение работы блокируется до тех пор, пока это событие не завершится.
ApplicationStopping Происходит нормальное завершение работы узла. Запросы могут все еще обрабатываться. Завершение работы блокируется до тех пор, пока это событие не завершится.
public class Startup
{
    public void Configure(IApplicationBuilder app, IHostApplicationLifetime appLifetime)
    {
        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
        appLifetime.ApplicationStopped.Register(OnStopped);

        Console.CancelKeyPress += (sender, eventArgs) =>
        {
            appLifetime.StopApplication();
            // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
            eventArgs.Cancel = true;
        };
    }

    private void OnStarted()
    {
        // Perform post-startup activities here
    }

    private void OnStopping()
    {
        // Perform on-stopping activities here
    }

    private void OnStopped()
    {
        // Perform post-stopped activities here
    }
}

Метод StopApplication запрашивает остановку приложения. Следующий класс использует StopApplication для корректного завершения работы приложения при вызове метода класса Shutdown:

public class MyClass
{
    private readonly IHostApplicationLifetime _appLifetime;

    public MyClass(IHostApplicationLifetime appLifetime)
    {
        _appLifetime = appLifetime;
    }

    public void Shutdown()
    {
        _appLifetime.StopApplication();
    }
}

Проверка области

CreateDefaultBuilder Устанавливает для ServiceProviderOptions.ValidateScopes значение true, если приложение находится в среде разработки.

Если для ValidateScopes установлено значение true, поставщик службы по умолчанию проверяет, что:

  • Службы с заданной областью не разрешаются из корневого поставщика службы, прямо или косвенно.
  • Службы с заданной областью не вводятся в одноэлементные объекты, прямо или косвенно.

Корневой поставщик службы создается при вызове BuildServiceProvider. Время существования корневого поставщика службы соответствует времени существования приложения или сервера — поставщик запускается с приложением и удаляется, когда приложение завершает работу.

Службы с заданной областью удаляются создавшим их контейнером. Если служба с заданной областью создается в корневом контейнере, время существования службы повышается до уровня одноэлементного объекта, поскольку она удаляется только корневым контейнером при завершении работы приложения или сервера. Проверка областей службы перехватывает эти ситуации при вызове BuildServiceProvider.

Чтобы всегда проверять область, в том числе в рабочей среде, настройте ServiceProviderOptions его в UseDefaultServiceProvider построителе узлов:

WebHost.CreateDefaultBuilder(args)
    .UseDefaultServiceProvider((context, options) => {
        options.ValidateScopes = true;
    })

Дополнительные ресурсы

Приложения ASP.NET Core настраивают и запускают узел. Узел отвечает за запуск приложения и управление временем существования. Узел настраивает как минимум сервер и конвейер обработки запросов. Узел также может настроить ведение журнала, внедрение зависимостей и конфигурацию.

В этой статье описывается веб-узел, доступ к которому предоставляется только для обеспечения обратной совместимости. Шаблоны ASP.NET Core создают универсальный узел .NET, который рекомендуется для всех типов приложений.

Создание узла

Создание узла с помощью экземпляра IWebHostBuilder. Обычно это делается в точке входа в приложение, то есть в методе Main.

В шаблонах проектов Main находится в Program.cs. Типичные вызовы CreateDefaultBuilder приложения для запуска настройки узла:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

Код, который вызывает CreateDefaultBuilder, находится в методе CreateWebHostBuilder, что отделяет его от кода в методе Main, который вызывает Run для объекта построителя. Такое отделение требуется, если вы используете инструменты Entity Framework Core. Эти инструменты используют метод CreateWebHostBuilder, который они могут вызвать во время разработки для настройки узла без необходимости запускать приложение. В качестве альтернативного способа можно использовать реализацию IDesignTimeDbContextFactory. Подробные сведения см. в статье Design-time DbContext Creation (Создание экземпляра DbContext во время разработки).

CreateDefaultBuilder выполняет следующие задачи:

Настройки, определенные CreateDefaultBuilder, можно переопределить и усилить с помощью ConfigureAppConfiguration, ConfigureLogging и других методов и методов расширения IWebHostBuilder. Ниже приведены некоторые примеры:

  • ConfigureAppConfiguration используется для указания дополнительного объекта IConfiguration для приложения. Следующий вызов ConfigureAppConfiguration добавляет делегата, чтобы включить конфигурацию приложения в файл appsettings.xml. ConfigureAppConfiguration можно вызывать несколько раз. Обратите внимание, что эта конфигурация не распространяется на узел (например, URL-адреса серверов или среду). См. раздел Значения конфигурации узла.

    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
        })
        ...
    
  • Следующий вызов ConfigureLogging добавляет делегата, чтобы настроить минимальный уровень ведения журнала (SetMinimumLevel) для LogLevel.Warning. Этот параметр переопределяет параметры в appsettings.Development.json (LogLevel.Debug) и appsettings.Production.json (LogLevel.Error) настроены CreateDefaultBuilder. ConfigureLogging можно вызывать несколько раз.

    WebHost.CreateDefaultBuilder(args)
        .ConfigureLogging(logging => 
        {
            logging.SetMinimumLevel(LogLevel.Warning);
        })
        ...
    
  • При следующем вызове к ConfigureKestrel переопределяется значение по умолчанию Limits.MaxRequestBodySize, равное 30 000 000 байтов, установленное при настройке Kestrel с помощью CreateDefaultBuilder:

    WebHost.CreateDefaultBuilder(args)
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.MaxRequestBodySize = 20000000;
        });
    

Корень содержимого определяет, где узел ищет файлы содержимого, например файлы представлений MVC. При запуске приложения из корневой папки проекта эта папка используется в качестве корня содержимого. Такое поведение по умолчанию принято в Visual Studio и шаблонах dotnet new.

Дополнительные сведения о конфигурации приложения см. в разделе Конфигурация в ASP.NET Core.

Примечание.

Помимо использования статического метода CreateDefaultBuilder, в ASP.NET Core 2.x поддерживается создание узла на основе WebHostBuilder.

При настройке узла Configure и ConfigureServices методов можно предоставить. Если используется класс Startup, в нем должен быть определен метод Configure. Подробные сведения см. в статье Запуск приложения в ASP.NET Core. Несколько вызовов ConfigureServices добавляются друг к другу. При нескольких вызовах Configure или UseStartup в WebHostBuilder предыдущие параметры заменяются.

Значения конфигурации узла

WebHostBuilder использует следующие подходы для задания значений конфигурации узла:

  • конфигурация построителя узла, которая включает в себя переменные среды в формате ASPNETCORE_{configurationKey}, Например, ASPNETCORE_ENVIRONMENT.
  • Расширения, такие как UseContentRoot и UseConfiguration (см. раздел Переопределение конфигурации).
  • UseSetting и связанный ключ. Значение, задаваемое с помощью UseSetting, всегда является строкой независимо от типа.

Хост использует значение, заданное последним. Дополнительные сведения см. в подразделе Переопределение конфигурации следующего раздела.

Ключ приложения (имя)

Свойство IWebHostEnvironment.ApplicationName задается автоматически при вызове UseStartup или Configure во время создания узла. Значение присваивается имени сборки, содержащей точку входа приложения. Чтобы задать значение явным образом, используйте следующую WebHostDefaults.ApplicationKeyкоманду:

Ключ: applicationName
Тип: string
По умолчанию: имя сборки, содержащей точку входа приложения
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_APPLICATIONNAME

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")

Перехват ошибок при загрузке

Этот параметр управляет перехватом ошибок при загрузке.

Ключ: captureStartupErrors
Тип: bool (true или 1)
Значение по умолчанию: false, если только приложение не работает с сервером Kestrel за IIS; в этом случае значение по умолчанию — true.
Задается с помощью: CaptureStartupErrors
переменной среды: ASPNETCORE_CAPTURESTARTUPERRORS

Если задано значение false, ошибки во время запуска приводят к завершению работы узла. Если задано значение true, узел перехватывает исключения во время запуска и пытается запустить сервер.

WebHost.CreateDefaultBuilder(args)
    .CaptureStartupErrors(true)

Корневой каталог содержимого

Этот параметр определяет то, где ASP.NET Core начинает искать файлы содержимого.

Ключ: contentRoot
Тип: string
Значение по умолчанию: папка, в которой находится сборка приложения.
Задается с помощью: UseContentRoot
переменной среды: ASPNETCORE_CONTENTROOT

Корневой каталог содержимого также используется в качестве базового пути для корневого каталога документов. Если путь к корневому каталогу содержимого не существует, узел не запускается.

WebHost.CreateDefaultBuilder(args)
    .UseContentRoot("c:\\<content-root>")

Дополнительные сведения см. в разделе:

Подробные сообщения об ошибках

Определяет, следует ли перехватывать подробные сообщения об ошибках.

Ключ: detailedErrors
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_DETAILEDERRORS

Если этот параметр включен (или если параметр Среда имеет значение Development), приложение перехватывает подробные исключения.

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")

Среда

Задает среду приложения.

Ключ: environment
Тип: string
Значение по умолчанию: Production
Задается с помощью: UseEnvironment
переменной среды: ASPNETCORE_ENVIRONMENT

В качестве среды можно указать любое значение. В платформе определены значения Development, Staging и Production. Регистр символов в значениях не учитывается. По умолчанию значение параметра Среда считывается из переменной среды ASPNETCORE_ENVIRONMENT. При использовании Visual Studio переменные среды могут быть заданы в launchSettings.json файле. Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

WebHost.CreateDefaultBuilder(args)
    .UseEnvironment(EnvironmentName.Development)

Начальные сборки размещения

Задает начальные сборки размещения для приложения.

Ключ: hostingStartupAssemblies
Тип: string
Значение по умолчанию: пустая строка
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES

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

Хотя значением по умолчанию этого параметра конфигурации является пустая строка, начальные сборки размещения всегда включают в себя сборку приложения. Если начальные сборки размещения указаны, они добавляются к сборке приложения для загрузки во время построения приложением общих служб при запуске.

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")

Порт HTTPS

Задайте порт перенаправления HTTPS. Используется при принудительном применении HTTPS.

Ключ: https_port
Тип: string
Значение по умолчанию: значение по умолчанию не задано.
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HTTPS_PORTS

WebHost.CreateDefaultBuilder(args)
    .UseSetting("https_port", "8080")

Исключаемые начальные сборки размещения

Разделенная точками с запятой строка начальных сборок размещения, которые необходимо исключить при запуске.

Ключ: hostingStartupExcludeAssemblies
Тип: string
Значение по умолчанию: пустая строка
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")

Предпочитать URL-адреса размещения

Указывает, должен ли узел ожидать передачи данных по URL-адресам, настроенным с помощью WebHostBuilder, вместо настроенных с помощью реализации IServer.

Ключ: preferHostingUrls
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: PreferHostingUrls
переменной среды: ASPNETCORE_PREFERHOSTINGURLS

WebHost.CreateDefaultBuilder(args)
    .PreferHostingUrls(true)

Запретить запуск размещения

Запрещает автоматическую загрузку начальных сборок размещения, включая начальные сборки размещения, настроенные сборкой приложения. Дополнительные сведения см. в статье Использование начальных сборок размещения в ASP.NET Core.

Ключ: preventHostingStartup
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_PREVENTHOSTINGSTARTUP

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")

URL-адреса сервера

Задает IP-адреса или адреса узлов с портами и протоколами, по которым сервер должен ожидать получения запросов.

Ключ: urls
Тип: string
По умолчанию:http://localhost:5000
Задается с помощью: UseUrls
переменной среды: ASPNETCORE_URLS

Укажите разделенный точками с запятой (;) список префиксов URL-адресов, на которые сервер должен отвечать. Например, http://localhost:123. Используйте символ "*", чтобы указать, что сервер должен ожидать получения запросов через определенный порт и по определенному протоколу по любому IP-адресу или имени узла (например, http://*:5000). Протокол (http:// или https://) должен указываться для каждого URL-адреса. Поддерживаемые форматы зависят от сервера.

WebHost.CreateDefaultBuilder(args)
    .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")

Kestrel имеет собственный API настройки конечных точек. Дополнительные сведения см. в статье KestrelНастройка конечных точек для веб-сервера для ASP.NET Core.

Время ожидания завершения работы

Определяет, как долго необходимо ожидать завершения работы веб-узла.

Ключ: shutdownTimeoutSeconds
Тип: int
Значение по умолчанию: 5
Задается с помощью: UseShutdownTimeout
переменной среды: ASPNETCORE_SHUTDOWNTIMEOUTSECONDS

Хотя ключ принимает значение int с UseSetting (например, .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")), метод расширения UseShutdownTimeout принимает TimeSpan.

Во время ожидания размещение:

  • Активирует IApplicationLifetime.ApplicationStopping.
  • Пытается остановить размещенные службы, записывая в журнал все ошибки для служб, которые не удалось остановить.

Если время ожидания истекает до остановки всех размещенных служб, активные службы останавливаются при завершении работы приложения. Службы останавливаются даже в том случае, если еще не завершили обработку. Если службе требуется дополнительное время для остановки, увеличьте время ожидания.

WebHost.CreateDefaultBuilder(args)
    .UseShutdownTimeout(TimeSpan.FromSeconds(10))

Стартовая сборка

Определяет сборку, в которой необходимо искать класс Startup.

Ключ: startupAssembly
Тип: string
Значение по умолчанию: сборка приложения
Задается с помощью: UseStartup
переменной среды: ASPNETCORE_STARTUPASSEMBLY

На сборку можно ссылаться по имени (string) или типу (TStartup). При вызове нескольких методов UseStartup приоритет имеет последний.

WebHost.CreateDefaultBuilder(args)
    .UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
    .UseStartup<TStartup>()

каталог документов

Задает относительный путь к статическим ресурсам приложения.

Ключ: webroot
Тип: string
По умолчанию: значение по умолчанию — wwwroot. Наличие пути {корневой_каталог_содержимого}/wwwroot обязательно. Если этот путь не существует, используется фиктивный поставщик файлов.
Задается с помощью: UseWebRoot
переменной среды: ASPNETCORE_WEBROOT

WebHost.CreateDefaultBuilder(args)
    .UseWebRoot("public")

Дополнительные сведения см. в разделе:

Переопределение конфигурации

Используйте конфигурацию для настройки веб-узла. В следующем примере конфигурация узла при необходимости указывается в hostsettings.json файле. Любая конфигурация, загруженная из hostsettings.json файла, может быть переопределена аргументами командной строки. Встроенная конфигурация (в config) используется для настройки узла с помощью UseConfiguration. Конфигурация IWebHostBuilder добавляется в конфигурацию приложения, но не наоборот — ConfigureAppConfiguration не влияет на конфигурацию IWebHostBuilder.

Переопределение конфигурации, предоставленной UseUrlshostsettings.json с помощью конфигурации, во-первых, второй аргумент командной строки:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("hostsettings.json", optional: true)
            .AddCommandLine(args)
            .Build();

        return WebHost.CreateDefaultBuilder(args)
            .UseUrls("http://*:5000")
            .UseConfiguration(config)
            .Configure(app =>
            {
                app.Run(context => 
                    context.Response.WriteAsync("Hello, World!"));
            });
    }
}

hostsettings.json:

{
    urls: "http://*:5005"
}

Примечание.

UseConfiguration копирует ключи только из предоставленного объекта IConfiguration для конфигурации конструктора узла. Поэтому указание reloadOnChange: true для файлов JSON, XML и INI не имеет никакого эффекта.

Чтобы указать узел, выполняющийся по определенному URL-адресу, можно передать нужное значение из командной строки при выполнении команды dotnet run. Аргумент командной строки переопределяет urls значение из hostsettings.json файла, а сервер прослушивает порт 8080:

dotnet run --urls "http://*:8080"

Управление узлом

Выполнить

Метод Run запускает веб-приложение и блокирует вызывающий поток до тех пор, пока работа узла не будет завершена.

host.Run();

Начало

Чтобы запустить узел без блокировки, вызовите метод Start.

using (host)
{
    host.Start();
    Console.ReadLine();
}

Если в метод Start передается список URL-адресов, он будет ожидать передачи данных по указанным URL-адресам.

var urls = new List<string>()
{
    "http://*:5000",
    "http://localhost:5001"
};

var host = new WebHostBuilder()
    .UseKestrel()
    .UseStartup<Startup>()
    .Start(urls.ToArray());

using (host)
{
    Console.ReadLine();
}

Приложение может инициализировать и запустить новый узел с использованием предварительно настроенных значений по умолчанию CreateDefaultBuilder с помощью статического удобного метода. Эти методы запускают сервер без выходных данных консоли и ожидают WaitForShutdown перерыва (CTRL-C/SIGINT или SIGTERM):

Start(RequestDelegate app)

Выполните запуск с помощью RequestDelegate:

using (var host = WebHost.Start(app => app.Response.WriteAsync("Hello, World!")))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

Выполните запрос в браузере к http://localhost:5000, чтобы получить ответ "Hello World!" WaitForShutdown блоков до тех пор, пока не будет выполнено прерывание (CTRL-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

Start(string url, RequestDelegate app)

Выполните запуск с помощью URL-адреса и RequestDelegate:

using (var host = WebHost.Start("http://localhost:8080", app => app.Response.WriteAsync("Hello, World!")))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании Start(RequestDelegate app), но приложение отвечает по адресу http://localhost:8080.

Start(Action<IRouteBuilder> routeBuilder)

Используйте экземпляр IRouteBuilder (Microsoft.AspNetCore.Routing) для применения ПО промежуточного слоя маршрутизации:

using (var host = WebHost.Start(router => router
    .MapGet("hello/{name}", (req, res, data) => 
        res.WriteAsync($"Hello, {data.Values["name"]}!"))
    .MapGet("buenosdias/{name}", (req, res, data) => 
        res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
    .MapGet("throw/{message?}", (req, res, data) => 
        throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
    .MapGet("{greeting}/{name}", (req, res, data) => 
        res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
    .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

В этом примере используйте следующие запросы в браузере:

Запросить Response
http://localhost:5000/hello/Martin Hello, Martin!
http://localhost:5000/buenosdias/Catrina Buenos dias, Catrina!
http://localhost:5000/throw/ooops! Вызывает исключение со строкой "ooops!"
http://localhost:5000/throw Вызывает исключение со строкой "Uh oh!"
http://localhost:5000/Sante/Kevin Sante, Kevin!
http://localhost:5000 Hello World!

WaitForShutdown блокируется, пока не будет создано прерывание (Ctrl-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

Start(string url, Action<IRouteBuilder> routeBuilder)

Используйте URL-адрес и экземпляр IRouteBuilder:

using (var host = WebHost.Start("http://localhost:8080", router => router
    .MapGet("hello/{name}", (req, res, data) => 
        res.WriteAsync($"Hello, {data.Values["name"]}!"))
    .MapGet("buenosdias/{name}", (req, res, data) => 
        res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
    .MapGet("throw/{message?}", (req, res, data) => 
        throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
    .MapGet("{greeting}/{name}", (req, res, data) => 
        res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
    .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании Start(Action<IRouteBuilder> routeBuilder), но приложение будет отвечать по адресу http://localhost:8080.

StartWith(Action<IApplicationBuilder> app)

Предоставьте делегат для настройки IApplicationBuilder:

using (var host = WebHost.StartWith(app => 
    app.Use(next => 
    {
        return async context => 
        {
            await context.Response.WriteAsync("Hello World!");
        };
    })))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Выполните запрос в браузере к http://localhost:5000, чтобы получить ответ "Hello World!" WaitForShutdown блоков до тех пор, пока не будет выполнено прерывание (CTRL-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

StartWith(string url, Action<IApplicationBuilder> app)

Предоставьте URL-адрес и делегат для настройки IApplicationBuilder:

using (var host = WebHost.StartWith("http://localhost:8080", app => 
    app.Use(next => 
    {
        return async context => 
        {
            await context.Response.WriteAsync("Hello World!");
        };
    })))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании StartWith(Action<IApplicationBuilder> app), но приложение будет отвечать по адресу http://localhost:8080.

Интерфейс IWebHostEnvironment

Интерфейс IWebHostEnvironment предоставляет сведения о среде веб-размещения приложения. Чтобы получить интерфейс IWebHostEnvironment для использования его свойств и методов расширения, воспользуйтесь внедрением конструктора:

public class CustomFileReader
{
    private readonly IWebHostEnvironment _env;

    public CustomFileReader(IWebHostEnvironment env)
    {
        _env = env;
    }

    public string ReadFile(string filePath)
    {
        var fileProvider = _env.WebRootFileProvider;
        // Process the file here
    }
}

Для настройки приложения при запуске в соответствии со средой можно применять подход на основе соглашения. Кроме того, можно внедрить интерфейс IWebHostEnvironment в конструктор Startup для использования в ConfigureServices:

public class Startup
{
    public Startup(IWebHostEnvironment env)
    {
        HostingEnvironment = env;
    }

    public IWebHostEnvironment HostingEnvironment { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        if (HostingEnvironment.IsDevelopment())
        {
            // Development configuration
        }
        else
        {
            // Staging/Production configuration
        }

        var contentRootPath = HostingEnvironment.ContentRootPath;
    }
}

Примечание.

Помимо метода расширения IsDevelopment, интерфейс IWebHostEnvironment предоставляет методы IsStaging, IsProduction и IsEnvironment(string environmentName). Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

Службу IWebHostEnvironment также можно внедрять непосредственно в метод Configure для настройки конвейера обработки:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        // In Development, use the Developer Exception Page
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // In Staging/Production, route exceptions to /error
        app.UseExceptionHandler("/error");
    }

    var contentRootPath = env.ContentRootPath;
}

IWebHostEnvironment можно внедрить в метод Invoke при создании пользовательского ПО промежуточного слоя:

public async Task Invoke(HttpContext context, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        // Configure middleware for Development
    }
    else
    {
        // Configure middleware for Staging/Production
    }

    var contentRootPath = env.ContentRootPath;
}

Интерфейс IHostApplicationLifetime

Интерфейс IHostApplicationLifetime позволяет выполнять действия после запуска и завершения работы. Три свойства этого интерфейса представляют собой токены отмены, которые служат для регистрации методов Action, определяющих события запуска и завершения работы.

Токен отмены Условие инициации…
ApplicationStarted Узел полностью запущен.
ApplicationStopped Заканчивается нормальное завершение работы узла. Все запросы должны быть обработаны. Завершение работы блокируется до тех пор, пока это событие не завершится.
ApplicationStopping Происходит нормальное завершение работы узла. Запросы могут все еще обрабатываться. Завершение работы блокируется до тех пор, пока это событие не завершится.
public class Startup
{
    public void Configure(IApplicationBuilder app, IHostApplicationLifetime appLifetime)
    {
        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
        appLifetime.ApplicationStopped.Register(OnStopped);

        Console.CancelKeyPress += (sender, eventArgs) =>
        {
            appLifetime.StopApplication();
            // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
            eventArgs.Cancel = true;
        };
    }

    private void OnStarted()
    {
        // Perform post-startup activities here
    }

    private void OnStopping()
    {
        // Perform on-stopping activities here
    }

    private void OnStopped()
    {
        // Perform post-stopped activities here
    }
}

Метод StopApplication запрашивает остановку приложения. Следующий класс использует StopApplication для корректного завершения работы приложения при вызове метода класса Shutdown:

public class MyClass
{
    private readonly IHostApplicationLifetime _appLifetime;

    public MyClass(IHostApplicationLifetime appLifetime)
    {
        _appLifetime = appLifetime;
    }

    public void Shutdown()
    {
        _appLifetime.StopApplication();
    }
}

Проверка области

CreateDefaultBuilder Устанавливает для ServiceProviderOptions.ValidateScopes значение true, если приложение находится в среде разработки.

Если для ValidateScopes установлено значение true, поставщик службы по умолчанию проверяет, что:

  • Службы с заданной областью не разрешаются из корневого поставщика службы, прямо или косвенно.
  • Службы с заданной областью не вводятся в одноэлементные объекты, прямо или косвенно.

Корневой поставщик службы создается при вызове BuildServiceProvider. Время существования корневого поставщика службы соответствует времени существования приложения или сервера — поставщик запускается с приложением и удаляется, когда приложение завершает работу.

Службы с заданной областью удаляются создавшим их контейнером. Если служба с заданной областью создается в корневом контейнере, время существования службы повышается до уровня одноэлементного объекта, поскольку она удаляется только корневым контейнером при завершении работы приложения или сервера. Проверка областей службы перехватывает эти ситуации при вызове BuildServiceProvider.

Чтобы всегда проверять область, в том числе в рабочей среде, настройте ServiceProviderOptions его в UseDefaultServiceProvider построителе узлов:

WebHost.CreateDefaultBuilder(args)
    .UseDefaultServiceProvider((context, options) => {
        options.ValidateScopes = true;
    })

Дополнительные ресурсы

Приложения ASP.NET Core настраивают и запускают узел. Узел отвечает за запуск приложения и управление временем существования. Узел настраивает как минимум сервер и конвейер обработки запросов. Узел также может настроить ведение журнала, внедрение зависимостей и конфигурацию.

В этой статье описывается веб-узел, доступ к которому предоставляется только для обеспечения обратной совместимости. Шаблоны ASP.NET Core создают универсальный узел .NET, который рекомендуется для всех типов приложений.

Создание узла

Создание узла с помощью экземпляра IWebHostBuilder. Обычно это делается в точке входа в приложение, то есть в методе Main.

В шаблонах проектов Main находится в Program.cs. Типичные вызовы CreateDefaultBuilder приложения для запуска настройки узла:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

Код, который вызывает CreateDefaultBuilder, находится в методе CreateWebHostBuilder, что отделяет его от кода в методе Main, который вызывает Run для объекта построителя. Такое отделение требуется, если вы используете инструменты Entity Framework Core. Эти инструменты используют метод CreateWebHostBuilder, который они могут вызвать во время разработки для настройки узла без необходимости запускать приложение. В качестве альтернативного способа можно использовать реализацию IDesignTimeDbContextFactory. Подробные сведения см. в статье Design-time DbContext Creation (Создание экземпляра DbContext во время разработки).

CreateDefaultBuilder выполняет следующие задачи:

Настройки, определенные CreateDefaultBuilder, можно переопределить и усилить с помощью ConfigureAppConfiguration, ConfigureLogging и других методов и методов расширения IWebHostBuilder. Ниже приведены некоторые примеры:

  • ConfigureAppConfiguration используется для указания дополнительного объекта IConfiguration для приложения. Следующий вызов ConfigureAppConfiguration добавляет делегата, чтобы включить конфигурацию приложения в файл appsettings.xml. ConfigureAppConfiguration можно вызывать несколько раз. Обратите внимание, что эта конфигурация не распространяется на узел (например, URL-адреса серверов или среду). См. раздел Значения конфигурации узла.

    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
        })
        ...
    
  • Следующий вызов ConfigureLogging добавляет делегата, чтобы настроить минимальный уровень ведения журнала (SetMinimumLevel) для LogLevel.Warning. Этот параметр переопределяет параметры в appsettings.Development.json (LogLevel.Debug) и appsettings.Production.json (LogLevel.Error) настроены CreateDefaultBuilder. ConfigureLogging можно вызывать несколько раз.

    WebHost.CreateDefaultBuilder(args)
        .ConfigureLogging(logging => 
        {
            logging.SetMinimumLevel(LogLevel.Warning);
        })
        ...
    
  • При следующем вызове к ConfigureKestrel переопределяется значение по умолчанию Limits.MaxRequestBodySize, равное 30 000 000 байтов, установленное при настройке Kestrel с помощью CreateDefaultBuilder:

    WebHost.CreateDefaultBuilder(args)
        .ConfigureKestrel((context, options) =>
        {
            options.Limits.MaxRequestBodySize = 20000000;
        });
    

Корень содержимого определяет, где узел ищет файлы содержимого, например файлы представлений MVC. При запуске приложения из корневой папки проекта эта папка используется в качестве корня содержимого. Такое поведение по умолчанию принято в Visual Studio и шаблонах dotnet new.

Дополнительные сведения о конфигурации приложения см. в разделе Конфигурация в ASP.NET Core.

Примечание.

Помимо использования статического метода CreateDefaultBuilder, в ASP.NET Core 2.x поддерживается создание узла на основе WebHostBuilder.

При настройке узла Configure и ConfigureServices методов можно предоставить. Если используется класс Startup, в нем должен быть определен метод Configure. Подробные сведения см. в статье Запуск приложения в ASP.NET Core. Несколько вызовов ConfigureServices добавляются друг к другу. При нескольких вызовах Configure или UseStartup в WebHostBuilder предыдущие параметры заменяются.

Значения конфигурации узла

WebHostBuilder использует следующие подходы для задания значений конфигурации узла:

  • конфигурация построителя узла, которая включает в себя переменные среды в формате ASPNETCORE_{configurationKey}, Например, ASPNETCORE_ENVIRONMENT.
  • Расширения, такие как UseContentRoot и UseConfiguration (см. раздел Переопределение конфигурации).
  • UseSetting и связанный ключ. Значение, задаваемое с помощью UseSetting, всегда является строкой независимо от типа.

Хост использует значение, заданное последним. Дополнительные сведения см. в подразделе Переопределение конфигурации следующего раздела.

Ключ приложения (имя)

Свойство IWebHostEnvironment.ApplicationName задается автоматически при вызове UseStartup или Configure во время создания узла. Значение присваивается имени сборки, содержащей точку входа приложения. Чтобы задать значение явным образом, используйте следующую WebHostDefaults.ApplicationKeyкоманду:

Ключ: applicationName
Тип: string
По умолчанию: имя сборки, содержащей точку входа приложения
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_APPLICATIONNAME

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")

Перехват ошибок при загрузке

Этот параметр управляет перехватом ошибок при загрузке.

Ключ: captureStartupErrors
Тип: bool (true или 1)
Значение по умолчанию: false, если только приложение не работает с сервером Kestrel за IIS; в этом случае значение по умолчанию — true.
Задается с помощью: CaptureStartupErrors
переменной среды: ASPNETCORE_CAPTURESTARTUPERRORS

Если задано значение false, ошибки во время запуска приводят к завершению работы узла. Если задано значение true, узел перехватывает исключения во время запуска и пытается запустить сервер.

WebHost.CreateDefaultBuilder(args)
    .CaptureStartupErrors(true)

Корневой каталог содержимого

Этот параметр определяет то, где ASP.NET Core начинает искать файлы содержимого.

Ключ: contentRoot
Тип: string
Значение по умолчанию: папка, в которой находится сборка приложения.
Задается с помощью: UseContentRoot
переменной среды: ASPNETCORE_CONTENTROOT

Корневой каталог содержимого также используется в качестве базового пути для корневого каталога документов. Если путь к корневому каталогу содержимого не существует, узел не запускается.

WebHost.CreateDefaultBuilder(args)
    .UseContentRoot("c:\\<content-root>")

Дополнительные сведения см. в разделе:

Подробные сообщения об ошибках

Определяет, следует ли перехватывать подробные сообщения об ошибках.

Ключ: detailedErrors
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_DETAILEDERRORS

Если этот параметр включен (или если параметр Среда имеет значение Development), приложение перехватывает подробные исключения.

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")

Среда

Задает среду приложения.

Ключ: environment
Тип: string
Значение по умолчанию: Production
Задается с помощью: UseEnvironment
переменной среды: ASPNETCORE_ENVIRONMENT

В качестве среды можно указать любое значение. В платформе определены значения Development, Staging и Production. Регистр символов в значениях не учитывается. По умолчанию значение параметра Среда считывается из переменной среды ASPNETCORE_ENVIRONMENT. При использовании Visual Studio переменные среды могут быть заданы в launchSettings.json файле. Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

WebHost.CreateDefaultBuilder(args)
    .UseEnvironment(EnvironmentName.Development)

Начальные сборки размещения

Задает начальные сборки размещения для приложения.

Ключ: hostingStartupAssemblies
Тип: string
Значение по умолчанию: пустая строка
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES

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

Хотя значением по умолчанию этого параметра конфигурации является пустая строка, начальные сборки размещения всегда включают в себя сборку приложения. Если начальные сборки размещения указаны, они добавляются к сборке приложения для загрузки во время построения приложением общих служб при запуске.

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")

Порт HTTPS

Задайте порт перенаправления HTTPS. Используется при принудительном применении HTTPS.

Ключ: https_port
Тип: string
Значение по умолчанию: значение по умолчанию не задано.
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HTTPS_PORTS

WebHost.CreateDefaultBuilder(args)
    .UseSetting("https_port", "8080")

Исключаемые начальные сборки размещения

Разделенная точками с запятой строка начальных сборок размещения, которые необходимо исключить при запуске.

Ключ: hostingStartupExcludeAssemblies
Тип: string
Значение по умолчанию: пустая строка
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")

Предпочитать URL-адреса размещения

Указывает, должен ли узел ожидать передачи данных по URL-адресам, настроенным с помощью WebHostBuilder, вместо настроенных с помощью реализации IServer.

Ключ: preferHostingUrls
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: PreferHostingUrls
переменной среды: ASPNETCORE_PREFERHOSTINGURLS

WebHost.CreateDefaultBuilder(args)
    .PreferHostingUrls(true)

Запретить запуск размещения

Запрещает автоматическую загрузку начальных сборок размещения, включая начальные сборки размещения, настроенные сборкой приложения. Дополнительные сведения см. в статье Использование начальных сборок размещения в ASP.NET Core.

Ключ: preventHostingStartup
Тип: bool (true или 1)
Значение по умолчанию: false
Задается с помощью: UseSetting
переменной среды: ASPNETCORE_PREVENTHOSTINGSTARTUP

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")

URL-адреса сервера

Задает IP-адреса или адреса узлов с портами и протоколами, по которым сервер должен ожидать получения запросов.

Ключ: urls
Тип: string
По умолчанию:http://localhost:5000
Задается с помощью: UseUrls
переменной среды: ASPNETCORE_URLS

Укажите разделенный точками с запятой (;) список префиксов URL-адресов, на которые сервер должен отвечать. Например, http://localhost:123. Используйте символ "*", чтобы указать, что сервер должен ожидать получения запросов через определенный порт и по определенному протоколу по любому IP-адресу или имени узла (например, http://*:5000). Протокол (http:// или https://) должен указываться для каждого URL-адреса. Поддерживаемые форматы зависят от сервера.

WebHost.CreateDefaultBuilder(args)
    .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")

Kestrel имеет собственный API настройки конечных точек. Дополнительные сведения см Kestrel . на веб-сервере в ASP.NET Core.

Время ожидания завершения работы

Определяет, как долго необходимо ожидать завершения работы веб-узла.

Ключ: shutdownTimeoutSeconds
Тип: int
Значение по умолчанию: 5
Задается с помощью: UseShutdownTimeout
переменной среды: ASPNETCORE_SHUTDOWNTIMEOUTSECONDS

Хотя ключ принимает значение int с UseSetting (например, .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")), метод расширения UseShutdownTimeout принимает TimeSpan.

Во время ожидания размещение:

  • Активирует IApplicationLifetime.ApplicationStopping.
  • Пытается остановить размещенные службы, записывая в журнал все ошибки для служб, которые не удалось остановить.

Если время ожидания истекает до остановки всех размещенных служб, активные службы останавливаются при завершении работы приложения. Службы останавливаются даже в том случае, если еще не завершили обработку. Если службе требуется дополнительное время для остановки, увеличьте время ожидания.

WebHost.CreateDefaultBuilder(args)
    .UseShutdownTimeout(TimeSpan.FromSeconds(10))

Стартовая сборка

Определяет сборку, в которой необходимо искать класс Startup.

Ключ: startupAssembly
Тип: string
Значение по умолчанию: сборка приложения
Задается с помощью: UseStartup
переменной среды: ASPNETCORE_STARTUPASSEMBLY

На сборку можно ссылаться по имени (string) или типу (TStartup). При вызове нескольких методов UseStartup приоритет имеет последний.

WebHost.CreateDefaultBuilder(args)
    .UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
    .UseStartup<TStartup>()

каталог документов

Задает относительный путь к статическим ресурсам приложения.

Ключ: webroot
Тип: string
По умолчанию: значение по умолчанию — wwwroot. Наличие пути {корневой_каталог_содержимого}/wwwroot обязательно. Если этот путь не существует, используется фиктивный поставщик файлов.
Задается с помощью: UseWebRoot
переменной среды: ASPNETCORE_WEBROOT

WebHost.CreateDefaultBuilder(args)
    .UseWebRoot("public")

Дополнительные сведения см. в разделе:

Переопределение конфигурации

Используйте конфигурацию для настройки веб-узла. В следующем примере конфигурация узла при необходимости указывается в hostsettings.json файле. Любая конфигурация, загруженная из hostsettings.json файла, может быть переопределена аргументами командной строки. Встроенная конфигурация (в config) используется для настройки узла с помощью UseConfiguration. Конфигурация IWebHostBuilder добавляется в конфигурацию приложения, но не наоборот — ConfigureAppConfiguration не влияет на конфигурацию IWebHostBuilder.

Переопределение конфигурации, предоставленной UseUrlshostsettings.json с помощью конфигурации, во-первых, второй аргумент командной строки:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("hostsettings.json", optional: true)
            .AddCommandLine(args)
            .Build();

        return WebHost.CreateDefaultBuilder(args)
            .UseUrls("http://*:5000")
            .UseConfiguration(config)
            .Configure(app =>
            {
                app.Run(context => 
                    context.Response.WriteAsync("Hello, World!"));
            });
    }
}

hostsettings.json:

{
    urls: "http://*:5005"
}

Примечание.

UseConfiguration копирует ключи только из предоставленного объекта IConfiguration для конфигурации конструктора узла. Поэтому указание reloadOnChange: true для файлов JSON, XML и INI не имеет никакого эффекта.

Чтобы указать узел, выполняющийся по определенному URL-адресу, можно передать нужное значение из командной строки при выполнении команды dotnet run. Аргумент командной строки переопределяет urls значение из hostsettings.json файла, а сервер прослушивает порт 8080:

dotnet run --urls "http://*:8080"

Управление узлом

Выполнить

Метод Run запускает веб-приложение и блокирует вызывающий поток до тех пор, пока работа узла не будет завершена.

host.Run();

Начало

Чтобы запустить узел без блокировки, вызовите метод Start.

using (host)
{
    host.Start();
    Console.ReadLine();
}

Если в метод Start передается список URL-адресов, он будет ожидать передачи данных по указанным URL-адресам.

var urls = new List<string>()
{
    "http://*:5000",
    "http://localhost:5001"
};

var host = new WebHostBuilder()
    .UseKestrel()
    .UseStartup<Startup>()
    .Start(urls.ToArray());

using (host)
{
    Console.ReadLine();
}

Приложение может инициализировать и запустить новый узел с использованием предварительно настроенных значений по умолчанию CreateDefaultBuilder с помощью статического удобного метода. Эти методы запускают сервер без выходных данных консоли и ожидают WaitForShutdown перерыва (CTRL-C/SIGINT или SIGTERM):

Start(RequestDelegate app)

Выполните запуск с помощью RequestDelegate:

using (var host = WebHost.Start(app => app.Response.WriteAsync("Hello, World!")))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

Выполните запрос в браузере к http://localhost:5000, чтобы получить ответ "Hello World!" WaitForShutdown блоков до тех пор, пока не будет выполнено прерывание (CTRL-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

Start(string url, RequestDelegate app)

Выполните запуск с помощью URL-адреса и RequestDelegate:

using (var host = WebHost.Start("http://localhost:8080", app => app.Response.WriteAsync("Hello, World!")))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании Start(RequestDelegate app), но приложение отвечает по адресу http://localhost:8080.

Start(Action<IRouteBuilder> routeBuilder)

Используйте экземпляр IRouteBuilder (Microsoft.AspNetCore.Routing) для применения ПО промежуточного слоя маршрутизации:

using (var host = WebHost.Start(router => router
    .MapGet("hello/{name}", (req, res, data) => 
        res.WriteAsync($"Hello, {data.Values["name"]}!"))
    .MapGet("buenosdias/{name}", (req, res, data) => 
        res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
    .MapGet("throw/{message?}", (req, res, data) => 
        throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
    .MapGet("{greeting}/{name}", (req, res, data) => 
        res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
    .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
    Console.WriteLine("Use Ctrl-C to shutdown the host...");
    host.WaitForShutdown();
}

В этом примере используйте следующие запросы в браузере:

Запросить Response
http://localhost:5000/hello/Martin Hello, Martin!
http://localhost:5000/buenosdias/Catrina Buenos dias, Catrina!
http://localhost:5000/throw/ooops! Вызывает исключение со строкой "ooops!"
http://localhost:5000/throw Вызывает исключение со строкой "Uh oh!"
http://localhost:5000/Sante/Kevin Sante, Kevin!
http://localhost:5000 Hello World!

WaitForShutdown блокируется, пока не будет создано прерывание (Ctrl-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

Start(string url, Action<IRouteBuilder> routeBuilder)

Используйте URL-адрес и экземпляр IRouteBuilder:

using (var host = WebHost.Start("http://localhost:8080", router => router
    .MapGet("hello/{name}", (req, res, data) => 
        res.WriteAsync($"Hello, {data.Values["name"]}!"))
    .MapGet("buenosdias/{name}", (req, res, data) => 
        res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
    .MapGet("throw/{message?}", (req, res, data) => 
        throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
    .MapGet("{greeting}/{name}", (req, res, data) => 
        res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
    .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании Start(Action<IRouteBuilder> routeBuilder), но приложение будет отвечать по адресу http://localhost:8080.

StartWith(Action<IApplicationBuilder> app)

Предоставьте делегат для настройки IApplicationBuilder:

using (var host = WebHost.StartWith(app => 
    app.Use(next => 
    {
        return async context => 
        {
            await context.Response.WriteAsync("Hello World!");
        };
    })))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Выполните запрос в браузере к http://localhost:5000, чтобы получить ответ "Hello World!" WaitForShutdown блоков до тех пор, пока не будет выполнено прерывание (CTRL-C/SIGINT или SIGTERM). Приложение выводит сообщение Console.WriteLine и ожидает нажатия клавиши, после чего завершает работу.

StartWith(string url, Action<IApplicationBuilder> app)

Предоставьте URL-адрес и делегат для настройки IApplicationBuilder:

using (var host = WebHost.StartWith("http://localhost:8080", app => 
    app.Use(next => 
    {
        return async context => 
        {
            await context.Response.WriteAsync("Hello World!");
        };
    })))
{
    Console.WriteLine("Use Ctrl-C to shut down the host...");
    host.WaitForShutdown();
}

Результат будет тем же, что и при использовании StartWith(Action<IApplicationBuilder> app), но приложение будет отвечать по адресу http://localhost:8080.

Интерфейс IWebHostEnvironment

Интерфейс IWebHostEnvironment предоставляет сведения о среде веб-размещения приложения. Чтобы получить интерфейс IWebHostEnvironment для использования его свойств и методов расширения, воспользуйтесь внедрением конструктора:

public class CustomFileReader
{
    private readonly IWebHostEnvironment _env;

    public CustomFileReader(IWebHostEnvironment env)
    {
        _env = env;
    }

    public string ReadFile(string filePath)
    {
        var fileProvider = _env.WebRootFileProvider;
        // Process the file here
    }
}

Для настройки приложения при запуске в соответствии со средой можно применять подход на основе соглашения. Кроме того, можно внедрить интерфейс IWebHostEnvironment в конструктор Startup для использования в ConfigureServices:

public class Startup
{
    public Startup(IWebHostEnvironment env)
    {
        HostingEnvironment = env;
    }

    public IWebHostEnvironment HostingEnvironment { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        if (HostingEnvironment.IsDevelopment())
        {
            // Development configuration
        }
        else
        {
            // Staging/Production configuration
        }

        var contentRootPath = HostingEnvironment.ContentRootPath;
    }
}

Примечание.

Помимо метода расширения IsDevelopment, интерфейс IWebHostEnvironment предоставляет методы IsStaging, IsProduction и IsEnvironment(string environmentName). Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

Службу IWebHostEnvironment также можно внедрять непосредственно в метод Configure для настройки конвейера обработки:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        // In Development, use the Developer Exception Page
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // In Staging/Production, route exceptions to /error
        app.UseExceptionHandler("/error");
    }

    var contentRootPath = env.ContentRootPath;
}

IWebHostEnvironment можно внедрить в метод Invoke при создании пользовательского ПО промежуточного слоя:

public async Task Invoke(HttpContext context, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        // Configure middleware for Development
    }
    else
    {
        // Configure middleware for Staging/Production
    }

    var contentRootPath = env.ContentRootPath;
}

Интерфейс IHostApplicationLifetime

Интерфейс IHostApplicationLifetime позволяет выполнять действия после запуска и завершения работы. Три свойства этого интерфейса представляют собой токены отмены, которые служат для регистрации методов Action, определяющих события запуска и завершения работы.

Токен отмены Условие инициации…
ApplicationStarted Узел полностью запущен.
ApplicationStopped Заканчивается нормальное завершение работы узла. Все запросы должны быть обработаны. Завершение работы блокируется до тех пор, пока это событие не завершится.
ApplicationStopping Происходит нормальное завершение работы узла. Запросы могут все еще обрабатываться. Завершение работы блокируется до тех пор, пока это событие не завершится.
public class Startup
{
    public void Configure(IApplicationBuilder app, IHostApplicationLifetime appLifetime)
    {
        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
        appLifetime.ApplicationStopped.Register(OnStopped);

        Console.CancelKeyPress += (sender, eventArgs) =>
        {
            appLifetime.StopApplication();
            // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
            eventArgs.Cancel = true;
        };
    }

    private void OnStarted()
    {
        // Perform post-startup activities here
    }

    private void OnStopping()
    {
        // Perform on-stopping activities here
    }

    private void OnStopped()
    {
        // Perform post-stopped activities here
    }
}

Метод StopApplication запрашивает остановку приложения. Следующий класс использует StopApplication для корректного завершения работы приложения при вызове метода класса Shutdown:

public class MyClass
{
    private readonly IHostApplicationLifetime _appLifetime;

    public MyClass(IHostApplicationLifetime appLifetime)
    {
        _appLifetime = appLifetime;
    }

    public void Shutdown()
    {
        _appLifetime.StopApplication();
    }
}

Проверка области

CreateDefaultBuilder Устанавливает для ServiceProviderOptions.ValidateScopes значение true, если приложение находится в среде разработки.

Если для ValidateScopes установлено значение true, поставщик службы по умолчанию проверяет, что:

  • Службы с заданной областью не разрешаются из корневого поставщика службы, прямо или косвенно.
  • Службы с заданной областью не вводятся в одноэлементные объекты, прямо или косвенно.

Корневой поставщик службы создается при вызове BuildServiceProvider. Время существования корневого поставщика службы соответствует времени существования приложения или сервера — поставщик запускается с приложением и удаляется, когда приложение завершает работу.

Службы с заданной областью удаляются создавшим их контейнером. Если служба с заданной областью создается в корневом контейнере, время существования службы повышается до уровня одноэлементного объекта, поскольку она удаляется только корневым контейнером при завершении работы приложения или сервера. Проверка областей службы перехватывает эти ситуации при вызове BuildServiceProvider.

Чтобы всегда проверять область, в том числе в рабочей среде, настройте ServiceProviderOptions его в UseDefaultServiceProvider построителе узлов:

WebHost.CreateDefaultBuilder(args)
    .UseDefaultServiceProvider((context, options) => {
        options.ValidateScopes = true;
    })

Дополнительные ресурсы