Inicialização de aplicativo no ASP.NET Core

Por Rick Anderson, Tom Dykstra e Steve Smith

A classe Startup configura serviços e o pipeline de solicitação do aplicativo.

A classe Startup

Os aplicativos do ASP.NET Core usam uma classe Startup, que é chamada de Startup por convenção. A classe Startup:

  • Opcionalmente, inclua um método ConfigureServices para configurar os serviços do aplicativo. Um serviço é um componente reutilizável que fornece a funcionalidade do aplicativo. Os serviços são registrados no ConfigureServices e consumidos no aplicativo por meio da DI (injeção de dependência) ou ApplicationServices .
  • Inclui um método Configure para criar o pipeline de processamento de solicitações do aplicativo.

ConfigureServices e Configure são chamados pelo runtime do ASP.NET Core quando o aplicativo é iniciado:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

O exemplo anterior é para Razor Pages; a versão do MVC é semelhante.

A classe Startup é especificada quando o host do aplicativo é criado. A classe normalmente é especificada chamando o método Startup WebHostBuilderExtensions.UseStartup <TStartup> no construtor de host:

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

O host fornece serviços que estão disponíveis para o construtor de classe Startup. O aplicativo adiciona serviços adicionais por meio de ConfigureServices. Os serviços de aplicativos e o host ficam disponíveis em Configure e em todo o aplicativo.

Somente os seguintes tipos de serviço podem ser injetados no Startup construtor ao usar o Host Genérico ( IHostBuilder ):

public class Startup
{
    private readonly IWebHostEnvironment _env;

    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
        Configuration = configuration;
        _env = env;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        if (_env.IsDevelopment())
        {
        }
        else
        {
        }
    }
}

A maioria dos serviços não está disponível até o método Configure ser chamado.

Inicialização múltipla

Quando o aplicativo define classes Startup separadas para ambientes diferentes (por exemplo, StartupDevelopment), a classe Startup apropriada é selecionada no runtime. A classe cujo sufixo do nome corresponde ao ambiente atual é priorizada. Se o aplicativo for executado no ambiente de desenvolvimento e incluir uma classe Startup e uma classe StartupDevelopment, a classe StartupDevelopment será usada. Para obter mais informações, veja Usar vários ambientes.

Veja O host para obter mais informações sobre o host. Para obter informações sobre como tratar erros durante a inicialização, consulte Tratamento de exceção na inicialização.

O método ConfigureServices

O método ConfigureServices é:

  • Opcional.
  • Chamado pelo host antes do método Configure para configurar os serviços do aplicativo.
  • Quando as opções de configuração são definidas por convenção.

O host pode configurar alguns serviços antes que métodos Startup sejam chamados. Para obter mais informações, confira O host.

Para recursos que exigem uma configuração significativa, há métodos de extensão Add{Service} em IServiceCollection. Por exemplo, Adicionar DbContext, Adicionar Identity Padrão, Adicionar EntityFrameworkStores e Adicionar Razor Páginas:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(
            options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddRazorPages();
    }

Adicionar serviços ao contêiner de serviços os torna disponíveis dentro do aplicativo e no método Configure. Os serviços são resolvidos por meio da injeção de dependência ou de ApplicationServices.

O método Configure

O método Configure é usado para especificar como o aplicativo responde às solicitações HTTP. O pipeline de solicitação é configurado adicionando componentes de middleware a uma instância de IApplicationBuilder. IApplicationBuilder está disponível para o método Configure, mas não é registrado no contêiner de serviço. A hospedagem cria um IApplicationBuilder e o passa diretamente para Configure.

Os modelos do ASP.NET Core configuram o pipeline com suporte para:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

O exemplo anterior é para Razor Pages; a versão do MVC é semelhante.

Cada método de extensão Use adiciona um ou mais componentes de middleware ao pipeline de solicitação. Por exemplo, UseStaticFiles configura o middleware para atender arquivos estáticos.

