HostingEnvironment是承载应用当前执行环境的描述,它是对所有实现了IHostingEnvironment接口的所有类型以及对应对象的统称。如下面的代码片段所示,一个HostingEnvironment对象承载的执行环境的描述信息体现在定义这个接口的6个属性上。ApplicationName和EnvironmentName分别代表当前应用的名称和执行环境的名称。WebRootPath和ContentRootPath是指向两个根目录的路径,前者指向的目录用于存放可供外界通过HTTP请求访问的资源,后者指向的目录存放的则是应用自身内部所需的资源。至于这个接口的ContentRootFileProvider和WebRootFileProvider属性返回的则是针对这两个目录的FileProvider对象。如下所示的HostingEnvironment类型是对IHostingEnvironment接口的默认实现。[本文已经同步到《ASP.NET Core框架揭秘》之中]

   1: public interface IHostingEnvironment

   2: {

   3:     string         ApplicationName { get; set; }

   4:     string         EnvironmentName { get; set; }

   5:     IFileProvider  ContentRootFileProvider { get; set; }

   6:     string         ContentRootPath { get; set; }

   7:     IFileProvider  WebRootFileProvider { get; set; }

   8:     string         WebRootPath { get; set; }

   9: }

  10:  

  11: public class HostingEnvironment : IHostingEnvironment

  12: {

  13:     string         ApplicationName { get; set; }

  14:     string         EnvironmentName { get; set; }

  15:     IFileProvider  ContentRootFileProvider { get; set; }

  16:     string         ContentRootPath { get; set; }

  17:     IFileProvider  WebRootFileProvider { get; set; }

  18:     string         WebRootPath { get; set; }

  19: }

一、ApplicationEnvironment

接下来我们会对HostingEnvironment对象承载的执行环境描述信息的来源进行详细介绍,不过在此之前我们有必要来了解另一个名为ApplicationEnvironment的类型,它定义在 “Microsoft.Extensions.PlatformAbstractions”这个NuGet包中。我们从其命名也可以看出这个对象描述的也是与执行环境相关的信息,而它承载的这些信息提下在如下四个属性成员上,它们分别表示应用的名称、基路径、版本和采用的.NET Framework。

   1: public class ApplicationEnvironment

   2: {

   3:     public string         ApplicationName {  get; }

   4:     public string         ApplicationBasePath {  get; }

   5:     public string         ApplicationVersion {  get; }

   6:     public FrameworkName  RuntimeFramework { get; }

   7: }

如果需要获取一个ApplicationEnvironment对象来描述当前执行环境,我们需要使用到如下这个名为PlatformServices的对象,它的Application属性返回的就是我们所需的ApplicationEnvironment对象。因为该类型并不存在一个公共的构函数,所以我们不能直接实例化一个PlatformServices对象,不过我们可以利用Default属性得到这个单例对象。

   1: public class PlatformServices

   2: {

   3:     private PlatformServices();

   4:     public ApplicationEnvironment     Application { get; }

   5:     public static PlatformServices    Default { get; }

   6: }

对于一个ApplicationEnvironment对象来说,它的ApplicationName、ApplicationVersion和RuntimeFramework属性决定于定义了程序入口Main方法的程序集,具体来说ApplicationName和ApplicationVersion分别返回这个程序集名称和版本,而这个编译这个程序集采用的.NET Framework的版本对应的正是RuntimeFramework属性。至于ApplicationBasePath属性,它返回的实际上是AppContext的BaseDirectoryPath属性对应的路径,运行时使用这个基础路径来解析被加载的目标程序集的真实路径。针对这四个属性的取值可以通过下面这段程序来验证。

   1: public class Program

   2: {

   3:     public static void Main()

   4:     {

   5:         Assembly assembly = typeof(Program).GetTypeInfo().Assembly;

   6:         AssemblyName assemblyName = assembly.GetName();

   7:         ApplicationEnvironment env = PlatformServices.Default.Application;

   8:  

   9:         Debug.Assert(env.ApplicationBasePath == AppContext.BaseDirectory);

  10:         Debug.Assert(env.ApplicationName == assemblyName.Name);

  11:         Debug.Assert(env.ApplicationVersion == assemblyName.Version.ToString());

  12:         Debug.Assert(env.RuntimeFramework.ToString() == assembly.GetCustomAttribute<TargetFrameworkAttribute>().FrameworkName);

  13:     }

  14: }

