Save Changes of IConfigurationRoot sections to its *.json file in .net Core 2.2

天大地大妈咪最大 提交于 2020-05-14 10:01:47

问题


i was digging to find out the solution but didn't manage to find it, i bet that someone has encountered this problem, so what is the problem?.

For test i have created simple console application (solution will be used in asp.net core web api).

I have TestSetting.json configuration file with 'Copy Always' setuped.

{
  "setting1" : "value1" 
}

And Simple code

IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();

IConfigurationRoot configuration = configurationBuilder.AddJsonFile("TestSettings.json",false, reloadOnChange: true).Build();

Console.WriteLine(configuration.GetSection("setting1").Value); // Output: value1
//Change configuration manually in file while console is waiting
Console.ReadKey();

//Changed manually in file Value appears
Console.WriteLine(configuration.GetSection("setting1").Value); // Output: Whatever you have setuped
Console.ReadKey();

configuration.GetSection("setting1").Value = "changed from code";
//Changed in code value appear
Console.WriteLine(configuration.GetSection("setting1").Value); // Output: changed from code

I have 2 requirements, i want to make it possible to change value in json configuration file manually while application is running and application will see updated value during next get of setting Section and it is working.

Second requirement is that, i want to preserve some information, to be accurate a last execution time of task which should be executed once per setuped period ex. once a day, so some loop check last execution time value and determine if operation has to be executed. Someone would ask that what i have will work, but i need also to cover scenario when operation has been executed and application has been restarted (server error, user restart etc), and i need to save this information in a way which will allow me to read it after app startup.

Reading code sample we can see that after changing setting1 in code we see that this section has been changed while trying to output it to console.

configuration.GetSection("setting1").Value = "changed from code";
//Changed in code value appear
Console.WriteLine(configuration.GetSection("setting1").Value); // Output: changed from code

Here comes the question :). Is it possible that this settings section change will also affect actual value in json file? I don't want to manually change this file by some stream writers or whatever.

Actual result is that: after changing value in code, the new value is getable in runtime but when you will go to debug binaries you will se that value1 in TestSettings.json file hasnt been changed.


回答1:


It is not possible via the Microsoft.Extensions.Configuration package to save changes made to the configuration to disk. There is an issue about it on github here where they chose not to do it. It is possible to do, just not via the IConfiguration interface. https://github.com/aspnet/Configuration/issues/385




回答2:


Thank you "Matt Luccas Phaure Jensen" For this, information, i have't found any solution for this there. If any one wants to use IOptions here is an answer how to do it How to update values into appsetting.json?

I want to do it in the way i started, so i looked to the implementation of Microsoft.Extensions.Configuration.Json and i have prepared simple solution to allow writing and use base implementation. It probably has many limitations but it will work in simple scenarios.

Two implementations from above dll have to be extended. So lets do it.

Implementation of WritableJsonConfigurationProvider with example save code of desired section.

Change values in JSON file (writing files)

public class WritableJsonConfigurationProvider : JsonConfigurationProvider
{
    public WritableJsonConfigurationProvider(JsonConfigurationSource source) : base(source)
    {
    }

    public override void Set(string key, string value)
    {
        base.Set(key,value);

        //Get Whole json file and change only passed key with passed value. It requires modification if you need to support change multi level json structure
        var fileFullPath = base.Source.FileProvider.GetFileInfo(base.Source.Path).PhysicalPath;
        string json = File.ReadAllText(fileFullPath);
        dynamic jsonObj = JsonConvert.DeserializeObject(json);
        jsonObj[key] = value;
        string output = JsonConvert.SerializeObject(jsonObj, Formatting.Indented);
        File.WriteAllText(fileFullPath, output);
    }
}

And implementation of WritableJsonConfigurationSource which is a extention of JsonConfigurationSource

public class WritableJsonConfigurationSource : JsonConfigurationSource
{
    public override IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        this.EnsureDefaults(builder);
        return (IConfigurationProvider)new WritableJsonConfigurationProvider(this);
    }
}

and that's it, lets use it

IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
IConfigurationRoot configuration = configurationBuilder.Add<WritableJsonConfigurationSource>(
    (Action<WritableJsonConfigurationSource>)(s =>
                                                     {
                                                         s.FileProvider = null;
                                                         s.Path = "TestSettings.json";
                                                         s.Optional = false;
                                                         s.ReloadOnChange = true;
                                                         s.ResolveFileProvider();
                                                     })).Build();

Console.WriteLine(configuration.GetSection("setting1").Value); // Output: value1
Console.ReadKey();

configuration.GetSection("setting1").Value = "changed from codeeee";
Console.WriteLine(configuration.GetSection("setting1").Value); // Output: changed from codeeee

Console.ReadKey();

Value is being changed in memory as well in file. Bingo :).

The code could have problems, can be refactored etc, this is only sample quick solution.



来源:https://stackoverflow.com/questions/57978535/save-changes-of-iconfigurationroot-sections-to-its-json-file-in-net-core-2-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!