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. 初识Hadoop、Hive

    2016.10.13 20:28 很久没有写随笔了,自打小宝出生后就没有写过新的文章.数次来到博客园,想开始新的学习历程,总是被各种琐事中断.一方面确实是最近的项目工作比较忙,各个集群频繁地上线加多版 ...

  2. UIViewController生命周期-完整版

    一.UIViewController 的生命周期 下面带 (NSObject)的方法是NSObject提供的方法.其他的都是UIViewController 提供的方法. load   (NSObje ...

  3. jQuery.Ajax IE8 无效(CORS)

    今天在开发的时候,遇到一个问题,$.get()在 IE8 浏览器不起作用,但 Chrome,Firefox 却是可以的,网上资料很多,最后发现是 IE8 默认不支持 CORS 请求,需要手动开启下: ...

  4. C#中将DataTable导出为HTML的方法

    今天我要向大家分享一种将DataTable导出为到HTML格式的方法.有时我们需要HTML格式的输出数据, 以下代码就可以帮助我们达到目的,. 首先,我们要绑定DataTable和 DataGridV ...

  5. AFNetworking 3.0 源码解读(十)之 UIActivityIndicatorView/UIRefreshControl/UIImageView + AFNetworking

    我们应该看到过很多类似这样的例子:某个控件拥有加载网络图片的能力.但这究竟是怎么做到的呢?看完这篇文章就明白了. 前言 这篇我们会介绍 AFNetworking 中的3个UIKit中的分类.UIAct ...

  6. Autofac - 属性注入

    属性注入不同于通过构造函数方式传入参数. 这里是通过注入的方式, 在类创建完毕之后, 资源释放之前, 给属性赋值. 这里, 我重新弄一些类来演示这一篇吧. public class ClassA { ...

  7. .Net语言 APP开发平台——Smobiler学习日志:如何快速在手机上实现ContextMenu

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 样式一 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的&qu ...

  8. Flex 布局教程:实例篇

    该教程整理自 阮一峰Flexible教程 今天介绍常见布局的Flex写法.你会看到,不管是什么布局,Flex往往都可以几行命令搞定. 我的主要参考资料是Landon Schropp的文章和Solved ...

  9. iOS之解决崩溃Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.

    崩溃提示:Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <CAL ...

  10. class-dump 反编译私有的库和应用

    一.下载并安装class-dump 下载class-dump-3.5.dmg  点击下载 下载完成以后双击.dmg的文件,将里面的class-dump拷贝到/usr/local/bin 设置权限chm ...