asp.net core 系列之Startup
这篇文章简单记录 ASP.NET Core中 ,startup类的一些使用。
一.前言
在 Startup类中,一般有两个方法:
- ConfigureServices 方法: 用来配置应用的 service 。
- Configure 方法:创建应用的请求处理管道
它们都在应用启动时,被ASP.NET Core runtime 调用:
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)
{
...
}
}
当应用的 host 被built(建立)时,Startup类被指定到应用中。
而在 Program 中,当 host builder 上的 Build 被调用时,应用的 host 被 built 。
而Startup类是通过调用WebHostBuilderExtensions.UseStartup<TStartup>方法指定的。
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run(); //Build方法被调用时,应用的host被建立,同时Startup被指定到应用中
} public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
在startup类中,一种依赖注入的常见用法:
- IHostingEnvironment : 根据enviironment (环境) 配置 services .
- IConfiguration : 读取配置
- ILoggerFactory : 在Startup.ConfigureServices中创建 logger .
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"]
}
}
注入IHostingEnvironment , 当定义不同环境的Startup (例如,StartupDevelopment 等),在运行时,选择合适的Startup。
二.ConfigureServices方法
它有三个特点:
- 可选的
- 在调用Configure方法之前调用 ConfigureServices
- Configuration options 按约定设置
1. 比较典型的是调用 Add{Service} 和 services.Configure{Service} 。例如:Configure Identity services.

2. host 可能会 在Startup方法被调用之前,配置一些服务。 例如: The host.

在startup被调用之前,CreateDefaultBuilder方法配置了一个host 。
3. Add{Service}是IServiceCollection的扩展方法,下面是一些使用:
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>();
}
添加 services 到 service container 使它们在应用和Configure方法中可用。services方法可以通过 dependency injection 或 ApplicationServices 解析。
三.The Configure method
Configure方法用来指定应用怎样 处理HTTP request。请求管道(request pipeline)通过添加中间组件到IApplicationBuilder实例中来配置。
ASP.NET Core 模板 配置的管道:
- Developer Exception Page
- Exception handler
- HTTP Strict Transport Security (HSTS)
- HTTPS redirection
- Static files
- General Data Protection Regulation (GDPR)
- ASP.NET Core MVC and Razor Pages
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();
}
使用Use扩展方法添加一个或多个中间组件到请求管道。例如,UseMvc扩展方法添加 Routing Middleware 到请求管道 并且配置MVC 作为一个默认的处理器。
四.Convenience methods
不使用Startup类配置services和request processing pipeline。在host builder 上调用ConfigureServices和Configure的简便方法。如果存在多个ConfigureServices的调用,会依次添加。如果存在多个Configure方法的调用,最后一个Configure的调用会被使用。
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.GetRequiredServices<IHostingEnvironment>();
var config = app.ApplicationServices.GetRequiredServices<IConfiguration>(); logger.LogInformation("Logged in Configure"); if (env.IsDevelopment())
{
...
}
else
{
...
} var configValue = config["subsection:suboption1"]; ...
});
}
五.Extend Startup with startup filters (使用startup filter扩展 Startup)
使用 IStartupFilter ,在应用的Configure 中间件管道的开头或末尾配置中间件。
IStartupFilter 实现Configure方法,它会接收和返回一个Action<IApplicationBuilder>。而IApplicationBuilder定义了一个类来配置一个应用的请求管道。
这些filters会按照添加到services container的顺序被调用。
下面是一个例子:
RequestSetOptionsMiddleware
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"]; //取请求中的option参数 if (!string.IsNullOrWhiteSpace(option))
{
_injectedOptions.Value.Option = WebUtility.HtmlEncode(option);
} await _next(httpContext);
}
}
RequestSetOptionsMiddleware 中间件被配置在 RequestSetOptionsStartupFilter 类中:
public class RequestSetOptionsStartupFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
builder.UseMiddleware<RequestSetOptionsMiddleware>();
next(builder);
};
}
}
IStartupFilter 在 ConfigureServices中被注册到 service container, 并且从Startup类的外部增强Startup:
WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddTransient<IStartupFilter,
RequestSetOptionsStartupFilter>();
})
.UseStartup<Startup>()
.Build();
当option的查询字符串存在时,中间件会在MVC中间件之前处理这个值

