在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();

时间: 2024-08-07 19:16:30

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

设置和获取与执行环境相关的信息?

设置和获取与执行环境相关的信息? HostingEnvironment是承载应用当前执行环境的描述,它是对所有实现了IHostingEnvironment接口的所有类型以及对应对象的统称.如下面的代码片段所示,一个HostingEnvironment对象承载的执行环境的描述信息体现在定义这个接口的6个属性上.ApplicationName和EnvironmentName分别代表当前应用的名称和执行环境的名称.WebRootPath和ContentRootPath是指向两个根目录的路径,前者指向的

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

在<中篇>中,我们对管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.总的来说,管道由一个服务器和一个HttpApplication构成,前者负责监听请求并将接收的请求传递给给HttpApplication对象处理,后者则将请求处理任务委托给注册的中间件来完成.中间件的注册是通过ApplicationBuilder对象来完成的,所以我们先来了解一下这究竟是个怎样的对象.[本文已经同步到<ASP.NET Core框架揭秘>之中] [

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

.NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中.对于分布式缓存,.NET Core提供了针对Redis和SQL Server的原生支持.除了这个独立的缓存系统之外,ASP.NET Core还借助一个中间件实现了“响应缓存”,它会按照HTTP缓存规范对整个响应实施缓存.不过按照惯例,在对缓存进行系统介绍之前,我们还是先通过一些简单的实例演示感知一下如果在一个ASP.NET Core应用中如何

asp.net core mvc中如何把二级域名绑定到特定的控制器上

由于公司的工作安排,一直在研究其他技术,所以一直没时间更新博客,今天终于可以停下手头的事情,写一些新内容了. 应用场景:企业门户网站会根据内容不同,设置不同的板块,如新浪有体育,娱乐频道,等等.有的情况下需要给不同的板块设置不同的二级域名,如新浪体育sports.sina.com.cn. 在asp.net core mvc中,如果要实现板块的效果,可能会给不同的板块建立不同的控制器(当然也有其他的技术,这里不讨论实现方式的好坏),在这种情况下,如何给控制器绑定上独有的二级域名,比如体育频道对应的

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 views and layout pages 修改视图和布局页 2.Change the title and menu link in the layout file 在布局文件中修改标题与菜单 3.Passing Data from the Controller to the View 从控制器向视图

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

在 ASP.NET MVC 早期版本中,我们可以通过在应用的 RegisterRoutes 方法中设置 routes.LowercaseUrls = true ; 来将页面的 URL 链接转小写.在 ASP.NET Core MVC 中,路由的配置类似与下面的代码: app.UseMvc(configureRoutes => { configureRoutes.MapRoute("Default", "{controller=App}/{action=Index}/{i

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

有时候,我们会遇到一些跟系统当前时间相关的需求,例如: 只有开学季才允许录入学生信息 只有到了晚上或者周六才允许备份博客 注册满 3 天的用户才允许进行一些操作 某用户在 24 小时内被禁止发言 很显然,要实现这些功能的代码多多少少要用到 DateTime.Now 这个静态属性,然而要使用单元测试或者集成测试对上述需求进行验证,往往需要采用一些曲线救国的方法甚至是直接跳过这些测试,这是因为在 .Net 中,DateTime.Now 通常难以被 Mock .这时候我就要夸一夸 Angular 的测

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

Http GET方法 首先我们来看看GET方法的Http请求,URL参数和ASP.NET Core MVC中Controller的Action方法参数匹配情况. 我定义一个UserController,其中有一个只接受GET请求的Action方法GetDataInPage public class UserController : Controller { [HttpGet] public IActionResult GetDataInPage(string languageCode, int

如何在ASP.NET Core应用中实现与第三方IoC/DI框架的整合?

我们知道整个ASP.NET Core建立在以ServiceCollection/ServiceProvider为核心的DI框架上,它甚至提供了扩展点使我们可以与第三方DI框架进行整合.对此比较了解的读者朋友应该很清楚,针对第三方DI框架的整合可以通过在定义Startup类型的ConfigureServices方法返回一个ServiceProvider来实现.但是真的有这么简单吗? 一.ConfigureServices方法返回的ServiceProvider貌似没有用!? 我们可以通过一个简单的