Cada componente de middleware no pipeline de solicitação é responsável por invocar o próximo componente no pipeline ou causar um curto-circuito da cadeia, se apropriado.

Serviços adicionais, como IWebHostEnvironment, ILoggerFactory ou qualquer coisa definida em ConfigureServices, podem ser especificados na assinatura do método Configure. Esses serviços serão injetados se estiverem disponíveis.

Para obter mais informações de como usar o IApplicationBuilder e a ordem de processamento de middleware, confira Middleware do ASP.NET Core.

Configurar serviços sem Inicialização

Para configurar serviços e o pipeline de processamento de solicitação sem usar uma classe Startup, chame os métodos de conveniência ConfigureServices e Configure no construtor do host. Diversas chamadas para ConfigureServices são acrescentadas umas às outras. Se houver várias chamadas de método Configure, a última chamada de Configure será usada.

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.ConfigureServices(services =>
                {
                    services.AddControllersWithViews();
                })
                .Configure(app =>
                {
                    var loggerFactory = app.ApplicationServices
                        .GetRequiredService<ILoggerFactory>();
                    var logger = loggerFactory.CreateLogger<Program>();
                    var env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
                    var config = app.ApplicationServices.GetRequiredService<IConfiguration>();

                    logger.LogInformation("Logged in Configure");

                    if (env.IsDevelopment())
                    {
                        app.UseDeveloperExceptionPage();
                    }
                    else
                    {
                        app.UseExceptionHandler("/Home/Error");
                        app.UseHsts();
                    }

                    var configValue = config["MyConfigKey"];
                });
            });
        });
}

Estender a inicialização com filtros de inicialização

Use IStartupFilter :

  • Para configurar o middleware no início ou no final do pipeline configurar middleware de um aplicativo sem uma chamada explícita para Use{Middleware} . IStartupFilter é usado pelo ASP.NET Core para adicionar padrões ao início do pipeline sem precisar fazer com que o autor do aplicativo registre explicitamente o middleware padrão. IStartupFilter permite que um componente diferente chame Use{Middleware} em nome do autor do aplicativo.
  • Para criar um pipeline Configure de métodos. IStartupFilter.Configure pode definir um middleware para ser executado antes ou depois do middleware adicionado pelas bibliotecas.

IStartupFilter implementa Configure, que recebe e retorna um Action<IApplicationBuilder>. Um IApplicationBuilder define uma classe para configurar o pipeline de solicitação do aplicativo. Para obter mais informações, confira Criar um pipeline de middleware com o IApplicationBuilder.

Cada IStartupFilter pode adicionar um ou mais middlewares no pipeline de solicitação. Os filtros são invocados na ordem em que foram adicionados ao contêiner de serviço. Filtros podem adicionar middleware antes ou depois de passar o controle para o filtro seguinte, de modo que eles são acrescentados ao início ou no final do pipeline de aplicativo.

O exemplo a seguir demonstra como registrar um middleware com IStartupFilter. O middleware RequestSetOptionsMiddleware define um valor de opção de um parâmetro de cadeia de caracteres de consulta:

public class RequestSetOptionsMiddleware
{
    private readonly RequestDelegate _next;

    public RequestSetOptionsMiddleware( RequestDelegate next )
    {
        _next = next;
    }

    // Test with https://localhost:5001/Privacy/?option=Hello
    public async Task Invoke(HttpContext httpContext)
    {
        var option = httpContext.Request.Query["option"];

        if (!string.IsNullOrWhiteSpace(option))
        {
            httpContext.Items["option"] = WebUtility.HtmlEncode(option);
        }

        await _next(httpContext);
    }
}

O RequestSetOptionsMiddleware é configurado na classe RequestSetOptionsStartupFilter:

public class RequestSetOptionsStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder =>
        {
            builder.UseMiddleware<RequestSetOptionsMiddleware>();
            next(builder);
        };
    }
}

