ASP.NET Core Web主机(IWebHostBuilder)

1.前言

ASP.NET Core应用程序可以配置和启动主机(Host)。主机负责应用程序启动和生存期管理,配置服务器和请求处理管道。主机还可以设置日志记录、依赖关系注入和配置。而host主机又包括Web主机(IWebHostBuilder)和通用主机(IHostBuilder)。该章节主要介绍了用于托管Web应用的Web主机。对于其他类型的应用,请使用通用主机。

2.设置主机

创建使用IWebHostBuilder实例的主机。通常在应用程序的入口点来执行Main方法。在项目模板中,Main位于Program.cs。典型应用默认调用CreateDefaultBuilder来开始创建主机:

1.  public  class  Program
2.  {
3.  public  static  void  Main(string[] args)
4.  {
5.  CreateWebHostBuilder(args).Build().Run();
6.  }
7.  public  static  IWebHostBuilder  CreateWebHostBuilder(string[] args)  =>
8.  WebHost.CreateDefaultBuilder(args)
9.  .UseStartup<Startup>();
10.  }

2.1执行下列任务

调用CreateDefaultBuilder的代码位于名为CreateWebHostBuilder的方法中,这让它区分于 Main中对生成器对象调用Run的代码。CreateDefaultBuilder执行下列任务:
●使用应用程序的托管配置提供应用程序将Kestrel服务器配置为Web服务器。
●将内容根设置为由 Directory.GetCurrentDirectory返回的路径。
●通过以下对象加载主机配置:
○前缀为ASPNETCORE_的环境变量(例如,ASPNETCORE_ENVIRONMENT)。
○命令行参数。
●按以下顺序加载应用程序配置:
○appsettings.json。
○appsettings.{Environment}.json。
○应用在使用入口程序集的Development环境中运行时的机密管理器。
○环境变量。
○命令行参数。
●配置控制台和调试输出的日志记录。日志记录包含appsettings.json或appsettings.{Environment}.json文件的日志记录配置部分中指定的日志筛选规则。
●使用ASP.NET Core模块在IIS后面运行时,CreateDefaultBuilder会启用IIS集成,这会配置应用程序的基址和端口。IIS集成还配置应用程序以捕获启动错误。
●如果应用环境为“开发(Development)”,请将ServiceProviderOptions.ValidateScopes设为true。

2.2重写和增强定义的配置

ConfigureAppConfiguration、ConfigureLogging以及IWebHostBuilder的其他方法和扩展方法可重写和增强CreateDefaultBuilder定义的配置。下面是一些示例:
ConfigureAppConfiguration:用于指定应用的其他IConfiguration。下面的ConfigureAppConfiguration调用添加委托,以在appsettings.xml文件中添加应用配置,该示例在Core系列第11章节有演示。可多次调用ConfigureAppConfiguration。请注意,此配置不适用于主机(例如,服务器URL或环境)。


1.  public  static  IWebHostBuilder  CreateWebHostBuilder(string[] args)  =>
2.  WebHost.CreateDefaultBuilder(args)
3.  .ConfigureAppConfiguration((hostingContext, config)  =>
4.  {
5.  config.AddXmlFile("appsettings.xml", optional:  true, reloadOnChange:  true);
6.  });

ConfigureLogging:ConfigureLogging调用添加委托,将最小日志记录级别 (SetMinimumLevel)配置为LogLevel.Warning。此设置重写CreateDefaultBuilder在appsettings.Development.json和appsettings.Production.json中配置,分别为LogLevel.Debug和LogLevel.Error。可多次调用 ConfigureLogging。

1.  public  static  IWebHostBuilder  CreateWebHostBuilder(string[] args)  =>
2.  WebHost.CreateDefaultBuilder(args)
3.  .ConfigureLogging(logging =>
4.  {
5.  logging.SetMinimumLevel(LogLevel.Warning);
6.  });

ConfigureKestrel:调用ConfigureKestrel来重写CreateDefaultBuilder在配置Kestrel时建立的30,000,000字节默认Limits.MaxRequestBodySize:

1.  public  static  IWebHostBuilder  CreateWebHostBuilder(string[] args)  =>
2.  WebHost.CreateDefaultBuilder(args)
3.  .ConfigureKestrel((context, options)  =>
4.  {
5.  options.Limits.MaxRequestBodySize  =  ;
6.  });

设置主机时,可以提供配置和ConfigureServices方法。如果指定Startup类,必须定义Configure方法。

3.主机配置值

WebHostBuilder依赖于以下的方法设置主机配置值:
●主机生成器配置,其中包括格式ASPNETCORE_{configurationKey}的环境变量。例如 ASPNETCORE_ENVIRONMENT。
●UseContentRoot和UseConfiguration等扩展。
●UseSetting和关联键。使用UseSetting设置值时,该值设置为无论何种类型的字符串。

3.1应用程序键(名称)

在主机构造期间调用UseStartup或Configure时,会自动设置 IHostingEnvironment.ApplicationName属性。该值设置为包含应用入口点的程序集的名称。要显式设置值,请使用WebHostDefaults.ApplicationKey(环境变量:ASPNETCORE_APPLICATIONNAME):

