Avvio dell'app in ASP.NET CoreApp startup in ASP.NET Core

Di Rick Anderson, Tom Dykstra, Luke Latham e Steve SmithBy Rick Anderson, Tom Dykstra, Luke Latham, and Steve Smith

La classe Startup configura i servizi e la pipeline delle richieste dell'app.The Startup class configures services and the app's request pipeline.

Classe StartupThe Startup class

Le app ASP.NET Core usano una classe Startup denominata Startup per convenzione.ASP.NET Core apps use a Startup class, which is named Startup by convention. La classe Startup:The Startup class:

  • Include facoltativamente un metodo ConfigureServices per configurare i servizi dell'app.Optionally includes a ConfigureServices method to configure the app's services. Un servizio è un componente riutilizzabile che fornisce la funzionalità delle app.A service is a reusable component that provides app functionality. I servizi sono configurati (operazione nota anche come registrazione in ConfigureServices e vengono utilizzati nell'app tramite inserimento delle dipendenze o ApplicationServices.Services are configured—also described as registered—in ConfigureServices and consumed across the app via dependency injection (DI) or ApplicationServices.
  • Include un metodo Configure per creare la pipeline di elaborazione delle richieste dell'app.Includes a Configure method to create the app's request processing pipeline.

ConfigureServices e Configure sono chiamate dal runtime di ASP.NET Core all'avvio dell'app:ConfigureServices and Configure are called by the ASP.NET Core runtime when the app starts:

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();
        });
    }
}

L'esempio precedente è per Razor Pages. La versione per MVC è simile.The preceding sample is for Razor Pages; the MVC version is similar.

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)
    {
        ...
    }
}

La classe Startup viene specificata al momento della compilazione dell'host dell'app.The Startup class is specified when the app's host is built. La classe Startup viene in genere specificata chiamando il metodo WebHostBuilderExtensions.UseStartup<TStartup> nel generatore host:The Startup class is typically specified by calling the WebHostBuilderExtensions.UseStartup<TStartup> method on the host builder:

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}
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>();
            });
}

L'host fornisce i servizi disponibili al costruttore della classe Startup.The host provides services that are available to the Startup class constructor. L'app aggiunge servizi aggiuntivi tramite ConfigureServices.The app adds additional services via ConfigureServices. I servizi dell'host e dell'app saranno disponibili in Configure e nell'app.Both the host and app services are available in Configure and throughout the app.

Quando si usa IHostBuilder è possibile inserire nel costruttore Startup solo i tipi di servizio seguenti:Only the following service types can be injected into the Startup constructor when using IHostBuilder:

public class Startup
{
    private readonly IWebHostEnvironment _env;
    public IConfiguration Configuration { get; }

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

    public void ConfigureServices(IServiceCollection services)
    {
        if (_env.IsDevelopment())
        {
        }
        else
        {
        }
        //   _config["key"]
    }
}

La maggior parte dei servizi non è disponibile fino a quando non viene chiamato il metodo Configure.Most services are not available until the Configure method is called.

L'host fornisce i servizi disponibili al costruttore della classe Startup.The host provides services that are available to the Startup class constructor. L'app aggiunge servizi aggiuntivi tramite ConfigureServices.The app adds additional services via ConfigureServices. I servizi dell'host e dell'app saranno quindi disponibili in Configure e nell'app.Both the host and app services are then available in Configure and throughout the app.

Un uso comune dell'inserimento di dipendenze nella classe Startup consiste nell'inserire:A common use of dependency injection into the Startup class is to inject:

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: {_env.EnvironmentName}");
        }

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

La maggior parte dei servizi non è disponibile fino a quando non viene chiamato il metodo Configure.Most services are not available until the Configure method is called.

Avvio multiploMultiple StartUp

Quando l'app definisce classi Startup separate per i diversi ambienti (ad esempio StartupDevelopment), la classe Startup appropriata viene selezionata durante il runtime.When the app defines separate Startup classes for different environments (for example, StartupDevelopment), the appropriate Startup class is selected at runtime. La classe il cui suffisso di nome corrisponde all'ambiente corrente ha la priorità.The class whose name suffix matches the current environment is prioritized. Se l'app viene eseguita nell'ambiente di sviluppo e include sia una classe Startup che una classe StartupDevelopment, viene usata la classe StartupDevelopment.If the app is run in the Development environment and includes both a Startup class and a StartupDevelopment class, the StartupDevelopment class is used. Per altre informazioni, vedere Usare più ambienti.For more information, see Use multiple environments.

Per altre informazioni sull'host, vedere L'host.See The host for more information on the host. Per informazioni sulla gestione degli errori durante l'avvio, vedere Gestione delle eccezioni durante l'avvio.For information on handling errors during startup, see Startup exception handling.

Metodo ConfigureServicesThe ConfigureServices method

