asp.net core 系列 2 启动类 Startup.CS
学无止境,精益求精
十年河东,十年河西,莫欺少年穷
学历代表你的过去,能力代表你的现在,学习代表你的将来
在探讨Startup启动类之前,我们先来了解下Asp.NET CORE 配置应用程序的执行顺序,如下图所示

与早期版本的 ASP.NET 对比,最显著的变化之一就是配置应用程序的方式, Global.asax、FilterConfig.cs 和 RouteConfig.cs 统统消失了,取而代之的是 Program.cs 和 Startup.cs。Program.cs 作为 Web 应用程序的默认入口,不做任何修改的情况下,会调用同目录下 Startup.cs 中的 ConfigureServices 方法 和 Configure 方法。
首先我们来看下Progarm.cs,如下
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
} public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
我们看到Program中Main函数很像我们之前的Console应用程序,那么它当中的CreateWebHostBuilder究竟做了什么事情呢?既然.Net Core是开源的,我们看源码就方便了很多,接下来就从源码来了解下它究竟做了什么工作。
/// <summary>
/// Initializes a new instance of the <see cref="WebHostBuilder"/> class with pre-configured defaults.
/// </summary>
/// <remarks>
/// The following defaults are applied to the returned <see cref="WebHostBuilder"/>:
/// use Kestrel as the web server and configure it using the application's configuration providers,
/// set the <see cref="IHostingEnvironment.ContentRootPath"/> to the result of <see cref="Directory.GetCurrentDirectory()"/>,
/// load <see cref="IConfiguration"/> from 'appsettings.json' and 'appsettings.[<see cref="IHostingEnvironment.EnvironmentName"/>].json',
/// load <see cref="IConfiguration"/> from User Secrets when <see cref="IHostingEnvironment.EnvironmentName"/> is 'Development' using the entry assembly,
/// load <see cref="IConfiguration"/> from environment variables,
/// load <see cref="IConfiguration"/> from supplied command line args,
/// configure the <see cref="ILoggerFactory"/> to log to the console and debug output,
/// and enable IIS integration.
/// </remarks>
/// <param name="args">The command line args.</param>
/// <returns>The initialized <see cref="IWebHostBuilder"/>.</returns>
public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
var builder = new WebHostBuilder(); if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey)))
{
builder.UseContentRoot(Directory.GetCurrentDirectory());
}
if (args != null)
{
builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
} builder.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); if (env.IsDevelopment())
{
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
} config.AddEnvironmentVariables(); if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
}).
UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
}); ConfigureWebDefaults(builder); return builder;
}
internal static void ConfigureWebDefaults(IWebHostBuilder builder)
{
builder.UseKestrel((builderContext, options) =>
{
options.Configure(builderContext.Configuration.GetSection("Kestrel"));
})
.ConfigureServices((hostingContext, services) =>
{
// Fallback
services.PostConfigure<HostFilteringOptions>(options =>
{
if (options.AllowedHosts == null || options.AllowedHosts.Count == )
{
// "AllowedHosts": "localhost;127.0.0.1;[::1]"
var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
// Fall back to "*" to disable.
options.AllowedHosts = (hosts?.Length > ? hosts : new[] { "*" });
}
});
// Change notification
services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration)); services.AddTransient<IStartupFilter, HostFilteringStartupFilter>(); services.AddRouting();
})
.UseIIS()
.UseIISIntegration();
}
从源码中我们可以看到,CreateDefaultBuilder执行的任务有:
1、加载主机和应用程序的配置表信息
2、配置日志记录
3、设置Web服务器
4、设置Asp.Net Core应用程序的托管形式。
Asp.Net Core应用程序的托管形式,它有两种托管形式:进程内托管InProcess和进程外托管OutOfProcess。我们知道Asp.Net Core是可以自托管的,它默认托管形式就是InProcess。那么这两种方式的区别是什么呢?
InProcess:配置进程内托管在项目.csproj文件中 <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>,在InProcess托管情况下,CreateDefaultBuilder()方法调用UseIIS()方法并在IIS工作进程(w3wp.exe或iisexpress.exe)内托管应用程序,从性能角度,InProcess托管比OutOfProcess托管提供了更高的请求吞吐量。
OutOfProcess:有2个Web服务器-内部Web服务器和外部Web服务器,内部Web服务器是Kestrel,托管进程是dotnet.exe;外部web服务器可以是iis,nginx,apache。
总之,我们可以初步理解为Program.cs 主要用来构造,配置,并启用项目所依赖的服务器,最后设置Asp.Net Core应用程序的托管形式。
在Program.cs中,我们发现它会引用Startup.CS,如下:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
下面我们来看看启动类Startup.CS,如下:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
}); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
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();
}
}
Startup 类的作用:
1. ConfigureServices方法用于定义(注册)应用程序所使用的服务。(如:ASP.NET Core MVC,Entity Framework Core,Identity 等);
2. Configure方法用于定义请求管道的中间件,该管道将用于处理应用程序的所有请求。
3. 注册服务添加方法是无序的,ASP.NET Core在应用程序启动的时候,只要有相应服务即可,而注册中间件时方法是有序的,管道内的每一个组件都可以选择是否将请求交给下一个组件,并在管道中调用下一个组件之前或之后执行某些操作。
1. ConfigureServices
应用通过 ConfigureServices 添加服务。 然后,主机和应用服务都可以在 Configure 和整个应用中使用。
也就是说在 ConfigureServices 中,我们...
在NETCORE中,依赖注入几乎无处不在,
未完,待续...下班了,中元节,不该过多加班的。
asp.net core 系列 2 启动类 Startup.CS的更多相关文章
- 探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs
原文:探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs 前言:.NET Core 3.0 SDK包含比以前版本更多的现成模板. 在本文中,我将 ...
- asp.net core 系列 2 启动Startup类介绍
一.Startup类 ASP.NET Core 应用是一个控制台应用,它在其 Program.Main 方法中创建 Web 服务器.其中Main方法是应用的托管入口点,Main 方法调用 WebHos ...
- Asp.Net Core 入门(二)——Startup.cs做了什么
上篇介绍了Program.cs中Main做了什么,这篇我们来讨论下Startup.cs它又做了什么呢? 我们新建一个Asp.Net Core Mvc项目,先来开一下Startup的代码 public ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
- ASP.NET Core系列(三):启动类Startup
前面讲了ASP.NET Core 的项目结构,查看完整的ASP.NET Core系列文章:https://www.cnblogs.com/zhangweizhong/category/1477144. ...
- ASP.NET CORE系列【七】分析NetCore启动原理
前言 有很久一段时间没更新了,因为工作和家里的问题导致没能坚持, 现在开始会继续每周更新,主要是记录自己所学和一起讨论解决过的问题,一起成长, 为.net圈子添砖加瓦! 介绍 到目前为止应该很多同学已 ...
- ASP.Net Core MVC6 RC2 启动过程分析[偏源码分析]
入口程序 如果做过Web之外开发的人,应该记得这个是标准的Console或者Winform的入口.为什么会这样呢? .NET Web Development and Tools Blog ASP.NE ...
- 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来说 ...
随机推荐
- cesium-webpack 入门开发系列一初探篇(附源码下载)
前言 cesium-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 we ...
- ICMP重定向 Redirect netwox libpcap netwag
搭建环境 两台虚拟机. 攻击者:192.168.1.8 被攻击者:192.168.1.9 网络配置 主机均采用DHCP 如果没有路由器,可以使用NAT模式来做 攻击者配置 打开转发数据包功能 # su ...
- Android开发利器之pidcat
介绍pidcat: pidcat 是Android届JakeWharton大神开发的一款命令行工具,堪称Android开发利器,它能方便Android程序猿捕获日志,过滤日志,定位程序问题,超级好用. ...
- Element-ui中自定义表单校验规则
先看一个场景图: 给一个标签el-tag添加表单的校验,且在内容有了以后关闭校验 看代码: <el-form-item class="baseinfo-tags" label ...
- 24.Java基础_IDEA类快捷键_Alt+insert
这个IDEA我真的爱了,Alt+insert可以定制生成类的各项基本方法 Alt+insert,会打开下面这个界面,选择需要的类方法,按回车 选择该方法下的参数设置,可以使用Ctrl+A全部选中 自动 ...
- equals和==的应用场景
今天我知道了 抽象类主要作为多个类的模板,接口则定义了多个类应该遵守的规范. "=="比"equals"运行速度快,因为"=="只是比较引用 ...
- 2. java 运算符
运算符 一.算术运算符 1. 四则与取模 + - * / % ++ -- (1) 单独使用++/--,前++和后++没有任何区别. (2) 混合使用,有区别 ①如果是前++,那么变量立刻马上 +1,然 ...
- while语句 break和continue
1.whlie 循环 基本条件 :while 条件: 代码块(循环体) else: 当上面的条件为假的,才会执行 执行顺序: 判断条件是否为真,如果为真,执行循环体,然后判断条件,...直到循环条件为 ...
- day57 choise字段与ajax
一.choice字段. 在django的orm中,创建如同性别,民.族等可选择的字段时,可以选择使用choice字段进行定义. 这样的定义可以使用简单的数字代替数据量大的字符,减少数据库的负担. ch ...
- python将xml文件数据增强(labelimg)
在处理faster-rcnn和yolo时笔者使用labelimg标注图片 但是我们只截取了大概800张左右的图,这个量级在训练时肯定是不够的,所以我们需要使用数据增强(无非是旋转加噪调量度)来增加我们 ...