Inicio de la aplicación en ASP.NET CoreApp startup in ASP.NET Core

Por Rick Anderson, Tom Dykstra, Luke Latham y Steve SmithBy Rick Anderson, Tom Dykstra, Luke Latham, and Steve Smith

La clase Startup configura los servicios y la canalización de solicitudes de la aplicación.The Startup class configures services and the app's request pipeline.

Clase StartupThe Startup class

Las aplicaciones de ASP.NET Core utilizan una clase Startup, que se denomina Startup por convención.ASP.NET Core apps use a Startup class, which is named Startup by convention. La clase Startup:The Startup class:

  • Incluye opcionalmente un método ConfigureServices para configurar los servicios de la aplicación.Optionally includes a ConfigureServices method to configure the app's services. Un servicio es un componente reutilizable que proporciona funcionalidades de la aplicación.A service is a reusable component that provides app functionality. Los servicios se registran en ConfigureServices y se usan en la aplicación a través de la inserción de dependencias (DI) o ApplicationServices.Services are registered in ConfigureServices and consumed across the app via dependency injection (DI) or ApplicationServices.
  • Incluye un método Configure para crear la canalización de procesamiento de solicitudes de la aplicación.Includes a Configure method to create the app's request processing pipeline.

El tiempo de ejecución ASP.NET Core llama a ConfigureServices y Configure cuando la aplicación se inicia: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();
        });
    }
}

El ejemplo anterior es para Razor Pages; la versión para MVC es similar.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 clase Startup se especifica cuando se crea el host de la aplicación.The Startup class is specified when the app's host is built. Normalmente, la clase Startup se especifica mediante la llamada al método WebHostBuilderExtensions.UseStartup<TStartup> en el generador de 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>();
            });
}

El host proporciona servicios que están disponibles para el constructor de clase Startup.The host provides services that are available to the Startup class constructor. La aplicación agrega servicios adicionales a través de ConfigureServices.The app adds additional services via ConfigureServices. Los servicios de la aplicación y el host están disponibles en Configure y en toda la aplicación.Both the host and app services are available in Configure and throughout the app.

Solo se pueden insertar los tipos de servicio siguientes en el constructor Startup cuando se usa el host genérico (IHostBuilder):Only the following service types can be injected into the Startup constructor when using the Generic Host (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
        {
        }
    }
}

La mayoría de los servicios no están disponibles hasta que se llama al método Configure.Most services are not available until the Configure method is called.

El host proporciona servicios que están disponibles para el constructor de clase Startup.The host provides services that are available to the Startup class constructor. La aplicación agrega servicios adicionales a través de ConfigureServices.The app adds additional services via ConfigureServices. Después, los servicios de la aplicación y el host están disponibles en Configure y en toda la aplicación.Both the host and app services are then available in Configure and throughout the app.

Un uso común de la inserción de dependencias en la clase Startup consiste en insertar: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: {EnvironmentName}", _env.EnvironmentName);
        }

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

La mayoría de los servicios no están disponibles hasta que se llama al método Configure.Most services are not available until the Configure method is called.

Inicio múltipleMultiple Startup

Cuando la aplicación define clases Startup independientes para otros entornos (por ejemplo, StartupDevelopment), la clase Startup correspondiente se selecciona en tiempo de ejecución.When the app defines separate Startup classes for different environments (for example, StartupDevelopment), the appropriate Startup class is selected at runtime. La clase cuyo sufijo de nombre coincide con el entorno actual se establece como prioritaria.The class whose name suffix matches the current environment is prioritized. Si la aplicación se ejecuta en el entorno de desarrollo e incluye tanto la clase Startup como la clase StartupDevelopment, se utiliza la clase 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. Para obtener más información, consulte Uso de varios entornos.For more information, see Use multiple environments.

Para obtener más información sobre el host, vea El host.See The host for more information on the host. Para obtener información sobre cómo controlar los errores que se producen durante el inicio, consulte Control de excepciones de inicio.For information on handling errors during startup, see Startup exception handling.

Método ConfigureServicesThe ConfigureServices method

El método ConfigureServices es:The ConfigureServices method is:

  • Opcional.Optional.
  • Lo llama el host antes del método Configure para configurar los servicios de la aplicación.Called by the host before the Configure method to configure the app's services.
  • Es donde se establecen por convención las opciones de configuración.Where configuration options are set by convention.

