学无止境,精益求精

十年河东,十年河西,莫欺少年穷

学历代表你的过去,能力代表你的现在,学习代表你的将来

在探讨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的更多相关文章

  1. 探索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包含比以前版本更多的现成模板. 在本文中,我将 ...

  2. asp.net core 系列 2 启动Startup类介绍

    一.Startup类 ASP.NET Core 应用是一个控制台应用,它在其 Program.Main 方法中创建 Web 服务器.其中Main方法是应用的托管入口点,Main 方法调用 WebHos ...

  3. Asp.Net Core 入门(二)——Startup.cs做了什么

    上篇介绍了Program.cs中Main做了什么,这篇我们来讨论下Startup.cs它又做了什么呢? 我们新建一个Asp.Net Core Mvc项目,先来开一下Startup的代码 public ...

  4. 【目录】asp.net core系列篇

    随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...

  5. ASP.NET Core系列(三):启动类Startup

    前面讲了ASP.NET Core 的项目结构,查看完整的ASP.NET Core系列文章:https://www.cnblogs.com/zhangweizhong/category/1477144. ...

  6. ASP.NET CORE系列【七】分析NetCore启动原理

    前言 有很久一段时间没更新了,因为工作和家里的问题导致没能坚持, 现在开始会继续每周更新,主要是记录自己所学和一起讨论解决过的问题,一起成长, 为.net圈子添砖加瓦! 介绍 到目前为止应该很多同学已 ...

  7. ASP.Net Core MVC6 RC2 启动过程分析[偏源码分析]

    入口程序 如果做过Web之外开发的人,应该记得这个是标准的Console或者Winform的入口.为什么会这样呢? .NET Web Development and Tools Blog ASP.NE ...

  8. asp.net core系列 30 EF管理数据库架构--必备知识 迁移

    一.管理数据库架构概述 EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步.一是以 EF Core 模型为基准,二是以数据库为基准. (1)如果希望以 EF Core 模型为 ...

  9. asp.net core系列 39 Web 应用Razor 介绍与详细示例

    一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...

随机推荐

  1. 远程控制服务(SSH)之Windows远程登陆Linux主机

    本篇blog同样介绍两种方式进行. 首先进行准备工作: 1.所用到的工具如下: (1)     装有Linux系统的VMware虚拟机*1 (2)     终端连接工具Xshell 6 2.将Wind ...

  2. 开源敏捷测试管理& 开源BUG跟踪管理软件itest(爱测试) V3.3.1小改紧急发布及正实现功能预告

    v3.3.1 下载地址 :itest下载 码云源码地址 https://gitee.com/itestwork/itest 开源中国  itest项目地址   https://www.oschina. ...

  3. 6.1 Spark SQL

    一.从shark到Spark SQL Hive能够把SQL程序转换成map-reduce程序   可以把Hadoop中的Hive看作是一个接口,主要起到了转换的功能,并没有实际存储数据. Shark即 ...

  4. 18.Java基础_关键字this及其内存原理

    this使用 this的内存原理 执行函数setName时,首先是创建函数栈空间,然后创建形参name,除此之外还会有一个this(实质是堆内存中对象的首地址),这个this会索引对象的成员变量nam ...

  5. 如何调用.so动态库中的函数,如何把自己的函数导出为.so的动态库函数供别人调用

    调用.so中的函数和平常的函数没有区别,只是在编译连接时加上-lxxxx就行了.要生成.so库,则编译时用下面的语句:gcc -shared -Wl,-soname,libmyfun.so -o li ...

  6. luoguP3071 [USACO13JAN]座位Seating

    https://www.luogu.org/problem/P3071 AC代码: https://www.luogu.org/blog/user33426/solution-p3071 莫名其妙RE ...

  7. Linux通过端口号查看使用进程-结束进程

    1. 查看进程(参数带 - 与不带有区别): command [options] 例:ps  -a(配合其他options参数以展示进程更多参数) ps -ef | grep 进程名(返回值是该进程的 ...

  8. arXiv网站

    arXiv 原先是由物理学家保罗·金斯巴格在1991年建立的网站, 我们会将预稿上传到arvix作为预收录,因此这就是个可以证明论文原创性(上传时间戳)的文档收录网站.

  9. Java HashMap用法

    为了做题用Java语法替代C++map的常用语法,记录一下,剖析原理以后再补上. 1.import java.util.HashMap;//导入; 2.HashMap<K, V> map= ...

  10. PyCharm工具配置和快捷键使用

    PyCharm是一款高效开发Python程序的IDE,包含有自动联想.语法高亮.代码调试.管理多个版本Python解释器等功能.本文主要描述Python界面个性化定制方法(字体.颜色配置).常用配置和 ...