O IStartupFilter é registrado no contêiner de serviço em ConfigureServices.

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
           .ConfigureAppConfiguration((hostingContext, config) =>
           {
           })
         .ConfigureWebHostDefaults(webBuilder =>
         {
             webBuilder.UseStartup<Startup>();
         })
        .ConfigureServices(services =>
        {
            services.AddTransient<IStartupFilter,
                      RequestSetOptionsStartupFilter>();
        });
}

Quando um parâmetro de cadeia de caracteres de consulta para option é fornecido, o middleware processa a atribuição de valor antes que o middleware do ASP.NET Core renderize a resposta.

A ordem de execução do middleware é definida pela ordem dos registros IStartupFilter:

  • Várias implementações de IStartupFilter podem interagir com os mesmos objetos. Se a ordem for importante, ordene seus registros de serviço IStartupFilter para corresponder à ordem em que os middlewares devem ser executados.

  • Bibliotecas podem adicionar middleware com uma ou mais implementações de IStartupFilter que são executadas antes ou depois de outro middleware de aplicativo registrado com IStartupFilter. Para invocar um middleware IStartupFilter antes de um middleware adicionado pelo IStartupFilter de uma biblioteca:

    • Posicione o registro do serviço antes que a biblioteca seja adicionada ao contêiner de serviço.
    • Para invocá-lo posteriormente, posicione o registro do serviço após a biblioteca ser adicionada.

Adicionar configuração na inicialização usando um assembly externo

Uma implementação IHostingStartup permite adicionar melhorias a um aplicativo durante a inicialização de um assembly externo fora da classe Startup do aplicativo. Para obter mais informações, consulte Usar assemblies de inicialização de hospedagem no ASP.NET Core.

Recursos adicionais

A classe Startup

Os aplicativos do ASP.NET Core usam uma classe Startup, que é chamada de Startup por convenção. A classe Startup:

  • Opcionalmente, inclua um método ConfigureServices para configurar os serviços do aplicativo. Um serviço é um componente reutilizável que fornece a funcionalidade do aplicativo. Os serviços são registrados no ConfigureServices e consumidos no aplicativo por meio da DI (injeção de dependência) ou ApplicationServices .
  • Inclui um método Configure para criar o pipeline de processamento de solicitações do aplicativo.

ConfigureServices e Configure são chamados pelo runtime do ASP.NET Core quando o aplicativo é iniciado:

public class Startup
{
    // Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    }

    // Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app)
    {
        ...
    }
}

A classe Startup é especificada quando o host do aplicativo é criado. A classe normalmente é especificada chamando o método Startup WebHostBuilderExtensions.UseStartup <TStartup> no construtor de host:

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

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

O host fornece serviços que estão disponíveis para o construtor de classe Startup. O aplicativo adiciona serviços adicionais por meio de ConfigureServices. Os serviços de aplicativos e o host ficam, então, disponíveis em Configure e em todo o aplicativo.

Um uso comum da injeção de dependência na classe Startup é injetar:

public class Startup
{
    private readonly IHostingEnvironment _env;
    private readonly IConfiguration _config;
    private readonly ILoggerFactory _loggerFactory;

    public Startup(IHostingEnvironment env, IConfiguration config, 
        ILoggerFactory loggerFactory)
    {
        _env = env;
        _config = config;
        _loggerFactory = loggerFactory;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        var logger = _loggerFactory.CreateLogger<Startup>();

        if (_env.IsDevelopment())
        {
            // Development service configuration

            logger.LogInformation("Development environment");
        }
        else
        {
            // Non-development service configuration

            logger.LogInformation("Environment: {EnvironmentName}", _env.EnvironmentName);
        }

        // Configuration is available during startup.
        // Examples:
        //   _config["key"]
        //   _config["subsection:suboption1"]
    }
}

A maioria dos serviços não está disponível até o método Configure ser chamado.

