asp.net的承载环境的配置与应用

news2024/11/18 13:37:08

[S1513]基于环境变量的配置初始化

应用启动的时候会将当前的环境变量作为配置源来创建承载最初配置数据的IConfiguration对象,但它只会选择名称以“ASPNETCORE_”为前缀的环境变量(通过静态类型Host的CreateDefaultBuilder方法创建的HostBuilder默认选择的是前缀为“DOTNET_”的环境变量)。在演示针对环境变量的初始化配置之前,需要先解决配置的消费问题,即如何获取配置数据。如下面的代码片段所示,我们设置两个环境变量,它们的名称分别为"ASPNETCORE_FOO"和"ASPNETCORE_BAR"。在调用WebApplication的CreateBuilder方法创建出WebApplicationBuilder对象之后,我们将它的Configuration属性提取出来。由调试断言可以看出这两个环境变量被成功转移到配置中了。代表承载应用的WebApplication构建出来后,其Configuration属性返回的IConfiguration对象上同样包含着相同的配置。

using System.Diagnostics;

Environment.SetEnvironmentVariable("ASPNETCORE_FOO", "123");
Environment.SetEnvironmentVariable("ASPNETCORE_BAR", "456");

var builder = WebApplication.CreateBuilder(args);
IConfiguration configuration = builder.Configuration;
Debug.Assert(configuration["foo"] == "123");
Debug.Assert(configuration["bar"] == "456");

var app = builder.Build();
configuration = app.Configuration;
Debug.Assert(configuration["foo"] == "123");
Debug.Assert(configuration["bar"] == "456");

[S1514]以键值对形式读取和修改配置

我们知道IConfiguration对象是以字典的结构来存储配置数据的,我们可以利用该对象提供的索引以键值对的形式来读取和修改配置。在ASP.NET Core应用中,我们可以通过调用定义在IWebHostBuilder接口的GetSetting方法和UseSetting方法达到相同的目的。

public interface IWebHostBuilder
{
    string GetSetting(string key);
    IWebHostBuilder UseSetting(string key, string value);
    ...
}

如下面的代码片段所示,我们可以通过利用WebApplicationBuilder的WebHost属性将对应的IWebHostBuilder对象提取出来,通过调用其GetSetting方法将以环境变量设置的配置提取出来。通过调用其UseSetting方法提供的键值对会保存到应用的配置中。配置最终的状态被固定下来后转移到了构建的WebApplication对象上。

using System.Diagnostics;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseSetting("foo", "abc");
builder.WebHost.UseSetting("bar", "xyz");

Debug.Assert(builder.WebHost.GetSetting("foo") == "abc");
Debug.Assert(builder.WebHost.GetSetting("bar") == "xyz");

IConfiguration configuration = builder.Configuration;
Debug.Assert(configuration["foo"] == "abc");
Debug.Assert(configuration["bar"] == "xyz");

var app = builder.Build();
configuration = app.Configuration;
Debug.Assert(configuration["foo"] == "abc");
Debug.Assert(configuration["bar"] == "xyz");

[S1515]注册配置源(利用IWebHostBuilder)

配置系统最大的特点是可以注册不同的配置源。针对配置源的注册同样可以利用三种编程方式来实现,第一种就是利用WebApplicationBuilder的Host属性返回的IHostBuilder对象,并调用其的ConfigureHostConfiguration和ConfigureAppConfiguration方法完成针对宿主和应用的配置,其中自然包含针对配置源的注册。IWebHostBuilder接口也提供如下这个等效的ConfigureAppConfiguration方法。如代码片段所示,该方法提供的参数是一个Action<WebHostBuilderContext, IConfigurationBuilder>委托,这意味着我们可以就承载上下文对配置做针对性设置。如果提供的设置与当前承载上下文无关,我们还可以调用另一个参数类型为Action<IConfigurationBuilder>的ConfigureAppConfiguration方法重载。

public interface IWebHostBuilder
{
    IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate);
}

public static class WebHostBuilderExtensions
{
    public static IWebHostBuilder ConfigureAppConfiguration(this IWebHostBuilder hostBuilder, Action<IConfigurationBuilder> configureDelegate);
}

