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

[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.mfbz.cn/a/762095.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Es结合springboot(笔记回忆)

导包 <!--导入es--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency><groupId>org.springframework.boot<…

换天空背景的软件有哪些?摄影师必备,让背景从灰暗到绚烂

在摄影的世界里&#xff0c;背景往往能够为照片增添一种难以言喻的情感色彩。 有时&#xff0c;一个简单的天空背景更换&#xff0c;就能让整张照片焕发出全新的生命力&#xff0c;表达出摄影师想要传达的情感和故事。 如今&#xff0c;随着科技的发展&#xff0c;一些换天空…

操作系统真象还原:进一步完善内核

第12章-进一步完善内核 12.1 Linux系统调用浅析 系统调用就是让用户进程申请操作系统的帮助&#xff0c;让操作系统帮其完成某项工作&#xff0c;也就是相当于用户进程调用了操作系统的功能&#xff0c;因此“系统调用”准确地来说应该被称为“操作系统功能调用”。 Linux 系…

【必看】卖惨营销

经常卖惨的人到底是什么心理&#xff1f; Berry Ni同学说&#xff1a; 吸引别人的注意力。想要得到关注。 让你降低对他的期待。 让你能够在他做好一件小事的情况下就表扬他。 控制你对他的想法认知。 ​ 浪矢心理同学说&#xff1a; 1&#xff0c;求关注。他觉得买惨有好处&…

64.WEB渗透测试-信息收集- WAF、框架组件识别(4)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;63.WEB渗透测试-信息收集- WAF、框架组件识别&#xff08;3&#xff09;-CSDN博客 我们在…

Stable Diffusion用AI绘画古诗文视频副业项目,轻松涨粉10W+,项目拆解分享给你【附详细玩法教程】

项目介绍 古诗文自古以来就有着广泛的受众&#xff0c;特别是在短视频平台上&#xff0c;它不仅有很高的流量潜力&#xff0c;还能给观众带来美的享受和教育意义。通过使用AI绘画工具&#xff0c;创作者能够将古诗文中的场景生动地呈现出来&#xff0c;制作出有艺术性、有教育…

测评:【AI办公】版本更迭与AI加持下的最新ONLYOFFICE桌面编辑器8.1

你是否还在为没有一款合适的在线桌面编辑器而苦恼&#xff1f;你是否还在因为办公软件的选择过少而只能使用WPS或者office&#xff1f;随着办公需求的不断变化和发展&#xff0c;办公软件也在不断更新和改进。ONLYOFFICE 作为一款全功能办公软件&#xff0c;一直致力于为用户提…

代理设计模式和装饰器设计模式的区别

代理设计模式: 作用:为目标(原始对象)增加功能(额外功能,拓展功能) 三种经典应用场景: 1&#xff1a;给原始对象增加额外功能(spring添加事务,Mybatis通过代理实现缓存功能等等) 2&#xff1a;远程代理&#xff08;网络通信&#xff0c;输出传输&#xff08;RPC&#xff0c;D…

ChatGPT-4o医学应用、论文撰写、数据分析与可视化、机器学习建模、病例自动化处理、病情分析与诊断支持

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT-3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年11月7日&#xff0c;OpenAI首届开发者大会被称为“科技界的春晚”&#xff0c;吸引了全球广大…

Linux_生产消费模型_Block_Queue

目录 一、互斥锁 1.1 错误的抢票 1.1.1 类的成员函数与构造 1.1.2 start 函数 1.1.3 线程的回调函数 1.1.4 main 函数 1.1.5 结果 1.2 概念 1.3 相关系统调用 1.3.1 锁的创建 1.3.2 锁的初始化 1.3.2.1 动态初始化 1.3.2.2 静态初始化 1.3.3 锁的销毁 1.3.4…

【Linux系统】文件描述符fd

1.回顾一下文件 我们之前对文件的理解是在语言层上&#xff0c;而语言层去理解文件是不可能的&#xff01;&#xff01;&#xff01; 下面是一份c语言文件操作代码&#xff01;&#xff01;&#xff01; #include<stdio.h> int main() {FILE* fd fopen("lo…

节点级、系统级、实车级的LIN测试主要差异点

文章目录 前言一、节点级1.前期准备2.测试执行 二、系统级1.前期准备2.测试执行 三、实车级1.前期准备2.测试执行 总结 前言 LIN协议一致性测试主要指的是物理层&#xff08;电阻、电容、电压、地偏移、显隐性电平、频率占空比、位时间等&#xff09;、数据链路层&#xff08;…

mysql mgr集群断电重启

一、前言 mysql mgr集群所有节点都断电重启时&#xff0c;就会面临一个问题&#xff0c;应该怎么重新构建mgr集群 二、操作 查询所有节点的master状态 show master status; 查看同步状态&#xff0c;可以通过uuid知道是通过哪个节点进行同步的数据 查看所有节点的uuid&#x…

鸿蒙 HarmonyOs 动画效果 快速入门

一、理论 1.1 animation属性 名称参数类型必填描述durationnumber否设置动画时长&#xff0c;默认值&#xff1a;1000&#xff0c;单位&#xff1a;毫秒temponumber否动画播放速度。数值越大&#xff0c;速度越快&#xff0c;默认为1curvestring | Curve否 设置动画曲线。 默…

element el-table表格切换分页保留分页数据+限制多选数量

el-table表格并没有相关的方法来禁用表头里面的多选按钮 那么我们可以另辟蹊径&#xff0c;来实现相同的多选切换分页&#xff08;保留分页数据&#xff09; 限制多选数量的效果 <el-table:data"tableData"style"width: 100%">// 不使用el-talbe自带…

EDI是什么?与ERP有何关系

EDI的发展过程 电子数据交换&#xff08;Electronic Data Interchange&#xff0c;EDI&#xff09;是一种通过电子方式传输商业文件的技术。EDI的历史可以追溯到20世纪60年代&#xff0c;当时企业开始使用计算机进行数据处理。最早的EDI系统是为解决大型企业间的信息交换问题而…

微信AI机器人智能助手:利用大模型定制训练知识库

随着人工智能技术的迅速发展&#xff0c;AI已经渗透到了我们生活得方方面面。AI文本撰写、AI绘画、AI生成视频、AI换脸等各类应用层出不穷。作为领先的创新人工智能和元宇宙厂商&#xff0c;道可云凭借自身在人工智能、元宇宙、虚拟数字人等领域的技术积累&#xff0c;将AI技术…

文本超长省略的几种方式(vue)

第一种&#xff0c;纯css 在给容器设置宽度后&#xff0c;使用css来省略文本超长部分&#xff0c;但是这样就看不到全部的内容 <template><div class"content"><div class"text">{{ text }}</div></div> </template>&…

Vue3 登录成功,浏览器存在toke,再次访问/login路由到/index 首页页面

文章目录 目录 文章目录 流程 小结 概要流程技术细节小结 概要 首先需要清楚知道浏览器localstorage和Session storage的区别 localStorage 和 sessionStorage 是 HTML5 提供的两种客户端存储数据的方法&#xff0c;它们在使用和生命周期上有一些区别&#xff1a; 1. 生命周期…

1.回溯算法.题目

1.回溯算法.题目 题目9.子集问题10.子集||11.递增子序列12.全排列13.全排列||14.回溯算法去重问题的另外一个写法15.重新安排行程16.N皇后 总结去重方式的不同 题目 9.子集问题 &#xff08;题目链接&#xff09; 给定一组不含重复元素的整数数组 nums&#xff0c;返回该数组…