ASP.NET Core appsettings.json在代码中更新

时间:2017-01-14 18:49:30

标签: c# json asp.net-core .net-core appsettings

我目前正在使用asp.net核心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"));

有没有办法从Controller中更改和保存MaxPvPowerMaxWindPower

我尝试使用

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");
 }

但它没有做任何事。

11 个答案:

答案 0 :(得分:9)

以下是Microsoft关于.Net Core Apps中配置设置的相关文章:

Asp.Net Core Configuration

该页面还有sample code,也可能会有所帮助。

<强>更新

我认为In-memory provider and binding to a POCO class可能有用,但不能像预期的那样工作。

下一个选项可以是在添加配置文件时将AddJsonFilereloadOnChange参数设置为true 手动解析JSON配置文件并按预期进行更改。

    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及更高版本中受支持。

答案 1 :(得分:7)

基本上你可以像IConfiguration一样设置值:

IConfiguration configuration = ...
// ...
configuration["key"] = "value";

问题在于JsonConfigurationProvider未实现将配置保存到文件中。正如您在source中看到的那样,它不会覆盖ConfigurationProvider的Set方法。 (见source

您可以创建自己的提供商并在那里实施保存。 Here (Basic sample of Entity Framework custom provider)是一个如何做到的例子。

答案 2 :(得分:6)

我接受了Qamar Zamans代码(谢谢),并对其进行了修改,以允许编辑参数more:than:one:layer:deep。

希望它可以帮助某人,这很奇怪,这不是某个地方的图书馆功能。

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; 
        }
    }

答案 3 :(得分:2)

    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);
    }

答案 4 :(得分:1)

在asp.net核心运行时中更新appsettings.json文件

示例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");
            }
        }

答案 5 :(得分:1)

根据Qamar Zaman和Alex Horlock的代码,我对其进行了一些更改。

 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);
        }


    }
}

答案 6 :(得分:0)

假设appsettings.json具有一个eureka端口,并希望在args中动态更改它(-p 5090)。这样,可以在创建许多服务时轻松更改docker的端口。

  "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();
            }

        }
     }

答案 7 :(得分:0)

我正在使用自己的配置部分和自己的强类型对象。我总是用这个强类型的对象注入IOptions。而且我能够在运行时更改配置。注意对象的范围。新的配置值由请求范围对象获取。我正在使用构造函数注入。

有关此文档,目前尚不清楚。.我不确定是否要这样做。阅读此in-depth discussion

答案 8 :(得分:0)

我解决这个问题的方法是添加一个存储在内存缓存中的“覆盖”属性。例如,我的应用程序在“appSettings.json”文件中有一个“CacheEnabled”设置,用于确定是否缓存数据查询结果。在应用程序/数据库测试期间,有时需要将此属性设置为“false”。

通过管理员菜单,管理员可以覆盖“CacheEnabled”设置。决定是否启用缓存的逻辑首先检查覆盖。如果找不到覆盖值,则使用“appSettings.json”值。

考虑到实施它所需的额外基础设施,这对很多人来说可能不是一个好的解决方案。但是,我的应用程序已经有缓存服务和管理员菜单,因此实现起来非常容易。

答案 9 :(得分:0)

我看到大多数答案都使用 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);
}

答案 10 :(得分:-1)

有一个简单的答案可以在运行时修改appsettings.json。

Json File structure

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