Il metodo ConfigureServices è:The ConfigureServices method is:

  • facoltativo.Optional.
  • Chiamato dall'host prima del metodo Configure per configurare i servizi dell'app.Called by the host before the Configure method to configure the app's services.
  • Dove le opzioni di configurazione sono impostate per convenzione.Where configuration options are set by convention.

L'host può configurare alcuni servizi prima che vengano chiamati i metodi Startup.The host may configure some services before Startup methods are called. Per altre informazioni, vedere L'host.For more information, see The host.

Per le funzionalità che richiedono l'installazione sostanziale, sono disponibili i metodi di estensione Add{Service} in IServiceCollection.For features that require substantial setup, there are Add{Service} extension methods on IServiceCollection. Ad esempio, AddDbContext, AddDefaultIdentity, AddEntityFrameworkStores e AddRazorPages:For example, AddDbContext, AddDefaultIdentity, AddEntityFrameworkStores, and AddRazorPages:

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();
    }
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>();
}

L'aggiunta dei servizi al contenitore dei servizi li rende disponibili all'interno dell'app e nel metodo Configure.Adding services to the service container makes them available within the app and in the Configure method. I servizi vengono risolti tramite inserimento delle dipendenze o da ApplicationServices.The services are resolved via dependency injection or from ApplicationServices.

Vedere SetCompatibilityVersion per altre informazioni su SetCompatibilityVersion.See SetCompatibilityVersion for more information on SetCompatibilityVersion.

Metodo ConfigureThe Configure method

Il metodo Configure viene usato per specificare come risponde l'app alle richieste HTTP.The Configure method is used to specify how the app responds to HTTP requests. La pipeline delle richieste viene configurata aggiungendo i componenti middleware a un'istanza IApplicationBuilder.The request pipeline is configured by adding middleware components to an IApplicationBuilder instance. IApplicationBuilder è disponibile per il metodo Configure ma non viene registrato nel contenitore dei servizi.IApplicationBuilder is available to the Configure method, but it isn't registered in the service container. L'hosting crea IApplicationBuilder e lo passa direttamente a Configure.Hosting creates an IApplicationBuilder and passes it directly to Configure.

I modelli ASP.NET Core configurano la pipeline con il supporto per:The ASP.NET Core templates configure the pipeline with support for:

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();
        });
    }
}

L'esempio precedente è per Razor Pages. La versione per MVC è simile.The preceding sample is for Razor Pages; the MVC version is similar.

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();
}

Ogni metodo di estensione Use aggiunge uno o più componenti middleware alla pipeline delle richieste.Each Use extension method adds one or more middleware components to the request pipeline. Ad esempio, UseStaticFiles configura il middleware per fornire i file statici.For instance, UseStaticFiles configures middleware to serve static files.

Ogni componente del middleware è responsabile della chiamata del componente seguente nella pipeline o del corto circuito della catena, se necessario.Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the chain, if appropriate.

I servizi aggiuntivi, ad esempio IWebHostEnvironment, ILoggerFactory o qualsiasi elemento definito in ConfigureServices, possono essere specificati nella firma del metodo Configure.Additional services, such as IWebHostEnvironment, ILoggerFactory, or anything defined in ConfigureServices, can be specified in the Configure method signature. Questi servizi vengono inseriti se sono disponibili.These services are injected if they're available.

I servizi aggiuntivi, ad esempio IHostingEnvironment e ILoggerFactory o qualsiasi elemento definito in ConfigureServices, possono essere specificati nella firma del metodo Configure.Additional services, such as IHostingEnvironment and ILoggerFactory, or anything defined in ConfigureServices, can be specified in the Configure method signature. Questi servizi vengono inseriti se sono disponibili.These services are injected if they're available.

Per altre informazioni su come usare IApplicationBuilder e sull'ordine di elaborazione del middleware, vedere Middleware di ASP.NET Core.For more information on how to use IApplicationBuilder and the order of middleware processing, see Middleware di ASP.NET Core.

Configurare i servizi senza StartupConfigure services without Startup

Per configurare i servizi e la pipeline di elaborazione delle richieste senza usare una classe Startup, chiamare i metodi pratici ConfigureServices e Configure sul generatore di host.To configure services and the request processing pipeline without using a Startup class, call ConfigureServices and Configure convenience methods on the host builder. Se vengono effettuate più chiamate a ConfigureServices, le chiamate vengono aggiunte l'una all'altra.Multiple calls to ConfigureServices append to one another. In presenza di più chiamate del metodo Configure viene usata l'ultima chiamata di Configure.If multiple Configure method calls exist, the last Configure call is used.

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) =>
           {
           })
        .ConfigureServices(services =>
        {
            services.AddControllersWithViews();

        }).ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.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"];
            }
            );
        });
}
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"];

                ...
            });
}

Estendere l'avvio con filtri di avvioExtend Startup with startup filters