我们可以利用WebApplicationBuilder的WebHost属性返回对应的IWebHostBuilder对象,并采用如下的方式利用这个对象注册配置源。

using System.Diagnostics;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureAppConfiguration(config => config.AddInMemoryCollection(new Dictionary<string, string>
    {
        ["foo"] = "123",
        ["bar"] = "456"
    }));
var app = builder.Build();
Debug.Assert(app.Configuration["foo"] == "123");
Debug.Assert(app.Configuration["bar"] == "456");

[S1516]注册配置源(Minimal API)

由于WebApplicationBuilder的Configuration属性返回的ConfigurationManager自身就是一个IConfigurationBuilder对象,所以最直接的方式就是按照如下的方式将配置源注册到它上面,这也是我们提供的编程方式。值得一提的是,如果调用WebApplication类型的CreateBuilder或者Create方法时传入了命令行参数,会自动添加针对命令行参数的配置源。

using System.Diagnostics;

var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddInMemoryCollection(new Dictionary<string, string>
{
    ["foo"] = "123",
    ["bar"] = "456"
});
var app = builder.Build();
Debug.Assert(app.Configuration["foo"] == "123");
Debug.Assert(app.Configuration["bar"] == "456");

[S1517]默认的承载环境

如下面的代码片段所示,派生于IHostEnvironment接口的IWebHostEnvironment接口定义了WebRootPath和WebRootFileProvider属性,前者表示用于存放Web资源文件根目录的路径,后者则返回该路径对应的IFileProvider对象。如果我们希望外部可以采用HTTP请求的方式直接访问某个静态文件(如JavaScript、CSS和图片文件等),只需要将它存放于WebRootPath属性表示的目录之下即可。当前承载环境之间反映在WebApplicationBuilder类型如下所示的Environment属性中。代表承载应用的WebApplication类型同样具有这样一个属性。

public interface IWebHostEnvironment : IHostEnvironment
{
    string 		WebRootPath { get; set; }
    IFileProvider 	WebRootFileProvider { get; set; }
}

public sealed class WebApplicationBuilder
{
    public IWebHostEnvironment Environment { get; }
    ...
}

public sealed class WebApplication
{
    public IWebHostEnvironment Environment { get; }
    ...
}

我们简单介绍与承载环境相关的六个属性(包含定义在IHostEnvironment接口中的四个属性)是如何设置的。IHostEnvironment 接口的ApplicationName代表当前应用的名称,它的默认值为入口程序集的名称。EnvironmentName表示当前应用所处部署环境的名称,其中开发(Development)、预发(Staging)和产品(Production)是三种典型的部署环境。根据不同的目的可以将同一个应用部署到不同的环境中,在不同环境中部署的应用往往具有不同的设置。在默认情况下,环境的名称为“Production”。ASP.NET Core应用会将所有的内容文件存储在同一个目录下,这个目录的绝对路径通过IWebHostEnvironment接口的ContentRootPath属性来表示,而ContentRootFileProvider属性则返回针对这个目录的PhysicalFileProvider对象。部分内容文件可以直接作为Web资源(如JavaScript、CSS和图片等)供客户端以HTTP请求的方式获取,存放此种类型内容文件的绝对目录通过IWebHostEnvironment接口的WebRootPath属性来表示,而针对该目录的PhysicalFileProvider自然可以通过对应的WebRootFileProvider属性来获取。

在默认情况下,由ContentRootPath属性表示的内容文件的根目录就是当前工作目录。如果该目录下存在一个名为“wwwroot”的子目录,那么它将用来存放Web资源,WebRootPath属性将返回这个目录。如果这样的子目录不存在,那么WebRootPath属性会返回Null。针对这两个目录的默认设置体现在如下所示的代码片段中。

using System.Diagnostics;
using System.Reflection;

var builder = WebApplication.CreateBuilder();
var environment = builder.Environment;

Debug.Assert(Assembly.GetEntryAssembly()?.GetName().Name == environment.ApplicationName);
var currentDirectory = Directory.GetCurrentDirectory();