1.  public  void  Configure(IApplicationBuilder app,  IHostingEnvironment env)
2.  {
3.  //应用程序默认名称为:CoreWeb (也就是项目名称)
4.  string an = env.ApplicationName;
5.  ...}
6.  public  static  IWebHostBuilder  CreateWebHostBuilder(string[] args)  =>
7.  WebHost.CreateDefaultBuilder(args).UseStartup<Startup>()
8.  .UseSetting(WebHostDefaults.ApplicationKey,  "CoreWeb");

3.2捕获启动错误

此设置控制启动错误的捕获。当false时,启动期间出错导致主机退出。当true时,主机在启动期间捕获异常并尝试启动服务器。(环境变量:ASPNETCORE_CAPTURESTARTUPERRORS)

1.  WebHost.CreateDefaultBuilder(args)
2.  .CaptureStartupErrors(true)

3.3内容根

此设置确定ASP.NET Core开始搜索内容文件,如MVC视图等。内容根也用作Web根设置的基路径。如果路径不存在,主机将无法启动。(环境变量:ASPNETCORE_CONTENTROOT)

1.  WebHost.CreateDefaultBuilder(args)
2.  .UseContentRoot("c:\\<content-root>")

3.4详细错误

确定是否应捕获详细错误。启用(或当环境设置为Development)时,应用捕获详细的异常。(环境变量:ASPNETCORE_DETAILEDERRORS)

1.  WebHost.CreateDefaultBuilder(args)
2.  .UseSetting(WebHostDefaults.DetailedErrorsKey,  "true")

3.5环境

设置应用程序的环境。环境可以设置为任何值。框架定义的值包括Development、Staging和Production。值不区分大小写。默认情况下,从ASPNETCORE_ENVIRONMENT环境变量读取环境。使用Visual Studio时,可能会在launchSettings.json文件中设置环境变量。有关于环境详情信息,可以移步到Core系列第10章节有参阅。(环境变量:ASPNETCORE_ENVIRONMENT)

1.  WebHost.CreateDefaultBuilder(args)
2.  .UseEnvironment(EnvironmentName.Development)

3.6HTTPS端口

设置HTTPS重定向端口。用于强制实施HTTPS。(环境变量:ASPNETCORE_HTTPS_PORT)