Usare IStartupFilter per configurare il middleware all'inizio e alla fine della pipeline del middleware Configure di un'app.Use IStartupFilter to configure middleware at the beginning or end of an app's Configure middleware pipeline. L'interfaccia IStartupFilter viene usata per creare una pipeline di metodi Configure.IStartupFilter is used to create a pipeline of Configure methods. IStartupFilter.Configure può impostare un middleware da eseguire prima o dopo l'aggiunta del middleware dalle librerie.IStartupFilter.Configure can set a middleware to run before or after middleware added by libraries.

IStartupFilter implementa Configure, che riceve e restituisce un Action<IApplicationBuilder>.IStartupFilter implements Configure, which receives and returns an Action<IApplicationBuilder>. IApplicationBuilder definisce una classe per configurare la pipeline delle richieste di un'app.An IApplicationBuilder defines a class to configure an app's request pipeline. Per altre informazioni, vedere Creare una pipeline middleware con IApplicationBuilder.For more information, see Create a middleware pipeline with IApplicationBuilder.

Ogni IStartupFilter può aggiungere uno o più middleware nella pipeline delle richieste.Each IStartupFilter can add one or more middlewares in the request pipeline. I filtri vengono richiamati nell'ordine in cui sono stati aggiunti al contenitore di servizi.The filters are invoked in the order they were added to the service container. Poiché i filtri possono aggiungere il middleware prima o dopo il passaggio del controllo al filtro successivo, i filtri vengono aggiunti all'inizio o alla fine della pipeline dell'app.Filters may add middleware before or after passing control to the next filter, thus they append to the beginning or end of the app pipeline.

L'esempio seguente dimostra come registrare un middleware con IStartupFilter.The following example demonstrates how to register a middleware with IStartupFilter. Il middleware RequestSetOptionsMiddleware imposta un valore di opzioni da un parametro di stringa di query:The RequestSetOptionsMiddleware middleware sets an options value from a query string parameter:

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);
    }
}

RequestSetOptionsMiddleware è configurato nella classe RequestSetOptionsStartupFilter:The RequestSetOptionsMiddleware is configured in the RequestSetOptionsStartupFilter class:

public class RequestSetOptionsStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder =>
        {
            builder.UseMiddleware<RequestSetOptionsMiddleware>();
            next(builder);
        };
    }
}
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);
    }
}

RequestSetOptionsMiddleware è configurato nella classe RequestSetOptionsStartupFilter:The RequestSetOptionsMiddleware is configured in the RequestSetOptionsStartupFilter class:

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

IStartupFilter è registrato nel contenitore di servizi in ConfigureServices.The IStartupFilter is registered in the service container in 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>();
        });
}
WebHost.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddTransient<IStartupFilter, 
            RequestSetOptionsStartupFilter>();
    })
    .UseStartup<Startup>()
    .Build();

Quando viene specificato un parametro di stringa di query per option, il middleware elabora l'assegnazione del valore prima che il middleware ASP.NET Core esegua il rendering della risposta.When a query string parameter for option is provided, the middleware processes the value assignment before the ASP.NET Core middleware renders the response.

L'ordine di esecuzione del middleware viene impostato in base all'ordine delle registrazioni IStartupFilter:Middleware execution order is set by the order of IStartupFilter registrations:

  • Più implementazioni IStartupFilter possono interagire con gli stessi oggetti.Multiple IStartupFilter implementations may interact with the same objects. Se l'ordinamento è un fattore importante, ordinare le registrazioni di servizio IStartupFilter in un ordine corrispondente a quello di esecuzione dei relativi middleware.If ordering is important, order their IStartupFilter service registrations to match the order that their middlewares should run.

  • Le librerie possono aggiungere middleware con una o più implementazioni IStartupFilter che viene eseguito prima o dopo altri middleware dell'app registrati con IStartupFilter.Libraries may add middleware with one or more IStartupFilter implementations that run before or after other app middleware registered with IStartupFilter. Per richiamare un middleware IStartupFilter prima che un middleware venga aggiunto da IStartupFilter di una libreria:To invoke an IStartupFilter middleware before a middleware added by a library's IStartupFilter:

    • Posizionare la registrazione del servizio prima che la libreria venga aggiunta al contenitore di servizi.Position the service registration before the library is added to the service container.
    • Per richiamarlo in un secondo momento, posizionare la registrazione dei servizi dopo l'aggiunta della libreria.To invoke afterward, position the service registration after the library is added.

Aggiungere elementi di configurazione all'avvio da un assembly esternoAdd configuration at startup from an external assembly

Un'implementazione IHostingStartup consente l'aggiunta di miglioramenti a un'app all'avvio, da un assembly esterno alla classe Startup dell'app.An IHostingStartup implementation allows adding enhancements to an app at startup from an external assembly outside of the app's Startup class. Per altre informazioni, vedere Usare assembly di avvio dell'hosting in ASP.NET Core.For more information, see Usare assembly di avvio dell'hosting in ASP.NET Core.

Risorse aggiuntiveAdditional resources