翻译 - ASP.NET Core 基本知识 - Startup 类
翻译自 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-5.0
Startup 类配置了服务和应用程序的请求管道。
Startup 类
ASP.NET Core 应用程序使用一个 Startup 类,约定名称为 Startup。
Startup 类:
- 包含一个可选的 ConfigureServices 方法配置应用程序的服务。服务是提供应用程序功能的可重复使用的组件。服务在 ConfigureServices 中注册,通过依赖注入 dependency injection (DI) 或者 ApplicationServices 在应用程序中使用。
- 包含一个 Configure 方法创建应用程序请求处理管道
ConfigureServices 和 Configure 被 ASP.NET Core 运行时在应用程序启动的时候调用:
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(); }); } }
上面的例子是为 Razor Pages 编写的。MVC 的版本是类似的。
Startup 类在应用程序的 host 被建立的时候指定。Startup 类通常在 host builder 上通过调用 WebHostBuilderExtensions.UseStartup<TStartup> 来指定:
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>(); }); }
host 提供的服务可以在 Startup 类构造方法中使用。应用程序通过 ConfigureServices 添加额外的服务。host 和 应用程序的服务在 Configure 和整个应用程序中都可以使用。
只用以下几个服务类型在使用 Generic Host (IHostBuilder) 可以被注入到 Startup 构造方法中:
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 { } } }
大多数服务直到 Configure 被调用之后才能使用。
多个 Startup
当应用程序为不同环境(例如,StartupDevelopment)定义了单独的 Startup 类,合适的 Startup 类在运行时会被选择。类名称的前缀匹配了当前环境的类优先级更高。如果应用程序运行在 Development 环境,并且包含了一个 Startup 类和一个 StartupDevelopment 类,类 StartupDevelopment 会被使用。更多信息查看 Use multiple environments。
查看 The host 关于 host 更多信息。更过关于在 startup 中处理错误的信息,查看 Startup exception handling。
ConfigureServices 方法
ConfigureServices 方法是:
- 可选的
- 在 Configure 方法配置应用程序服务之前由 host 调用
- 约定的设置 configuration options 的地方
在 Startup 方法被调用之前,host 可能会配置一些服务。更多信息请查看 The host。
对于需要大量设置的功能,可以使用 IServiceCollection 的扩展方法 Add{Service} 来添加。例如,AddDbContext,AddDefaultIdentify,AddEntityFrameworkStores 和 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(); }
添加服务到服务容器中可以使得服务在应用程序和 Configure 中都可以使用。服务通过依赖注入 (dependency injection)或者 ApplicationServices 获取。
Configure 方法
Configure 方法被用来指定应用程序如何处理 HTTP 请求。请求管道通过添加中间件组件到 IApplicationBuilder 的一个实例中配置。IApplicationBuilder 对 Configure 是可以使用的,但是并没有在服务容器中注册。Hosting 创建一个 IApplicationBuilder 对象直接传递给 Configure。
ASP.NET Core templates 配置管道会有以下支持:
- Developer Exception Page
- Exception handler
- HTTP Strict Transport Security (HSTS)
- HTTPS redirection
- Static files
- ASP.NET Core MVC 和 Razor Pages
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(); }); } }
上面是 Razor Pages 示例代码;MVC 版本也是类似的。
每一个 Use 扩展方法添加一个或多个中间件组件到请求管道中。例如,UseStaticFiles 配置静态文件服务 static files。
请求管道中的每一个中间件组件负责调用管道中的下一个组件,或者合适的话通过链式调用。
更过的服务,例如 IWebHostEnvironment,ILoggerFactory,或者在 ConfigureServices 中定义的任何东西,都可以在 Configure 方法中签名指定。这些服务如果可用的话可以通过注入。
更过关于如何使用 IApplicationBuilder 和处理中间件的顺序,请查看 ASP.NET Core Middleware。
不试用 Startup 配置服务
在 host builder 上调用约定的 ConfigureServices 和 Configure 配置服务和请求处理管道,可以去掉 Startup 类。多个 ConfigureServices 调用将会附加到另外一个上面。如果多个 Configure 方法调用存在,那么只有最后一个 Configure 调用将会生效。
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"]; }); }); }); }
使用 startup filters 扩展 Startup
使用 IStartupFilter:
- 实现在应用程序的 Configure 开头或者结尾配置中间件管道的时候不显式调用 Use{Middleware}。ASP.NET Core 使用 IStartupFilter 添加默认的中间件到管道的开头,而应用程序的作者不用显式的注册默认的中间件。为应用程序的考虑,IStartupFilter 允许一个不同的组件调用 Use{Middleware}。
- 创建一个 Configure 方法的管道。IStartupFilter.Configure 可以添加一个在通过库添加的中间件之前或者之后运行的中间件。
IStartupFilter 实现了 Configure,接收和返回一个 Action<IApplicationBuilder>。 IApplicationBuilder 定义了配置应用程序管道的类。更多信息查看,Create a middleware pipeline with IApplicationBuilder。
每一个 IStartupFilter 可以添加一个或多个中间件到请求管道中。filters 按照他们被添加到服务容器中的顺序被调用。Filters可能在把控制权传递给下一个filter之前或者之后添加中间件,所以他们附加到应用程序管道的开头或者结尾。
下面的示例展示了如何使用 IStartupFilter 注册一个中间件。RequestSetOptionsMiddleware 中间件设置请求参数为可选值:
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); } }
在 RequestSetOptionsStartupFilter 中配置 RequestSetOptionsMiddleware:
public class RequestSetOptionsStartupFilter : IStartupFilter { public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) { return builder => { builder.UseMiddleware<RequestSetOptionsMiddleware>(); next(builder); }; } }
IStartupFilter 在 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>(); }); }
当请求参数中存在 option 参数的时候,中间件在 ASP.NET Core 中间件渲染返回之前就会进行赋值操作。
中间件执行的顺序是根据 IStartupFilter 注册的顺序确定的:
- 多个 IStartupFilter 实现可能处理相同的对象。如果顺序很重要的话,排序好 IStartupFilter 服务注册的顺序以匹配他们中间件的应该运行的顺序。
- 库可能添加有一个或者多个 IStartupFilter 实现的中间件,这些中间件在应用程序其他注册了 IStartupFilter 的中间件之前或者之后运行。在通过库的 IStartupFilter 添加的中间件之前调用一个 IStartupFilter 中间件:
* 把服务注册放到库被添加到服务容器之前添加
* 要之后调用,就把服务注册放到库被添加之后
在 Startup 中从外部程序集中添加配置
一个 IHostingStartup 实现允许从外部程序集在 Startup 中添加增强的功能。更多信息查看,Use hosting startup assemblies in ASP.NET Core。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端