Debug.Assert(Equals( environment.ContentRootPath,  currentDirectory));
Debug.Assert(Equals(environment.ContentRootPath, currentDirectory));

var wwwRoot = Path.Combine(currentDirectory, "wwwroot");
if (Directory.Exists(wwwRoot))
{
    Debug.Assert(Equals(environment.WebRootPath, wwwRoot));
}
else
{
    Debug.Assert(environment.WebRootPath == null);
}

static bool Equals(string path1, string path2) =>string.Equals(path1.Trim(Path.DirectorySeparatorChar), path2.Trim(Path.DirectorySeparatorChar),StringComparison.OrdinalIgnoreCase);

[S1518]通过配置定制承载环境

IWebHostEnvironment对象承载的与承载环境相关的属性(ApplicationName、EnvironmentName、ContentRootPath和WebRootPath)可以通过配置的方式进行定制,对应配置项的名称分别为“applicationName”、“environment”、“contentRoot”和“webroot”。静态类WebHostDefaults为它们定义了对应的属性。通过第14章“服务承载”可知,前三个配置项的名称同样以静态只读字段的形式定义在HostDefaults类型中。

public static class WebHostDefaults
{
    public static readonly string EnvironmentKey 	= "environment";
    public static readonly string ContentRootKey 	= "contentRoot";
    public static readonly string ApplicationKey 	= "applicationName";
    public static readonly string WebRootKey    	= "webroot";;
}

public static class HostDefaults
{
    public static readonly string EnvironmentKey = "environment";
    public static readonly string ContentRootKey = "contentRoot";
    public static readonly string ApplicationKey = "applicationName";
}

由于应用初始化过程中的很多操作都与当前的承载环境有关,所以承载环境必须在启动应用最初的环境就被确定下来,并在整个应用生命周期内都不能改变。如果我们希望采用配置的方式来控制当前应用的承载环境,相应的设置必须在WebApplicationBuilder对象创建之前执行,在之后试图修改相关的配置都会抛出异常。按照这个原则,我们可以采用命令行参数的方式对承载环境进行设置。

var app = WebApplication.Create(args);
var environment = app.Environment;

Console.WriteLine($"ApplicationName:{environment.ApplicationName}");
Console.WriteLine($"ContentRootPath:{environment.ContentRootPath}");
Console.WriteLine($"WebRootPath:{environment.WebRootPath}");
Console.WriteLine($"EnvironmentName:{environment.EnvironmentName}");

上面的演示程序利用命令行参数的方式控制承载环境的四个属性。如代码片段所示,我们将命令行参数传入WebApplication类型的Create方法创建了一个WebApplication对象,然后从中提取出代表承载环境的IWebHostEnvironment对象并将其携带信息输出到控制台上。我们命令行的方式启动该程序,并指定了与承载环境相关的四个参数。

image


图1 利用命令行参数定义承载环境

除了命令行参数,使用环境变量同样能达到相同的目的,当时应用的名称目前无法通过对应的配置进行设置。对于上面创建的这个演示程序,我们现在换一种方式启动它。如图2所示,在执行“dotnet run”命令启动程序之前,我们为承载环境的四个属性设置了对应的环境变量。从输出的结果可以看出,除了应用名称依然是入口程序集名称外,承载环境的其他三个属性与我们设置的环境变量是一致的。

image


图2 利用环境变量定义承载环境

[S1519]利用WebApplicationOptions定制承载环境

承载环境除了可以采用利用上面演示的两种方式进行设置外,我们也可以使用如下这个WebApplicationOptions配置选项。如代码片段所示,WebApplicationOptions定义了四个属性,分别代表命令行参数数组、环境名称、应用名称和内容根目录路径。WebApplicationBuilder具有如下这个参数类型为WebApplicationOptions的CreateBuilder方法。

public class WebApplicationOptions
{
    public string[] 	Args { get; set; }
    public string 	EnvironmentName { get; set; }
    public string 	ApplicationName { get; set; }
    public string 	ContentRootPath { get; set; }
}

public sealed class WebApplication
{
    public static WebApplicationBuilder CreateBuilder(WebApplicationOptions options);
    ...
}