1.  WebHost.CreateDefaultBuilder(args)
2.  .UseSetting(")

3.7服务器(Kestrel) URL

指示IP地址或主机地址,其中包含服务器应针对请求侦听的端口和协议。设置为服务器应响应的以分号分隔 (;) 的URL前缀列表。例如 http://localhost:123。使用“”指示服务器应针对请求侦听的使用特定端口和协议(例如 http://:5000)的IP地址或主机名。协议(http://或https://)必须包含每个URL。不同的服务器支持的格式有所不同。(环境变量:ASPNETCORE_URLS)

1.  WebHost.CreateDefaultBuilder(args)
2.  .UseUrls("https://*:5000;https://localhost:5001;https://hostname:5002")
image
image

4.重写配置

使用配置可以配置Web主机。在下面的示例中,主机配置是根据需要在hostsettings.json文件中指定。命令行参数可能会重写从hostsettings.json文件加载的任何配置。生成的配置(在config中)用于通过UseConfiguration配置主机。
新建一个hostsettings.json文件,内容如下:

1.  {
2.  "urls":  "https://*:5005"
3.  }
1.  public  static  IWebHostBuilder  CreateWebHostBuilder(string[] args)
2.  {
3.  //IConfigurationBuilder的配置主机
4.  var config =  new  ConfigurationBuilder()
5.  .SetBasePath(Directory.GetCurrentDirectory())
6.  //主机配置在hostsettings.json文件中指定
7.  .AddJsonFile("hostsettings.json", optional:  true)
8.  //输入的命令行参数可能会重写从hostsettings.json文件加载的任何配置
9.  .AddCommandLine(args)
10.  .Build();

12.  return  WebHost.CreateDefaultBuilder(args)
13.  .UseUrls("https://*:5001")
14.  .UseConfiguration(config)
15.  .Configure(app =>
16.  {
17.  //生成的配置委托函数
18.  app.Run(context =>
19.  context.Response.WriteAsync("Hello, World!"));
20.  });
21.  }

上述代码描述意思是若要指定在特定的URL上运行的主机,所需的值可以在执行dotnet运行时从命令提示符传入。命令行参数重写hostsettings.json文件中的urls值,且服务器侦听端口8080:

1.  dotnet run --urls "http://*:8080"

主机启动时,先用hostsettings.json config重写UseUrls提供的urls参数配置,然后再用命令行参数config重写hostsettings.json config的urls参数配置。

5.管理主机

管理主题启动方式有Run和Start两种。Run方法启动Web应用程序并阻止调用线程,直到关闭主机。Start方法通过调用自身以非阻止方式运行主机。

1.  //Run
2.  CreateWebHostBuilder(args).Build().Run();
1.  //Start:非阻止方式,所有必须加上ReadLine
2.  CreateWebHostBuilder(args).Build().Start();
3.  Console.ReadLine();

6.IHostingEnvironment接口

IHostingEnvironment接口提供有关应用的Web承载环境的信息。使用构造函数注入获取 IHostingEnvironment以使用其属性和扩展方法:

1.  //示例1:
2.  public  class  CustomFileReader
3.  {
4.  private  readonly  IHostingEnvironment _env;

6.  public  CustomFileReader(IHostingEnvironment env)
7.  {
8.  _env = env;
9.  }
10.  public  string  ReadFile(string filePath)
11.  {
12.  var fileProvider = _env.WebRootFileProvider;
13.  // Process the file here
14.  }
15.  }

可以用于在启动时基于环境配置应用程序或者将IHostingEnvironment注入到Startup构造函数,用于ConfigureServices:

1.  //示例2:
2.  public  class  Startup
3.  {
4.  public  Startup(IHostingEnvironment env)
5.  {
6.  HostingEnvironment  = env;
7.  }
8.  public  IHostingEnvironment  HostingEnvironment  {  get;  }
9.  public  void  ConfigureServices(IServiceCollection services)
10.  {
11.  if  (HostingEnvironment.IsDevelopment())
12.  {
13.  // Development configuration
14.  }
15.  else
16.  {
17.  // Staging/Production configuration
18.  }
19.  var contentRootPath =  HostingEnvironment.ContentRootPath;
20.  }
21.  }

IHostingEnvironment服务还可以直接注入到Configure方法以设置处理管道:

1.  //示例3:
2.  public  void  Configure(IApplicationBuilder app,  IHostingEnvironment env)
3.  {
4.  if  (env.IsDevelopment())
5.  {
6.  // In Development, use the Developer Exception Page
7.  app.UseDeveloperExceptionPage();
8.  }
9.  else
10.  {
11.  // In Staging/Production, route exceptions to /error
12.  app.UseExceptionHandler("/error");
13.  }
14.  var contentRootPath = env.ContentRootPath;
15.  }

创建自定义中间件(要了解中间件的同学们,可以移步到第四章节学习)时可以将IHostingEnvironment 注入Invoke方法:

1.  public async Task  Invoke(HttpContext context,  IHostingEnvironment env)
2.  {
3.  if  (env.IsDevelopment())
4.  {
5.  // Configure middleware for Development
6.  }
7.  else
8.  {
9.  // Configure middleware for Staging/Production
10.  }
11.  var contentRootPath = env.ContentRootPath;
12.  }

7.IApplicationLifetime接口

IApplicationLifetime允许后启动和关闭活动。接口上的三个属性是用于注册Action方法(用于定义启动和关闭事件)的取消标记。

取消标记 | 触发条件

ApplicationStarted | 主机已完全启动。

ApplicationStopped | 主机正在完成正常关闭。应处理所有请求。 关闭受到阻止,直到完成此事件。

ApplicationStopping | 主机正在执行正常关闭。仍在处理请求。关闭受到阻止,直到完成此事件。

1.  public  class  Startup
2.  {
3.  public  void  Configure(IApplicationBuilder app,  IApplicationLifetime appLifetime)
4.  {
5.  appLifetime.ApplicationStarted.Register(OnStarted);
6.  appLifetime.ApplicationStopping.Register(OnStopping);
7.  appLifetime.ApplicationStopped.Register(OnStopped);
8.  Console.CancelKeyPress  +=  (sender, eventArgs)  =>
9.  {
10.  appLifetime.StopApplication();
11.  // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
12.  eventArgs.Cancel  =  true;
13.  };
14.  }
15.  private  void  OnStarted()
16.  {
17.  // Perform post-startup activities here
18.  }
19.  private  void  OnStopping()
20.  {
21.  // Perform on-stopping activities here
22.  }
23.  private  void  OnStopped()
24.  {
25.  // Perform post-stopped activities here
26.  }
27.  }

StopApplication是请求应用终止的意思。以下类在调用类的Shutdown方法时使用StopApplication正常关闭应用:

1.  public  class  MyClass
2.  {
3.  private  readonly  IApplicationLifetime _appLifetime;
4.  public  MyClass(IApplicationLifetime appLifetime)
5.  {
6.  _appLifetime = appLifetime;
7.  }
8.  public  void  Shutdown()
9.  {
10.  _appLifetime.StopApplication();
11.  }
12.  }

8.作用域验证

如果应用环境为“开发(Development)”,则CreateDefaultBuilder将ServiceProviderOptions.ValidateScopes设为true。若将ValidateScopes设为true,默认服务提供应用程序会执行检查来验证以下内容:
●作用域服务不能直接或间接地从根服务提供者解析。
●作用域服务不会直接或间接地注入到单例中(服务的生命周期)。
若要始终验证作用域(包括在生命周期环境中验证),请使用主机生成器上的 UseDefaultServiceProvider配置ServiceProviderOptions:


1.  WebHost.CreateDefaultBuilder(args)
2.  .UseDefaultServiceProvider((context, options)  =>  {
3.  options.ValidateScopes  =  true;
4.  })

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342