Inicialização múltipla

Quando o aplicativo define classes Startup separadas para ambientes diferentes (por exemplo, StartupDevelopment), a classe Startup apropriada é selecionada no runtime. A classe cujo sufixo do nome corresponde ao ambiente atual é priorizada. Se o aplicativo for executado no ambiente de desenvolvimento e incluir uma classe Startup e uma classe StartupDevelopment, a classe StartupDevelopment será usada. Para obter mais informações, veja Usar vários ambientes.

Veja O host para obter mais informações sobre o host. Para obter informações sobre como tratar erros durante a inicialização, consulte Tratamento de exceção na inicialização.

O método ConfigureServices

O método ConfigureServices é:

  • Opcional.
  • Chamado pelo host antes do método Configure para configurar os serviços do aplicativo.
  • Quando as opções de configuração são definidas por convenção.

O host pode configurar alguns serviços antes que métodos Startup sejam chamados. Para obter mais informações, confira O host.

Para recursos que exigem uma configuração significativa, há métodos de extensão Add{Service} em IServiceCollection. Por exemplo, Adicionar DbContext, Adicionar Identity Padrão, Adicionar EntityFrameworkStores e Adicionar Razor Páginas:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();


    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

Adicionar serviços ao contêiner de serviços os torna disponíveis dentro do aplicativo e no método Configure. Os serviços são resolvidos por meio da injeção de dependência ou de ApplicationServices.

Confira SetCompatibilityVersion para obter mais informações sobre SetCompatibilityVersion.

O método Configure

O método Configure é usado para especificar como o aplicativo responde às solicitações HTTP. O pipeline de solicitação é configurado adicionando componentes de middleware a uma instância de IApplicationBuilder. IApplicationBuilder está disponível para o método Configure, mas não é registrado no contêiner de serviço. A hospedagem cria um IApplicationBuilder e o passa diretamente para Configure.

Os modelos do ASP.NET Core configuram o pipeline com suporte para:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc();
}

Cada método de extensão Use adiciona um ou mais componentes de middleware ao pipeline de solicitação. Por exemplo, UseStaticFiles configura o middleware para atender arquivos estáticos.

Cada componente de middleware no pipeline de solicitação é responsável por invocar o próximo componente no pipeline ou causar um curto-circuito da cadeia, se apropriado.

Serviços adicionais, como IHostingEnvironment e ILoggerFactory ou qualquer coisa definida em ConfigureServices, podem ser especificados na assinatura do método Configure. Esses serviços serão injetados se estiverem disponíveis.

Para obter mais informações de como usar o IApplicationBuilder e a ordem de processamento de middleware, confira Middleware do ASP.NET Core.

Configurar serviços sem Inicialização

Para configurar serviços e o pipeline de processamento de solicitação sem usar uma classe Startup, chame os métodos de conveniência ConfigureServices e Configure no construtor do host. Diversas chamadas para ConfigureServices são acrescentadas umas às outras. Se houver várias chamadas de método Configure, a última chamada de Configure será usada.

public class Program
{
    public static IHostingEnvironment HostingEnvironment { get; set; }
    public static IConfiguration Configuration { get; set; }

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
            })
            .ConfigureServices(services =>
            {
                ...
            })
            .Configure(app =>
            {
                var loggerFactory = app.ApplicationServices
                    .GetRequiredService<ILoggerFactory>();
                var logger = loggerFactory.CreateLogger<Program>();
                var env = app.ApplicationServices.GetRequiredService<IHostingEnvironment>();
                var config = app.ApplicationServices.GetRequiredService<IConfiguration>();

                logger.LogInformation("Logged in Configure");

                if (env.IsDevelopment())
                {
                    ...
                }
                else
                {
                    ...
                }

                var configValue = config["subsection:suboption1"];

                ...
            });
}

Estender a inicialização com filtros de inicialização