如果利用WebApplicationOptions来对应用所在的承载环境进行设置,上面演示的程序可以改写成如下的形式。由于WebApplicationOptions并不包含WebRootPath对应的配置选项,如果程序运行后会发现承载环境的这个属性为空。由于IWebHostEnvironment服务提供的应用名称会被视为一个程序集名称,针对它的设置会影响类型的加载,所以我们基本上不会设置应用的名称。

var options = new WebApplicationOptions
{
    Args 		= args,
    ApplicationName 	= "MyApp",
    ContentRootPath 	= Path.Combine(Directory.GetCurrentDirectory(), "contents"),
    EnvironmentName 	= "staging"
};
var app = WebApplication.CreateBuilder(options).Build();
var environment = app.Environment;
Console.WriteLine($"ApplicationName:{environment.ApplicationName}");
Console.WriteLine($"ContentRootPath:{environment.ContentRootPath}");
Console.WriteLine($"WebRootPath:{environment.WebRootPath}");
Console.WriteLine($"EnvironmentName:{environment.EnvironmentName}");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1884104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【笔记】记录一次全新的Java项目部署过程

记录一次全新的Java项目部署过程 环境&#xff1a;CentOS7 一、初始环境准备 yum install wget -y yum install vim -y yum install net-tools -y mkdir /data mkdir /data/html mkdir /data/backend一、安装JDK 17 安装JDK17 # 下载rpm wget https://download.oracle.com…

科普文:一文搞懂jvm(一)jvm概叙

概叙 因篇幅限制&#xff0c;这里将分为多篇文章来讲解。 为什么要学习jvm&#xff1f; 1.这是3年的java程序员必备技能。 2.理解“跨平台”、熟悉jvm组织结构、类的加载、双亲委派、对象在jvm中的生命周期、STD。 3.最终目的只有一个&#xff1a;用jdk提供的工具分析排查解决…

一篇带你了解ScheduledExecutorService的用法和适用场景

希望文章能给到你启发和灵感&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏 支持一下博主吧&#xff5e; 阅读指南 开篇说明一、ScheduledExecutorService的作用二、ScheduledExecutorService的使用2.1 常用方法2.2 如何关闭释放资源 三、最后 开篇说明 …

SAPUI5基础知识10 - i18与国际化

1. 背景 i18n 是 “internationalization” 的缩写&#xff0c;其中的 18 是 “internationalization” 这个单词中间的字符数。i18n 是一种让应用程序支持多种语言的方法&#xff0c;也就是我们通常所说的国际化。 在SAPUI5中&#xff0c;i18n主要通过使用资源模型&#xff…

基于Java平价平价汽车租赁系统设计和实现(源码+LW+部署讲解)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

一、课程介绍,基础—环境安装、判断、循环语句等(爬虫及数据可视化)

一、课程介绍&#xff0c;基础—环境安装、判断、循环语句等&#xff08;爬虫及数据可视化&#xff09; 1. 课程介绍1.1 相关内容1.2 学习目标1.3 学习内容安排 2. python2.1 环境配置2.2 标识符和关键字2.3 运算符2.4 判断语句2.5 循环语句 1. 课程介绍 1.1 相关内容 10天的…

一文了解IP地址冲突的起因与解决方案

IP 地址冲突是困扰网络管理员影响网络的正常运行的常见因素。深入理解并有效解决 IP 地址冲突故障对于维护网络的高效稳定运行具有重要意义。 一、IP 地址冲突的原因 &#xff08;一&#xff09;人为配置错误 网络用户在手动配置 IP 地址时&#xff0c;对网络配置了解不多用户…

HarmonyOS开发探索:父子组件手势绑定问题处理

场景一&#xff1a;父子组件同时绑定手势的冲突处理 效果图 方案 在默认情况下&#xff0c;手势事件为非冒泡事件&#xff0c;当父子组件绑定相同的手势时&#xff0c;父子组件绑定的手势事件会发生竞争&#xff0c;最多只有一个组件的手势事件能够获得响应&#xff0c;默认子…

数据结构笔记第3篇:双向链表

