在我的 .NET Core 应用程序中,我向 appsettings.json 添加了一个数组,如下所示:
{
"SettingsA": {
"PropA": [
"ChildObjectA": {
...
},
"ChildObjectB": {
...
}
]
}
}
如果我想在我的azure应用程序服务中的应用程序设置中覆盖该值,以便它将具有空数组:
{
"SettingsA": {
"PropA": []
}
}
有办法做到这一点吗?
我试着放
SettingsA:PropsA -> []
在应用程序设置中,但它似乎没有覆盖appsettings.json的值
为了补充这里已经给出的所有精彩答案,以下是我们在现实生活场景中的做法。
我们需要在应用程序设置中配置一组支持的语言。这是我们的 .NET Core 项目的 appSettings.json 中的样子:
{
...
"SupportedLanguages": [
{
"Code": "en-AU",
"Name": "English (Australia)"
},
{
"Code": "en-GB",
"Name": "English (United Kingdom)"
},
{
"Code": "en-US",
"Name": "English (United States)"
}
]
}
这就是它最终在我们的 Azure 应用服务中的样子:
这有点繁琐,特别是如果您有更大或更复杂的层次结构,但我认为目前没有其他方法。
这里的答案https://www.ryansouthgate.com/2016/03/23/iconfiguration-in-netcore/是你可以覆盖数组中的元素或添加其他元素,但他说你不能覆盖整个阵列,这看起来很奇怪。
覆盖语法使用从零开始的访问,例如 SettingsA:PropA:0:Something,我已在应用服务上尝试过此操作,并可以确认它是否有效。
为此,在 Azure 上使用多平台语法,请使用 __
这种方式适用于 Windows 和 Linux 部署的应用服务:
SettingsA__PropA__0__Something
您可以使用
AddEnvironmentVariables
属性来实现 覆盖 azure 上的应用程序设置 到本地设置。
注意:这里的值为空。
要覆盖“应用程序设置”部分中的嵌套键,我们可以使用完整路径
SettingsA:PropA
作为名称或使用双下划线SettingsA__PropA
来定义变量。你可以参考这篇文章。
在本地,您可以进行如下配置: 在 Startup.cs 中:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
configuration = builder.Build();
}
public IConfiguration configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddOptions();
services.Configure<SettingsOptions>(configuration.GetSection("SettingsA"));
}
在 appsettings.json 中:
{"SettingsA": {
"PropA": ["a","b"]
}
}
在 HomeController 中:
private readonly IOptions<SettingsOptions> options;
public HomeController(IOptions<SettingsOptions> options)
{
this.options = options;
}
public IActionResult Index()
{
var value = options.Value;
ViewBag.Index = value.PropA+"success";
return View();
}
在设置选项中:
public class SettingsOptions
{
public string SettingsA { get; set; }
public string PropA { get; set; }
}
将项目发布到azure后,它将覆盖PropA值。 更多关于如何从asp.net core读取appsetting的详细信息,请关注这个案例。
这是微软团队非常奇怪的行为。看来他们并没有意识到现实是什么样的。
我最终得到了一个带有逗号分隔值的字符串而不是数组。
(这个答案是对@Lukos'和@KenR's答案的补充。)
我遇到了与 OP 类似的场景,我需要在 Azure 门户中的 Web
App Service
的应用程序设置中覆盖值或清空数组。为了避免手动输入过程,我生成了 JavaScript,以自动将 appsettings.json
中使用的 JSON 转换为 Azure 门户中批量编辑/导入中使用的 JSON 格式。 此处和此处列出了批量编辑/导入 JSON 格式。
下面的 HTML/CSS/JavaScript 代码段包含一个用于清空数组中所有值的复选框和一个用于设置分隔符的文本输入控件(例如
__
双下划线或 :
冒号)。
该代码片段很基本,在此作为简单示例列出。我上传了带有 UI 的完整工具来处理嵌套数组和属性。
document.addEventListener("DOMContentLoaded", initialize);
let sourceEl,
resultEl,
separatorEl,
emptyArrEl;
let resultArr,
sep,
setValToEmpty;
function initialize() {
sourceEl = document.querySelector("#source-str");
resultEl = document.querySelector("#result");
separatorEl = document.querySelector("#separator-input");
emptyArrEl = document.querySelector("#empty-arr-input");
document.querySelector("#convert-src").addEventListener("click", convertClick);
}
function convertClick() {
const sourceStr = sourceEl.value;
const sepChar = separatorEl.value;
const emptyArr = emptyArrEl.checked;
const convertResult = convert(sourceStr, sepChar, emptyArr);
if (!Array.isArray(convertResult)) {
console.error(convertResult);
return;
}
const json = JSON.stringify(resultArr, undefined, 2);
resultEl.textContent = json;
//resultEl.scrollIntoView({ behavior: "smooth" });
}
function convert(sourceStr, sepChar, emptyArr) {
if (!sourceStr) {
return {
message: "An appsettings.json array string was not entered into the text area"
};
}
// Remove whitespace from both ends of the source string
sourceStr = sourceStr.trim();
// Add an open curly bracket ('{') if this character
// is not at the beginning of the trimmed string.
// Assume a close curly bracket does not exist
// if an opening curly bracket does not exist.
if (sourceStr.indexOf("{") !== 0) {
sourceStr = "{" + sourceStr + "}";
}
// Convert the source string into an object using
// 'JSON.parse()' within a 'try...catch' statement.
let srcObj;
try {
srcObj = JSON.parse(sourceStr);
} catch (error) {
return error;
}
resultArr = [];
// If the separator input control returns an empty value,
// then default to a double underscore ("__")
// (a multiplataform syntax on Azure App Service).
sep = !sepChar ? "__" : sepChar;
setValToEmpty = emptyArr;
parseObj(srcObj, "");
return resultArr;
}
// Use template literals with backticks (`${value}`)
// to convert non-strings (e.g. boolean, numbers) to string.
function parseObj(obj) {
// Set the 'arrName' variable to the key
for (let [arrName, value] of Object.entries(obj)) {
if (Array.isArray(value)) {
iterateNamedArray(arrName, value);
}
}
}
function iterateNamedArray(arrName, value) {
for (let i = 0; i < value.length; i++) {
if (typeof value[i] === "object") { // Array of objects
if (setValToEmpty) {
const name = `${arrName}${sep}${i}`;
resultArr.push({
name: name,
value: ""
});
continue;
}
// Iterate entries of 'value[i]' object
for (let [propName, propValue] of Object.entries(value[i])) {
const name = `${arrName}${sep}${i}${sep}${propName}`;
resultArr.push({
name: name,
value: `${propValue}`
});
}
} else { // Array of strings, integers, booleans
const name = `${arrName}${sep}${i}`;
if (setValToEmpty) {
value[i] = "";
}
resultArr.push({
name: name,
value: `${value[i]}`
});
}
}
}
body {
display: grid;
grid-gap: 0.5rem;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
h4 {
margin: 0;
padding: 0
}
#source-str {
width: 80%;
height: 10rem;
padding: 0.5rem 1rem;
border: 1px solid #ddd;
font-size: 0.95rem;
white-space: pre;
margin-bottom: 1rem;
}
#result {
background: #f7f7f7;
border: 1px solid #ddd;
border-left: 3px solid #1c8dc3;
margin: 0;
padding: 0.5rem 1rem;
box-sizing: border-box;
font-size: 1rem;
line-height: 1.6;
width: 90%;
min-height: 15rem;
white-space: pre-wrap;
}
#controls {
display: flex;
flex-direction: row;
gap: 2rem;
align-items: center;
align-content: center;
margin-bottom: 1rem;
}
#convert-src {
background-color: #1c8dc3;
color: #fff;
padding: 0.5rem;
border: unset;
width: fit-content;
}
label {
display: grid;
grid-auto-flow: column;
justify-content: start;
grid-gap: .5rem;
align-items: center;
}
#separator-input {
width: 2rem;
height: 1.5rem;
text-align: center;
font-weight: bold;
display: grid;
border: 1px solid #ddd;
}
#empty-arr-input {
width: 1.2rem;
height: 1.2rem;
}
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Convert appsettings.json to Azure bulk import - Simple</title>
<link href="~/css/convert-appsettings-simple.css" rel="stylesheet" />
</head>
<body>
<h4>appsettings.json</h4>
<textarea id="source-str" title="appsettings JSON text">
"SupportedLanguages": [
{
"Code": "en-AU",
"Name": "English (Australia)"
},
{
"Code": "en-GB",
"Name": "English (United Kingdom)"
},
{
"Code": "en-US",
"Name": "English (United States)"
}
],
"Unsupported": [
{
"Code": "fr-FR",
"Name": "French (France)"
},
{
"Code": "fr-CA",
"Name": "French (Canada)"
}
],
"SpellCheckers": [
"UKEng.dll",
"AusEng.dll"
]
</textarea>
<div id="controls">
<label>
<span>Separator</span>
<input type="text" id="separator-input" value="__" />
</label>
<label>
<span>Empty array</span>
<input type="checkbox" id="empty-arr-input" />
</label>
<button type="button" id="convert-src">Convert</button>
</div>
<h4>Azure bulk edit JSON</h4>
<pre id="result"></pre>
<script type="module" src="~/js/convert-appsettings-simple.js"></script>
</body>
</html>
应用程序设置中的设置会在运行时注入到您的appsettings.json
供您参考。您可以在发布期间通过 VSTS 覆盖设置。以下是Colin 的 ALM 角构建和发布工具和教程的链接。更详细的可以参考上一篇psycho的回复
如果需要在 VSTS 发布活动期间(在将其发布到 Azure 之前)覆盖 appsettings.json 的值,可以使用 Colin 的 ALM Corner 构建和发布工具。