中间件的执行顺序是按照IStartupFilter的注册顺序
六. 补充
这里晚上补充下 ApplicationServices 解析services的使用
IApplicationBuilder app
app.ApplicationServices.GetService 方法
如上,IApplicationBuilder类型,即可得到ApplicationServices,然后利用其方法来解析services
参考网址:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-2.2
asp.net core 系列之Startup的更多相关文章
- ASP.NET Core系列(三):启动类Startup
前面讲了ASP.NET Core 的项目结构,查看完整的ASP.NET Core系列文章:https://www.cnblogs.com/zhangweizhong/category/1477144. ...
- asp.net core系列 30 EF管理数据库架构--必备知识 迁移
一.管理数据库架构概述 EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步.一是以 EF Core 模型为基准,二是以数据库为基准. (1)如果希望以 EF Core 模型为 ...
- asp.net core系列 39 Web 应用Razor 介绍与详细示例
一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...
- asp.net core系列 38 WebAPI 返回类型与响应格式--必备
一.返回类型 ASP.NET Core 提供以下 Web API Action方法返回类型选项,以及说明每种返回类型的最佳适用情况: (1) 固定类型 (2) IActionResult (3) Ac ...
- asp.net core 系列 22 EF(连接字符串,连接复原,DbContext)
一.连接字符串 在上二篇中,ASP.NET Core 应用程序连接字符串是写死在ConfigureServices代码中,下面介绍通过配置来实现.连接字符串可以存储在 appsettings.json ...
- asp.net core 系列 18 web服务器实现
一. ASP.NET Core Module 在介绍ASP.NET Core Web实现之前,先来了解下ASP.NET Core Module.该模块是插入 IIS 管道的本机 IIS 模块(本机是指 ...
- asp.net core 系列 16 Web主机 IWebHostBuilder
一.概述 在asp.net core中,Host主机负责应用程序启动和生存期管理.host主机包括Web 主机(IWebHostBuilder)和通用主机(IHostBuilder).Web 主机是适 ...
- asp.net core 系列 14 错误处理
一.概述 本文介绍处理 ASP.NET Core 应用中常见错误的一些方法.主要是关于:开发环境异常页:非开发环境配置自定义异常处理页:配置状态代码页(没有正文响应,http状态400~599的). ...
- 技术的正宗与野路子 c#, AOP动态代理实现动态权限控制(一) 探索基于.NET下实现一句话木马之asmx篇 asp.net core 系列 9 环境(Development、Staging 、Production)
黄衫女子的武功似乎与周芷若乃是一路,飘忽灵动,变幻无方,但举手抬足之间却是正而不邪,如说周芷若形似鬼魅,那黄衫女子便是态拟神仙. 这段描写出自<倚天屠龙记>第三十八回. “九阴神抓”本是& ...
随机推荐
- Android 4.0开发之GridLayOut布局实践
在上一篇教程中http://blog.csdn.net/dawanganban/article/details/9952379,我们初步学习了解了GridLayout的布局基本知识,通过学习知道,Gr ...
- Python Tricks(二十一)—— 排列组合的计算
使用循环: 阶乘的实现: def fac(n): r = 1. for i in range(1, n+1): r *= i return r 排列:Anm=m!n!=(m−n+1)⋯m def pe ...
- android module 模块共用远程包
在项目有多模块,需要使用到同一个第三方包时,引入报错,个人解决方法如下 1. 在模块build.gradle 文件中配置maven远程地址 可从app下的build.gradle文件里复制 allpr ...
- C#中的字符串——用Stringbuilder类很重要
注:这篇文章基本是<C#高级编程>(第七版)第九章的学习笔记. 众所周知,C#中处理字符串通常用的都是string,它其实是.NET基础类System.String类的映射.注意一个是小写 ...
- HDU 1143 Tri Tiling(递归)
意甲冠军:一些现有的1*2小盒子.求拼3*n多少个长方形的拼写. 思考: 因为它是一个递归式.肯定会遇到层的关系.仔细观察,研究发现,每层应设置2一层.(奇数层不能是矩形)而从显卡好最后一层的最后一战 ...
- python下载图片(3)
# -*- coding: utf-8 -*-"""some function by metaphy,2007-04-03,copyleftversion 0.2&quo ...
- 解决popup不随着window一起移动的问题
原文:解决popup不随着window一起移动的问题 当我们设置Popup的StayOpen="True"时,会发现移动窗体或者改变窗体的Size的时候,Popup并不会跟随着一起 ...
- java线:辛格尔顿隐藏ThreadLocal实现线程数据共享
效果图分享: A和B需要共享同一线程,还有一组的相同A和B共享还有一组线程,两组相互之间不受影响. 代码: package cn.itcast.lesson6; import java.util.Ra ...
- 在 DEBIAN 上安装 SQL SERVER
微软在开源 .NET Framework 之后,相继推出了跨平台的编辑器 Visual Studio Code,跨平台的 SQL Server 数据库 SQL Server vNext,Visual ...
- String,CString,TCHAR,char之间区别和联系
char是类型TCHAR也是!不过他可以通过是否定义了UNICODE宏来判断到底是char还是w_char; TCHAR是一种字符串类型,它让你在以MBCS和UNNICODE来build程序时可以使用 ...