Use IStartupFilter :

  • Para configurar o middleware no início ou no final de um pipeline de middleware de configuração de um aplicativo sem uma chamada explícita para Use{Middleware} . IStartupFilter é usado pelo ASP.NET Core para adicionar padrões ao início do pipeline sem precisar fazer com que o autor do aplicativo registre explicitamente o middleware padrão. IStartupFilter permite uma chamada de componente diferente Use{Middleware} em nome do autor do aplicativo.
  • Para criar um pipeline de Configure métodos. IStartupFilter.Configure pode definir um middleware para ser executado antes ou depois do middleware adicionado pelas bibliotecas.

IStartupFilter implementa Configure, que recebe e retorna um Action<IApplicationBuilder>. Um IApplicationBuilder define uma classe para configurar o pipeline de solicitação do aplicativo. Para obter mais informações, confira Criar um pipeline de middleware com o IApplicationBuilder.

Cada IStartupFilter pode adicionar um ou mais middlewares no pipeline de solicitação. Os filtros são invocados na ordem em que foram adicionados ao contêiner de serviço. Filtros podem adicionar middleware antes ou depois de passar o controle para o filtro seguinte, de modo que eles são acrescentados ao início ou no final do pipeline de aplicativo.

O exemplo a seguir demonstra como registrar um middleware com IStartupFilter. O middleware RequestSetOptionsMiddleware define um valor de opção de um parâmetro de cadeia de caracteres de consulta:

public class RequestSetOptionsMiddleware
{
    private readonly RequestDelegate _next;
    private IOptions<AppOptions> _injectedOptions;

    public RequestSetOptionsMiddleware(
        RequestDelegate next, IOptions<AppOptions> injectedOptions)
    {
        _next = next;
        _injectedOptions = injectedOptions;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        Console.WriteLine("RequestSetOptionsMiddleware.Invoke");

        var option = httpContext.Request.Query["option"];

        if (!string.IsNullOrWhiteSpace(option))
        {
            _injectedOptions.Value.Option = WebUtility.HtmlEncode(option);
        }

        await _next(httpContext);
    }
}

O RequestSetOptionsMiddleware é configurado na classe RequestSetOptionsStartupFilter:

public class RequestSetOptionsStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder =>
        {
            builder.UseMiddleware<RequestSetOptionsMiddleware>();
            next(builder);
        };
    }
}

O IStartupFilter é registrado no contêiner de serviço em ConfigureServices.

WebHost.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddTransient<IStartupFilter, 
            RequestSetOptionsStartupFilter>();
    })
    .UseStartup<Startup>()
    .Build();

Quando um parâmetro de cadeia de caracteres de consulta para option é fornecido, o middleware processa a atribuição de valor antes que o middleware do ASP.NET Core renderize a resposta.

A ordem de execução do middleware é definida pela ordem dos registros IStartupFilter:

  • Várias implementações de IStartupFilter podem interagir com os mesmos objetos. Se a ordem for importante, ordene seus registros de serviço IStartupFilter para corresponder à ordem em que os middlewares devem ser executados.

  • Bibliotecas podem adicionar middleware com uma ou mais implementações de IStartupFilter que são executadas antes ou depois de outro middleware de aplicativo registrado com IStartupFilter. Para invocar um middleware IStartupFilter antes de um middleware adicionado pelo IStartupFilter de uma biblioteca:

    • Posicione o registro do serviço antes que a biblioteca seja adicionada ao contêiner de serviço.
    • Para invocá-lo posteriormente, posicione o registro do serviço após a biblioteca ser adicionada.

Adicionar configuração na inicialização usando um assembly externo

Uma implementação IHostingStartup permite adicionar melhorias a um aplicativo durante a inicialização de um assembly externo fora da classe Startup do aplicativo. Para obter mais informações, consulte Usar assemblies de inicialização de hospedagem no ASP.NET Core.

Recursos adicionais