在ASP.NET Core应用中如何设置和获取与执行环境相关的信息?
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应用中如何设置和获取与执行环境相关的信息?的更多相关文章
- ASP.NET MVC和ASP.NET Core MVC中获取当前URL/Controller/Action (转载)
ASP.NET MVC 一.获取URL(ASP.NET通用): [1]获取完整url(协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [ ...
- ASP.NET Core MVC 中设置全局异常处理方式
在asp.net core mvc中,如果有未处理的异常发生后,会返回http500错误,对于最终用户来说,显然不是特别友好.那如何对于这些未处理的异常显示统一的错误提示页面呢? 在asp.net c ...
- 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[下]:管道是如何构建起来的?
在<中篇>中,我们对管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.总的来说,管道由一个服务器和一个HttpApplication构成 ...
- ASP.NET Core中的缓存[1]:如何在一个ASP.NET Core应用中使用缓存
.NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中.对于分布式缓存,.NET Core提供了针对 ...
- 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 ...
- 在 ASP.NET Core 项目中实现小写的路由URL
在 ASP.NET MVC 早期版本中,我们可以通过在应用的 RegisterRoutes 方法中设置 routes.LowercaseUrls = true ; 来将页面的 URL 链接转小写.在 ...
- 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 ...
- 如何在 ASP.NET Core 测试中操纵时间?
有时候,我们会遇到一些跟系统当前时间相关的需求,例如: 只有开学季才允许录入学生信息 只有到了晚上或者周六才允许备份博客 注册满 3 天的用户才允许进行一些操作 某用户在 24 小时内被禁止发言 很显 ...
- ASP.NET Core MVC中URL和数据模型的匹配
Http GET方法 首先我们来看看GET方法的Http请求,URL参数和ASP.NET Core MVC中Controller的Action方法参数匹配情况. 我定义一个UserController ...
随机推荐
- CoreCLR源码探索(一) Object是什么
.Net程序员们每天都在和Object在打交道 如果你问一个.Net程序员什么是Object,他可能会信誓旦旦的告诉你"Object还不简单吗,就是所有类型的基类" 这个答案是对的 ...
- ArcGIS 10.0紧凑型切片读写方法
首先介绍一下ArcGIS10.0的缓存机制: 切片方案 切片方案包括缓存的比例级别.切片尺寸和切片原点.这些属性定义缓存边界的存在位置,在某些客户端中叠加缓存时匹配这些属性十分重要.图像格式和抗锯齿等 ...
- [BOT] 一种android中实现“圆角矩形”的方法
内容简介 文章介绍ImageView(方法也可以应用到其它View)圆角矩形(包括圆形)的一种实现方式,四个角可以分别指定为圆角.思路是利用"Xfermode + Path"来进行 ...
- JavaScript动画-磁性吸附
▓▓▓▓▓▓ 大致介绍 磁性吸附是以模拟拖拽为基础添加一个拖拽时范围的限定而来的一个效果,如果对模拟拖拽有疑问的同学请移步模拟拖拽. 源代码.效果:点这里 ▓▓▓▓▓▓ 范围限定(可视区) 先来看一个 ...
- [原] KVM 虚拟化原理探究(4)— 内存虚拟化
KVM 虚拟化原理探究(4)- 内存虚拟化 标签(空格分隔): KVM 内存虚拟化简介 前一章介绍了CPU虚拟化的内容,这一章介绍一下KVM的内存虚拟化原理.可以说内存是除了CPU外最重要的组件,Gu ...
- [WPF] Wait for a moment.
一.控件介绍 在 WPF 中使用的等待控件,控件包括三种,普通的等待信息提示(WaitTip),进度条提示(WaitProgress),以及主程序覆盖的模拟时钟等待窗口(WaitClock),具体效果 ...
- 如何为你的微信小程序体积瘦身?
众所周知,微信小程序在发布的时候,对提交的代码有1M大小的限制!所以,如果你正在写一个功能稍微复杂一点的小程序,就必须得时刻小心注意你的代码是不是快触及这个底线了. 在设计一个小程序之初,我们就需要重 ...
- Android 死锁和重入锁
死锁的定义: 1.一般的死锁 一般的死锁是指多个线程的执行必须同时拥有多个资源,由于不同的线程需要的资源被不同的线程占用,最终导致僵持的状态,这就是一般死锁的定义. package com.cxt.t ...
- 【一起学OpenFOAM】03 OpenFOAM基本使用流程
OpenFOAM初学者常常对于软件的使用流程感到很迷惑,与其他的具有GUI的CFD软件不同,OpenFOAM的所有操作均为基于文本操作,譬如说里面各种计算模型.计算参数.流程控制参数等,均为通过修改对 ...
- Xamarin和微软发起.NET基金会
新闻<微软宣布成立.NET基金会全面支持开源项目 包括C#编译器Roslyn>,看到大家对微软的开放都很兴奋.在此之前在.NET社区也有了大量的开源项目,所列的24个项目也是早就开源,这次 ...