El host puede configurar algunos servicios antes de que se llame a los métodos Startup.The host may configure some services before Startup methods are called. Para obtener más información, vea El host.For more information, see The host.

Para las características que requieren una configuración sustancial, hay métodos de extensión Add{Service} en IServiceCollection.For features that require substantial setup, there are Add{Service} extension methods on IServiceCollection. Por ejemplo, AddDbContext, AddDefaultIdentity, AddEntityFrameworkStores y 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>();
}

La adición de servicios al contenedor de servicios hace que estén disponibles en la aplicación y en el método Configure.Adding services to the service container makes them available within the app and in the Configure method. Los servicios se resuelven a través de la inserción de dependencias o desde ApplicationServices.The services are resolved via dependency injection or from ApplicationServices.

Vea SetCompatibilityVersion para obtener más información sobre SetCompatibilityVersion.See SetCompatibilityVersion for more information on SetCompatibilityVersion.

El método ConfigureThe Configure method

El método Configure se usa para especificar la forma en que la aplicación responde a las solicitudes HTTP.The Configure method is used to specify how the app responds to HTTP requests. La canalización de solicitudes se configura mediante la adición de componentes de middleware a una instancia de IApplicationBuilder.The request pipeline is configured by adding middleware components to an IApplicationBuilder instance. IApplicationBuilder está disponible para el método Configure, pero no está registrado en el contenedor de servicios.IApplicationBuilder is available to the Configure method, but it isn't registered in the service container. El hospedaje crea un elemento IApplicationBuilder y lo pasa directamente a Configure.Hosting creates an IApplicationBuilder and passes it directly to Configure.

Las plantillas de ASP.NET Core configuran la canalización con compatibilidad para lo siguiente: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();
        });
    }
}

El ejemplo anterior es para Razor Pages; la versión para MVC es similar.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();
}

Cada método de extensión Use agrega uno o más componentes de middleware a la canalización de solicitudes.Each Use extension method adds one or more middleware components to the request pipeline. Por ejemplo, UseStaticFiles configura middleware para proporcionar archivos estáticos.For instance, UseStaticFiles configures middleware to serve static files.

Cada componente de middleware de la canalización de solicitudes es responsable de invocar al siguiente componente de la canalización o de cortocircuitar la cadena en caso de ser necesario.Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the chain, if appropriate.

En la firma del método Configure se pueden especificar servicios adicionales, como IWebHostEnvironment, ILoggerFactory, o bien todo lo definido en ConfigureServices.Additional services, such as IWebHostEnvironment, ILoggerFactory, or anything defined in ConfigureServices, can be specified in the Configure method signature. Estos servicios adicionales se insertan si están disponibles.These services are injected if they're available.

En la firma del método Configure se pueden especificar servicios adicionales, como IHostingEnvironment e ILoggerFactory, o bien todo lo definido en ConfigureServices.Additional services, such as IHostingEnvironment and ILoggerFactory, or anything defined in ConfigureServices, can be specified in the Configure method signature. Estos servicios adicionales se insertan si están disponibles.These services are injected if they're available.

Para obtener más información sobre cómo usar IApplicationBuilder y el orden de procesamiento de middleware, consulte Middleware de ASP.NET Core.For more information on how to use IApplicationBuilder and the order of middleware processing, see Middleware de ASP.NET Core.

Configuración de servicios sin inicioConfigure services without Startup

Para configurar los servicios y la canalización de procesamiento de solicitudes sin usar una clase Startup, llame a los métodos de conveniencia ConfigureServices y Configure en el generador de host.To configure services and the request processing pipeline without using a Startup class, call ConfigureServices and Configure convenience methods on the host builder. Varias llamadas a ConfigureServices se anexan entre sí.Multiple calls to ConfigureServices append to one another. Si hay varias llamadas al método Configure, se usa la última llamada a 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) =>
            {
            })
            .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"];
                });
            });
        });
}
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"];

                ...
            });
}

Extensión del inicio con filtros de inicioExtend Startup with startup filters