1、双向链表的结构 注意&#xff1a;这里的 "带头" 跟前面我们说的 "头结点" 是两个概念&#xff0c;实际前面的在单链表阶段称呼不严谨&#xff0c;但是为了同学们更好的理解就直接称为单链表的头结点。 带头链表里的头结点&#xff0c;实际为 "哨兵…

# 职场生活之道:善于团结

在职场这个大舞台上&#xff0c;每个人都是演员&#xff0c;也是观众。要想在这个舞台上站稳脚跟&#xff0c;除了专业技能&#xff0c;更要学会如何与人相处&#xff0c;如何团结他人。团结&#xff0c;是职场生存的重要法则之一。 1. 主动团结&#xff1a;多一个朋友&#x…

UE5(c++)开发日志(3):将前面写的输出日志的方法进行封装

Public下新增一个c类&#xff1a; 选择无属性&#xff0c;因为不需要添加任何东西进去, 也不需要借助里面任何东西。 创建一个命名空间Debug&#xff0c;可以在命名空间内写一点静态方法 &#xff1a; namespace Debug{} static void Print(const FString& message, con…

试用笔记之-汇通汉诺塔-益智游戏

首先下载汇通汉诺塔&#xff1a; http://www.htsoft.com.cn/download/HanoiTower.rar 汇通汉诺塔游戏规则:把X轴的圈圈都移到Z轴过关。 还可以选择自动游戏哦&#xff0c;看看AI机器人玩汇通汉诺塔

前程无忧滑块

声明(lianxi a15018601872) 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 前言(lianxi …

启智畅想火车集装箱箱号识别系统,同时识别车皮号、火车底盘号码

1、应用背景 在现代物流体系中&#xff0c;铁路集装箱运输扮演着举足轻重的角色&#xff0c;目前各个铁路系统在管理集装箱车厢进出站时&#xff0c;方法传统&#xff0c;采用人工登记集装箱箱号、车皮号以及火车底盘号码的方式&#xff0c;效率低、错误率高、人员工作量大、信…

湖北大学2024年成人高考函授报名专升本会计学专业介绍

湖北大学&#xff0c;这所坐落于历史文化名城武汉的高等学府&#xff0c;自其创立之初&#xff0c;便秉持着“厚德博学&#xff0c;求是创新”的校训&#xff0c;致力于培养一代又一代的优秀人才。而今&#xff0c;为满足广大社会人士对高等教育的渴求&#xff0c;特别是那些已…

新的里程碑丨deepin校园联盟在拉丁美洲自由软件节上的国际风采

deepin校园联盟秉持推广开源文化与技术的宗旨&#xff0c;在全球技术交流的洪流中&#xff0c;再次于海外掀起热烈浪潮。在厄瓜多尔雅才理工大学&#xff08;Yachay Tech University&#xff09;&#xff0c;deepin校园联盟大使Mosquera率领团队&#xff0c;跨越数百公里之遥&a…

Jenkins教程-12-发送html邮件测试报告

上一小节我们学习了发送钉钉测试报告通知的方法&#xff0c;本小节我们讲解一下发送html邮件测试报告的方法。 1、自动化用例执行完后&#xff0c;使用pytest_terminal_summary钩子函数收集测试结果&#xff0c;存入本地status.txt文件中&#xff0c;供Jenkins调用 #conftest…

Optional类方法

Optional类 方法empty()方法of(T value)ofNullable(T value)filter(Predicate<? super T> predicate)get()ifPresent(Consumer<? super T> consumer)isPresent()map(Function<? super T,? extends U> mapper)orElse(T other)orElseGet(Supplier<? ex…

如何实现Action菜单

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"自定义标题栏"相关的内容&#xff0c;本章回中将介绍自定义Action菜单.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里提到的…

Swift 中的 StoreKit 测试

文章目录 前言创建一个 StoreKit Demo使用 SKTestSessionaskToBuyEnabled 属性总结前言 StoreKit 框架的第二次迭代是我在过去几年中应用程序中最重大的变化。最近版本的 StoreKit 框架已完全采用了 Swift 语言特性,如 async 和 await。本篇内容我们将讨论 StoreKitTest 框架…