如果我们没有对应用的名称做显式设置,当前HostingEnvironment的ApplicationName属性体现的应用名称来源于这个ApplicationEnvironment对象的同名属性。HostingEnvironment包括ApplicationName在内的四个属性(不包括WebRootFileProvider和ContentRootFileProvider属性,因为它们决定于对应ContentRootPath和WebRootPath属性)都可以通过WebHostOptions来设置。通过前面一章的介绍我们知道WebHostOptions对象是根据WebHostBuilder的采用的配置来创建的,所以我们可以利用配置的方式来决定执行环境。

二、Configuration和WebHostOptions

对于通过HostingEnvironment的四个属性(ApplicationName、EnvironmentName、WebRootPath和ContentRootPath) 承载的四个与执行环境相关的设置,在WebHostOptions对象上都具有对应的属性,后者是前者的数据来源。由于WebHostOptions对象是WebHostBuilder根据它采用的配置来创建的,所以这些设置最初来源于使用的配置。值得一提的是,如果EnvironmentName属性未作显式设置,它使用的默认值为“Production”。

由于WebHostBuilder会采用环境变量作为配置来源,并且采用“ASPNETCORE_”作为环境变量过滤采用的前缀,所以我们完全可以按照如下的方式通过设置环境变量的方式来初始化由HostingEnvironment承载的执行环境选项。

   1: Environment.SetEnvironmentVariable("ASPNETCORE_APPLICATIONNAME", "MyApp");

   2: Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Staging");

   3: Environment.SetEnvironmentVariable("ASPNETCORE_WEBROOT", @"c:\myapp\wwwroot\");

   4: Environment.SetEnvironmentVariable("ASPNETCORE_CONTENTROOT", @"c:\myapp\contentroot");

   5:  

   6: new WebHostBuilder()

   7:     .UseConfiguration(new ConfigurationBuilder().AddJsonFile("weboptions.json"))

   8:     .ConfigureServices(svcs => {

   9:         IHostingEnvironment env = svcs.BuildServiceProvider().GetRequiredService<IHostingEnvironment>();

  10:         Debug.Assert(env.ApplicationName == "MyApp");

  11:         Debug.Assert(env.EnvironmentName == "Staging");

  12:         Debug.Assert(env.WebRootPath == @"c:\myapp\wwwroot\");

  13:         Debug.Assert(env.ContentRootPath == @"c:\myapp\contentroot");

  14:     })

  15:     .UseKestrel()

  16:     .Build();

虽然WebHostBuilder默认使用环境变量作为配置源,但是我们可以显式地创建一个Configuration对象并通过调用它的扩展方法UseConfiguration进行“导入”。对于上面这段程序,如果我们将配置定义在一个具有如下结构的JSON文件(weboptions.json),我们只需要在创建WebHost之前按照如下的方式调用UseConfiguration方法将对应配置导入进来即可。

weboptions.json:

   1: {

   2:   "applicationName": "MyApp",

   3:   "environment"    : "Staging",

   4:   "webRoot"        : "c:\\myapp\\wwwroot",

   5:   "contentRoot"    : "c:\\myapp\\contentroot"

   6: }

Program

   1: new WebHostBuilder()

   2:     .UseConfiguration(new ConfigurationBuilder().AddJsonFile("weboptions.json").Build())

   3:     .ConfigureServices(svcs => {

   4:         IHostingEnvironment env = svcs.BuildServiceProvider().GetRequiredService<IHostingEnvironment>();

   5:         Debug.Assert(env.ApplicationName  == "MyApp");

   6:         Debug.Assert(env.EnvironmentName  == "Staging");

   7:         Debug.Assert(env.WebRootPath       == @"c:\myapp\wwwroot\");

   8:         Debug.Assert(env.ContentRootPath  == @"c:\myapp\contentroot");

   9:     })

  10:     .UseKestrel()

  11:     .Build();

三、特殊的ApplicationName

对于HostingEnvironment的这四个属性来说,表示应用名称的ApplicationName比较特殊。虽然它的初始值来源于配置,当我们调用Configure方法或者UseStartup方法是,这个属性会被覆盖。如下这段程序与上面不同之处在于创建WebHost之前调用Configure方法,我们采用环境变量设置的应用名(“MyApp”)将失效。

   1: Environment.SetEnvironmentVariable("ASPNETCORE_APPLICATIONNAME", "MyApp");

   2: new WebHostBuilder()

   3:     .ConfigureServices(svcs => {

   4:         IHostingEnvironment env = svcs.BuildServiceProvider().GetRequiredService<IHostingEnvironment>();

   5:         Debug.Assert(env.ApplicationName != "MyApp");

   6:     })

   7:     .UseKestrel()

   8:     .Configure(app => {})

   9: .Build();

其实这个问题的答案我们在《应用的入口——Startup》中已经给出了。如下所示的是WebHostBuilder用于注册Startup的两个扩展方法Configure和UseStartup的定义,我们可以清楚地看到在创建并注册Startup之前,它们都会设置当前应用的名称。

   1: public static class WebHostBuilderExtensions

   2: {    

   3:     public static IWebHostBuilder Configure(this IWebHostBuilder hostBuilder, Action<IApplicationBuilder> configureApp)

   4:     {

   5:         var startupAssemblyName = configureApp.GetMethodInfo().DeclaringType.GetTypeInfo().Assembly.GetName().Name;

   6:  

   7:         return hostBuilder

   8:             .UseSetting("applicationName", startupAssemblyName)

   9:             …

  10:     }

  11:  

  12:     public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType)

  13:     {

  14:         var startupAssemblyName = startupType.GetTypeInfo().Assembly.GetName().Name;

  15:         return hostBuilder

  16:             .UseSetting("ApplicationName", startupAssemblyName)

  17:             ...           

  18:     }

  19: }

如果我们调用WebHostBuilder的UseStartup方法设置了一个启动类,那么这个类型所在的程序集名称将作为当前应用的名称。如果我们通过Configure方法并提供了一个Action<IApplicationBuilder>类型的委托对象,那么这个委托对象对应方法被定义在哪个类型中,这个类型所在的程序基名称将会作为应用名称。对于后一种情况,我们可以采用如下两种方式来提供这个Action<IApplicationBuilder>对象,最终将会导致设置的应用名称完全不同。

   1: public static class Startup

   2: {

   3:     public static void Configure(IApplicationBuilder app);

   4: }

   5:  

   6: //Configure(app=>Startup.Configure(app))

   7: new WebHostBuilder()

   8:     .ConfigureServices(svcs => {

   9:         IHostingEnvironment env = svcs.BuildServiceProvider().GetRequiredService<IHostingEnvironment>();

  10:         Debug.Assert(env.ApplicationName == Assembly.GetEntryAssembly().GetName().Name);

  11:     })

  12:     .UseKestrel()

  13:     .Configure(app=>Startup.Configure(app))

  14:     .Build();

  15:  

  16: //Configure(Startup.Configure)

  17: new WebHostBuilder()

  18:     .ConfigureServices(svcs => {

  19:         IHostingEnvironment env = svcs.BuildServiceProvider().GetRequiredService<IHostingEnvironment>();

  20:         Debug.Assert(env.ApplicationName == typeof(Startup).GetTypeInfo().Assembly.GetName().Name);

  21:     })

  22:     .UseKestrel()

  23:     .Configure(Startup.Configure)

  24:     .Build();

在ASP.NET Core应用中如何设置和获取与执行环境相关的信息?的更多相关文章

  1. ASP.NET MVC和ASP.NET Core MVC中获取当前URL/Controller/Action (转载)

    ASP.NET MVC 一.获取URL(ASP.NET通用): [1]获取完整url(协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [ ...

  2. ASP.NET Core MVC 中设置全局异常处理方式

    在asp.net core mvc中,如果有未处理的异常发生后,会返回http500错误,对于最终用户来说,显然不是特别友好.那如何对于这些未处理的异常显示统一的错误提示页面呢? 在asp.net c ...

  3. 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[下]:管道是如何构建起来的?

    在<中篇>中,我们对管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.总的来说,管道由一个服务器和一个HttpApplication构成 ...

  4. ASP.NET Core中的缓存[1]:如何在一个ASP.NET Core应用中使用缓存

    .NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中.对于分布式缓存,.NET Core提供了针对 ...

  5. 006.Adding a controller to a ASP.NET Core MVC app with Visual Studio -- 【在asp.net core mvc 中添加一个控制器】

    Adding a controller to a ASP.NET Core MVC app with Visual Studio 在asp.net core mvc 中添加一个控制器 2017-2-2 ...

  6. 在 ASP.NET Core 项目中实现小写的路由URL

    在 ASP.NET MVC 早期版本中,我们可以通过在应用的 RegisterRoutes 方法中设置 routes.LowercaseUrls = true ; 来将页面的 URL 链接转小写.在 ...

  7. 007.Adding a view to an ASP.NET Core MVC app -- 【在asp.net core mvc中添加视图】

    Adding a view to an ASP.NET Core MVC app 在asp.net core mvc中添加视图 2017-3-4 7 分钟阅读时长 本文内容 1.Changing vi ...

  8. 如何在 ASP.NET Core 测试中操纵时间?

    有时候,我们会遇到一些跟系统当前时间相关的需求,例如: 只有开学季才允许录入学生信息 只有到了晚上或者周六才允许备份博客 注册满 3 天的用户才允许进行一些操作 某用户在 24 小时内被禁止发言 很显 ...

  9. ASP.NET Core MVC中URL和数据模型的匹配

    Http GET方法 首先我们来看看GET方法的Http请求,URL参数和ASP.NET Core MVC中Controller的Action方法参数匹配情况. 我定义一个UserController ...

随机推荐

  1. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  2. 一起来玩echarts系列(一)------箱线图的分析与绘制

    一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...

  3. 结合Jexus + Kestrel 部署 asp.net core 生产环境

    ASP.NET Core 是微软的全新的框架.这一框架的目标 ︰ 跨平台 针对云应用优化 解除 System.Web 的依赖. 获得下面三个方面的优势,你可以把它认为是一个C# 版本的NodeJS: ...

  4. 干货分享:SQLSERVER使用裸设备

    干货分享:SQLSERVER使用裸设备 这篇文章也适合ORACLE DBA和MYSQL DBA 阅读 裸设备适用于Linux和Windows 在ORACLE和MYSQL里也是支持裸设备的!! 介绍 大 ...

  5. 一步一步使用ABP框架搭建正式项目系列教程

    研究ABP框架好多天了,第一次看到这个框架的名称到现在已经很久了,但由于当时内功有限,看不太懂,所以就只是大概记住了ABP这个名字.最近几天,看到了园友@阳光铭睿的系列ABP教程,又点燃了我内心要研究 ...

  6. 对Castle Windsor的Resolve方法的解析时new对象的探讨

    依赖注入框架Castle Windsor从容器里解析一个实例时(也就是调用Resolve方法),是通过调用待解析对象的构造函数new一个对象并返回,那么问题是:它是调用哪个构造函数呢? 无参的构造函数 ...

  7. EventBus实现activity跟fragment交互数据

    最近老是听到技术群里面有人提出需求,activity跟fragment交互数据,或者从一个activity跳转到另外一个activity的fragment,所以我给大家介绍一个开源项目,EventBu ...

  8. H5坦克大战之【画出坦克】

    今天是个特殊的日子,圣诞节,也是周末,在这里先祝大家圣诞快乐!喜庆的日子,我们可以稍微放松一下,扯一扯昨天雷霆对战凯尔特人的比赛,这场比赛大威少又双叒叕拿下三双,而且是一个45+11+11的超级三双, ...

  9. log4net使用手册

    1. log4net简介 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.Java平台下,它还 ...

  10. RabbitMQ + PHP (一)入门与安装

    RabbitMQ: 1.是实现AMQP(高级消息队列协议)的消息中间件的一种. 2.主要是为了实现系统之间的双向解耦而实现的.当生产者大量产生数据时,消费者无法快速消费,那么需要一个中间层.保存这个数 ...