Use IStartupFilter:Use IStartupFilter:

  • Para configurar el middleware al principio o al final de la canalización de middleware Configure de una aplicación sin una llamada explícita a Use{Middleware}.To configure middleware at the beginning or end of an app's Configure middleware pipeline without an explicit call to Use{Middleware}. ASP.NET Core usa IStartupFilter para agregar los valores predeterminados al principio de la canalización sin que el creador de la aplicación tenga que registrar explícitamente el middleware predeterminado.IStartupFilter is used by ASP.NET Core to add defaults to the beginning of the pipeline without having to make the app author explicitly register the default middleware. IStartupFilter permite que otro componente llame a Use{Middleware} en nombre del creador de la aplicación.IStartupFilter allows a different component call Use{Middleware} on behalf of the app author.
  • Para crear una canalización de métodos Configure.To create a pipeline of Configure methods. IStartupFilter.Configure puede configurar middleware para que se ejecute antes o después del middleware agregado por las bibliotecas.IStartupFilter.Configure can set a middleware to run before or after middleware added by libraries.

IStartupFilter implementa Configure, que recibe y devuelve un elemento Action<IApplicationBuilder>.IStartupFilter implements Configure, which receives and returns an Action<IApplicationBuilder>. IApplicationBuilder define una clase para configurar la canalización de solicitudes de una aplicación.An IApplicationBuilder defines a class to configure an app's request pipeline. Para más información, vea Creación de una canalización de middleware con IApplicationBuilder.For more information, see Create a middleware pipeline with IApplicationBuilder.

Cada instancia de IStartupFilter puede agregar uno o más middleware en la canalización de solicitudes.Each IStartupFilter can add one or more middlewares in the request pipeline. Los filtros se invocan en el orden en que se agregaron al contenedor de servicios.The filters are invoked in the order they were added to the service container. Los filtros pueden agregar middleware antes o después de pasar el control al siguiente filtro, por lo que se anexan al principio o al final de la canalización de la aplicación.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.

En el ejemplo siguiente, se muestra cómo registrar un componente de middleware con IStartupFilter.The following example demonstrates how to register a middleware with IStartupFilter. El componente de middleware RequestSetOptionsMiddleware establece un valor de opciones de un parámetro de cadena de consulta: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 está configurado en las clase 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 está configurado en las clase 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 se registra en el contenedor de servicios en 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();

Cuando se proporciona un parámetro de cadena de consulta para option, el middleware procesa la asignación del valor antes de que el middleware de ASP.NET Core represente la respuesta.When a query string parameter for option is provided, the middleware processes the value assignment before the ASP.NET Core middleware renders the response.

El orden de ejecución de middleware se establece según el orden de registros de IStartupFilter:Middleware execution order is set by the order of IStartupFilter registrations:

  • Varias implementaciones de IStartupFilter pueden interactuar con los mismos objetos.Multiple IStartupFilter implementations may interact with the same objects. Si el orden es importante, ordene los registros de servicio de IStartupFilter para que coincidan con el orden en que se deben ejecutar los middleware.If ordering is important, order their IStartupFilter service registrations to match the order that their middlewares should run.

  • Las bibliotecas pueden agregar middleware con una o varias implementaciones de IStartupFilter que se ejecuten antes o después de otro middleware de aplicación registrado con IStartupFilter.Libraries may add middleware with one or more IStartupFilter implementations that run before or after other app middleware registered with IStartupFilter. Para invocar un middleware IStartupFilter antes de un middleware agregado por el elemento IStartupFilter de una biblioteca:To invoke an IStartupFilter middleware before a middleware added by a library's IStartupFilter:

    • Coloque el registro del servicio antes de que la biblioteca se agregue al contenedor de servicios.Position the service registration before the library is added to the service container.
    • Para la invocación posterior, coloque el registro del servicio después de que se agregue la biblioteca.To invoke afterward, position the service registration after the library is added.

Agregar opciones de configuración en el inicio desde un ensamblado externoAdd configuration at startup from an external assembly

Una implementación de IHostingStartup permite agregar mejoras a una aplicación al iniciarla a partir de un ensamblado externo fuera de la clase Startup de esta.An IHostingStartup implementation allows adding enhancements to an app at startup from an external assembly outside of the app's Startup class. Para más información, consulte Uso de ensamblados de inicio de hospedaje en ASP.NET Core.For more information, see Uso de ensamblados de inicio de hospedaje en ASP.NET Core.

Recursos adicionalesAdditional resources