코드의 ASP.NET Core appsettings.json 업데이트
현재 asp.net core v1.1을 사용하여 프로젝트를 진행하고 있으며, appsettings.json에는 다음이 있습니다.
"AppSettings": {
"AzureConnectionKey": "***",
"AzureContainerName": "**",
"NumberOfTicks": 621355968000000000,
"NumberOfMiliseconds": 10000,
"SelectedPvInstalationIds": [ 13, 137, 126, 121, 68, 29 ],
"MaxPvPower": 160,
"MaxWindPower": 5745.35
},
저장하기 위해 사용하는 클래스도 있습니다.
public class AppSettings
{
public string AzureConnectionKey { get; set; }
public string AzureContainerName { get; set; }
public long NumberOfTicks { get; set; }
public long NumberOfMiliseconds { get; set; }
public int[] SelectedPvInstalationIds { get; set; }
public decimal MaxPvPower { get; set; }
public decimal MaxWindPower { get; set; }
}
DI는 Startup.cs에서 사용할 수 있습니다.
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
변경하고 저장할 수 있는 방법이 있나요?MaxPvPower
그리고.MaxWindPower
콘트롤러에서?
나는 그것을 사용해봤어요.
private readonly AppSettings _settings;
public HomeController(IOptions<AppSettings> settings)
{
_settings = settings.Value;
}
[Authorize(Policy = "AdminPolicy")]
public IActionResult UpdateSettings(decimal pv, decimal wind)
{
_settings.MaxPvPower = pv;
_settings.MaxWindPower = wind;
return Redirect("Settings");
}
하지만 아무것도 하지 않았다.
기본적으로 값을 설정할 수 있습니다.IConfiguration
다음과 같습니다.
IConfiguration configuration = ...
// ...
configuration["key"] = "value";
여기서의 문제는, 예를 들면JsonConfigurationProvider
그럼 Configuration이 파일에 저장되지 않습니다.소스에서 알 수 있듯이 Set 메서드는 덮어쓰지 않습니다.ConfigurationProvider
. (출처 참조)
독자적인 프로바이더를 작성해, 거기에 보존을 실장할 수 있습니다.여기(Entity Framework 커스텀 프로바이더의 기본 샘플)는 그 방법의 예입니다.
에서의 설정 설정에 관한 Microsoft의 관련 문서를 다음에 나타냅니다.넷 코어 애플리케이션:
페이지에는 샘플 코드도 포함되어 있어 도움이 될 수 있습니다.
갱신하다
In-memory provider 및 POCO 클래스에 대한 바인딩은 유용하다고 생각했지만 OP의 예상대로 작동하지 않습니다.
다음 옵션은 다음과 같습니다.reloadOnChange
설정 파일을 추가하고 JSON Configuration파일을 수동으로 해석하여 원하는 대로 변경할 때 AddJsonFile 파라미터를 true로 설정합니다.
public class Startup
{
...
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
...
}
...
reloadOnChange
는 ASP에서만 지원됩니다.NET Core 1.1 이후
갱신하다appsettings.json
파일을 ASP에 저장합니다.실행 시 NET Core.
이 샘플을 가져가세요.appsettings.json
파일:
{
Config: {
IsConfig: false
}
}
업데이트할 코드입니다.IsConfig
true 속성:
Main()
{
AddOrUpdateAppSetting("Config:IsConfig", true);
}
public static void AddOrUpdateAppSetting<T>(string key, T value)
{
try
{
var filePath = Path.Combine(AppContext.BaseDirectory, "appSettings.json");
string json = File.ReadAllText(filePath);
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
var sectionPath = key.Split(":")[0];
if (!string.IsNullOrEmpty(sectionPath))
{
var keyPath = key.Split(":")[1];
jsonObj[sectionPath][keyPath] = value;
}
else
{
jsonObj[sectionPath] = value; // if no sectionpath just set the value
}
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(filePath, output);
}
catch (ConfigurationErrorsException)
{
Console.WriteLine("Error writing app settings");
}
}
Qamar Zamans 코드(감사합니다)를 가져와서 파라미터 편집에 사용할 수 있도록 수정했습니다.파라미터는 1층보다 더 깊습니다.
이게 어디선가 도서관 기능이 아니라는 사실에 놀라는 누군가가 도움이 되길 바랍니다.
public static class SettingsHelpers
{
public static void AddOrUpdateAppSetting<T>(string sectionPathKey, T value)
{
try
{
var filePath = Path.Combine(AppContext.BaseDirectory, "appsettings.json");
string json = File.ReadAllText(filePath);
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
SetValueRecursively(sectionPathKey, jsonObj, value);
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(filePath, output);
}
catch (Exception ex)
{
Console.WriteLine("Error writing app settings | {0}", ex.Message);
}
}
private static void SetValueRecursively<T>(string sectionPathKey, dynamic jsonObj, T value)
{
// split the string at the first ':' character
var remainingSections = sectionPathKey.Split(":", 2);
var currentSection = remainingSections[0];
if (remainingSections.Length > 1)
{
// continue with the procress, moving down the tree
var nextSection = remainingSections[1];
SetValueRecursively(nextSection, jsonObj[currentSection], value);
}
else
{
// we've got to the end of the tree, set the value
jsonObj[currentSection] = value;
}
}
public static void SetAppSettingValue(string key, string value, string appSettingsJsonFilePath = null)
{
if (appSettingsJsonFilePath == null)
{
appSettingsJsonFilePath = System.IO.Path.Combine(System.AppContext.BaseDirectory, "appsettings.json");
}
var json = System.IO.File.ReadAllText(appSettingsJsonFilePath);
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(json);
jsonObj[key] = value;
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
System.IO.File.WriteAllText(appSettingsJsonFilePath, output);
}
카마르 자만과 알렉스 호록의 코드에 따라 조금 바꿨습니다.
public static class SettingsHelpers
{
public static void AddOrUpdateAppSetting<T>(T value, IWebHostEnvironment webHostEnvironment)
{
try
{
var settingFiles = new List<string> { "appsettings.json", $"appsettings.{webHostEnvironment.EnvironmentName}.json" };
foreach (var item in settingFiles)
{
var filePath = Path.Combine(AppContext.BaseDirectory, item);
string json = File.ReadAllText(filePath);
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
SetValueRecursively(jsonObj, value);
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(filePath, output);
}
}
catch (Exception ex)
{
throw new Exception($"Error writing app settings | {ex.Message}", ex);
}
}
private static void SetValueRecursively<T>(dynamic jsonObj, T value)
{
var properties = value.GetType().GetProperties();
foreach (var property in properties)
{
var currentValue = property.GetValue(value);
if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string) || property.PropertyType == typeof(decimal))
{
if (currentValue == null) continue;
try
{
jsonObj[property.Name].Value = currentValue;
}
catch (RuntimeBinderException)
{
jsonObj[property.Name] = new JValue(currentValue);
}
continue;
}
try
{
if (jsonObj[property.Name] == null)
{
jsonObj[property.Name] = new JObject();
}
}
catch (RuntimeBinderException)
{
jsonObj[property.Name] = new JObject(new JProperty(property.Name));
}
SetValueRecursively(jsonObj[property.Name], currentValue);
}
}
}
대부분의 답변이 사용되었습니다.Newtonsoft.Json
를 참조하십시오.한 층 깊이의 설정을 갱신할 필요가 있는 경우는, 다음과 같이 할 수 있습니다.Newtonsoft.Json
및 사용System.Text.Json
(에 내장되어 있습니다.Net Core 3.0 이상)의 기능.심플한 실장은 다음과 같습니다.
public void UpdateAppSetting(string key, string value)
{
var configJson = File.ReadAllText("appsettings.json");
var config = JsonSerializer.Deserialize<Dictionary<string, object>>(configJson);
config[key] = value;
var updatedConfigJson = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText("appsettings.json", updatedConfigJson);
}
appsettings.json에 eureka 포트가 있으며 args(-p 5090)에서 동적으로 변경하려고 합니다.이렇게 하면 많은 서비스를 작성할 때 도커가 쉽게 포트를 변경할 수 있습니다.
"eureka": {
"client": {
"serviceUrl": "http://10.0.0.101:8761/eureka/",
"shouldRegisterWithEureka": true,
"shouldFetchRegistry": false
},
"instance": {
"port": 5000
}
}
public class Startup
{
public static string port = "5000";
public Startup(IConfiguration configuration)
{
configuration["eureka:instance:port"] = port;
Configuration = configuration;
}
public static void Main(string[] args)
{
int port = 5000;
if (args.Length>1)
{
if (int.TryParse(args[1], out port))
{
Startup.port = port.ToString();
}
}
}
나만의 설정 섹션과 강력한 유형의 개체를 사용하고 있습니다.난 항상 이 강한 타입의 오브젝트로 IOptions를 주입한다.런타임에 설정을 변경할 수 있습니다.물체의 범위를 매우 주의 깊게 다루십시오.새로운 설정값은 요구 범위 오브젝트에 의해 선택됩니다.컨스트럭터 주입을 사용하고 있습니다.
이에 대한 문서화는 매우 불명확합니다만,이게 운명인지 잘 모르겠어요.자세한 내용을 읽어보십시오.
실행 시 appsettings.json을 수정하기 위한 자세한 답변이 있습니다.
var filePath = Path.Combine(System.AppContext.BaseDirectory, "appSettings.json");
string jsonString = System.IO.File.ReadAllText(filePath);
//use https://json2csharp.com/ to create the c# classes from your json
Root root = JsonSerializer.Deserialize<Root>(jsonString);
var dbtoadd = new Databas()
{
Id = "myid",
Name = "mynewdb",
ConnectionString = ""
};
//add or change anything to this object like you do on any list
root.DatabaseSettings.Databases.Add(dbtoadd);
//serialize the new updated object to a string
string towrite = JsonSerializer.Serialize(root);
//overwrite the file and it wil contain the new data
System.IO.File.WriteAllText(filePath, towrite);
이 문제를 해결하는 방법은 메모리 캐시에 "덮어쓰기" 속성을 추가하는 것입니다.예를 들어 어플리케이션의 "appSettings.json" 파일에 데이터 쿼리 결과의 캐시 여부를 결정하는 "CacheEnabled" 설정이 있습니다.응용 프로그램/DB 테스트 중에 이 속성을 "false"로 설정하는 것이 바람직할 수 있습니다.
관리자는 관리자 메뉴를 통해 "CacheEnabled" 설정을 재정의할 수 있습니다.캐시가 네이블인지 아닌지를 결정하는 로직은 우선 오버라이드를 확인합니다.재정의 값을 찾을 수 없는 경우 "appSettings.json" 값을 사용합니다.
이 솔루션을 구현하기 위해 필요한 추가 인프라를 고려할 때 많은 사용자에게 이 솔루션은 적합하지 않을 수 있습니다.다만, 애플리케이션에는 이미 캐싱 서비스도 있고 관리자 메뉴도 있기 때문에, 실장은 꽤 간단했습니다.
프로젝트에서는 Active Directory Settings를 다음과 같이 사용하고 있습니다.
//...
public class Startup
{
public void ConfigureServices(IServicesCollection services)
{
//...
services.Configure<Ldap>(opts=> {
opts.Url = "example.com";
opts.UseSsl = true;
opts.Port = 111;
opts.BindDn = "CN=nn,OU=nn,OU=nn,DC=nn,DC=nn";
opts.BindCredentials = "nn";
opts.SearchBase = "DC=nn,DC=nn";
opts.SearchFilter = "(&(objectClass=User){0})";
opts.AdminCn = "CN=nn,OU=nn,OU=nn,DC=nn,DC=nn";
opts.SearchGroupBase = "OU=nn,DC=nn,DC=nn";
});
//...
}
}
따라서 appsettings.json을 사용하지 않습니다.
그런 다음 컨트롤러에서 다음 설정을 업데이트할 수 있습니다.
//...
[HttpPost("setActiveDirectorySettings")]
public ActionResult<IOptions<Ldap>> SetActiveDirectorySettings(ActiveDirectorySettings clientActiveDirectorySettings)
{
LdapOptions.Value.Url = clientActiveDirectorySettings.Url;
LdapOptions.Value.UseSsl = clientActiveDirectorySettings.UseSsl;
LdapOptions.Value.Port = clientActiveDirectorySettings.Port;
LdapOptions.Value.BindDn = clientActiveDirectorySettings.BindDn;
LdapOptions.Value.BindCredentials = clientActiveDirectorySettings.BindCredentials;
LdapOptions.Value.SearchBase = clientActiveDirectorySettings.SearchBase;
LdapOptions.Value.SearchFilter = clientActiveDirectorySettings.SearchFilter;
LdapOptions.Value.AdminCn = clientActiveDirectorySettings.AdminCn;
LdapOptions.Value.SearchGroupBase = clientActiveDirectorySettings.SearchGroupBase;
return Ok(LdapOptions.Value);
}
//...
나한텐 효과가 있는 것 같아
@Alper Ebicoglu 답변에 근거합니다.
취득:
// ===== || GET || GET appsettings.js property =====================================================================
[HttpGet]
[Route("GetNotificationDays")]
public async Task<IActionResult> GetNotificationDays()
{
var path = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json");
var json = await System.IO.File.ReadAllTextAsync(path);
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(json);
return StatusCode(200, new { daysBefore = (int)jsonObj.InvoicementNotificationSettings.DaysBefore});
}
유효기간:
(int)jsonObj.Invoice Notification Settings(청구서 통지 설정).일전 =
(int) = cast to int - depending on the property jsonObj = appsettings.js, InvoicementNotificationSettings = object in appsettings.js, DaysBefore = property in InvoicementNotificationSettings
업데이트: 앱 설정.js
// ===== || PUT || UPDATE appsettings.js property =====================================================================
[HttpPut]
[Route("SetNotificationDays")]
public async Task<IActionResult> SetNotificationDays(int notificationDays)
{
if (notificationDays != 0)
{
var path = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json");
var json = await System.IO.File.ReadAllTextAsync(path);
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(json);
jsonObj.InvoicementNotificationSettings.DaysBefore = notificationDays;
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
await System.IO.File.WriteAllTextAsync(path, output);
return await GetNotificationDays();
}
return StatusCode(409);
}
메모리에서 앱 설정을 읽는 경우: 예:int daysBefore = configuration.GetValue<int>("InvoicementNotificationSettings:DaysBefore");
Than In Startup.js - 업데이트 후 appsettings.js를 자동 새로고침합니다.
public class Startup
{
public static IConfiguration Configuration { get; set; }
// Constructor -----------------------------------------------------------------------------------------------------------------------------
public Startup(IConfiguration configuration, Microsoft.Extensions.Hosting.IHostEnvironment env)
{
Configuration = configuration;
// To autoreload appsettings.js after update -------------------------
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
어플리케이션 설정js
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=ItlCrmsDb;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
},
"InvoicementNotificationSettings": {
"DaysBefore": 4
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
언급URL : https://stackoverflow.com/questions/41653688/asp-net-core-appsettings-json-update-in-code
'programing' 카테고리의 다른 글
JavaScript에서 fetch() API 요청 및 응답 가로채기 (0) | 2023.04.05 |
---|---|
React의 인라인 CSS 스타일: 미디어 쿼리를 구현하는 방법 (0) | 2023.04.05 |
Json.NET: 중첩된 사전을 역직렬화하는 중 (0) | 2023.04.05 |
JSONP에서 .ajax()를 사용하는 기본적인 예? (0) | 2023.04.05 |
Windows Azure 동적 콘텐츠에서 gzip HTTP 압축을 활성화하는 방법 (0) | 2023.03.31 |