We have a process during a MSI based installation were we are taking in appsetting values via paramaters and/or an installer form.
I am trying to dynamically update the json properties of the applications appsettings file but am not sure how to search the json using the key format of "node:child:child" at any depth. All options are on the table, we are able to serialize the object and use reflection, a linq solution or anything else. This will be very similar to how something like the json replacement works in an Azure build or release pipeline.
Currently have this which is very close except I cannt extract the json string from the IConfiguration in order to write it back to the file.....
public static ActionResult ModifySettings(Session session)
{
session.Log("Begin ModifySettings");
try
{
string[] customData = session.CustomActionData.Keys.ToArray();
string[] customValues = session.CustomActionData.Values.ToArray();
///Product.wxs -> BinDir=[BinDir]
var installDirectory = customValues[1];
string file = Path.Combine(installDirectory, "appsettings.json");
session.Log(string.Format($"Updating file: {file}.{Environment.NewLine}."));
if (File.Exists(file))
{
session.Log($"Updating Settings file: {file}.{Environment.NewLine}");
var configFile = new ConfigurationBuilder().AddJsonFile(file).Build();
for (int i = 3; i < customData.Count(); i++)
{
if (!ReplaceSetting(configFile, customData[i], customValues[i], session))
throw new ArgumentException($"Error during settings replacement of {customData[i]} with {customValues[i]}",customData[i]);
}
var settingsAsString = configFile.ToString();//DOES NOT WORK
session.Log($"Updated settings{Environment.NewLine}{settingsAsString}{Environment.NewLine}");
File.WriteAllText(file, settingsAsString);
}
else
{
session.Log($"Failed to update file {file}.{Environment.NewLine}Exiting.");
return ActionResult.Failure;
}
return ActionResult.Success;
}catch(Exception ex)
{
session.Log(ex.Message);
return ActionResult.Failure;
}
}
private static bool ReplaceSetting(IConfigurationRoot settings, string settingName, string settingValue, Session session)
{
try
{
session.Log(string.Format($"Updating Setting: {settingName}{Environment.NewLine}Value: {settingValue}{Environment.NewLine}"));
settings[settingName] = settingValue; //<- THIS IS THE PART I NEED TO MIMIC WHEN SETTINGNAME FORMAT IS SOMETHING:SOMETHINGELSE:PROPERTY!!!
}
catch(Exception ex)
{
session.Log(ex.Message);
return false;
}
return true;
}
EDIT Working solution using JObject
public static ActionResult ModifySettings(Session session)
{
session.Log("Begin ModifySettings");
try
{
string[] customData = session.CustomActionData.Keys.ToArray();
string[] customValues = session.CustomActionData.Values.ToArray();
///Product.wxs -> BinDir=[BinDir]
var installDirectory = customValues[1];
string file = Path.Combine(installDirectory, "appsettings.json");
session.Log(string.Format($"Updating file: {file}.{Environment.NewLine}."));
if (File.Exists(file))
{
session.Log($"Updating Settings file: {file}.{Environment.NewLine}");
var configFile = new ConfigurationBuilder().AddJsonFile(file).Build();
JObject settings = JObject.Parse(File.ReadAllText(file));
for (int i = 3; i < customData.Count(); i++)
{
if (!ReplaceSetting(ref settings, customData[i], customValues[i], session))
throw new ArgumentException($"Error during settings replacement of {customData[i]} with {customValues[i]}",customData[i]);
}
session.Log($"Updated settings{Environment.NewLine}{settings.ToString()}{Environment.NewLine}");
File.WriteAllText(file, settings.ToString());
}
else
{
session.Log($"Failed to update file {file}.{Environment.NewLine}Exiting.");
return ActionResult.Failure;
}
return ActionResult.Success;
}catch(Exception ex)
{
session.Log(ex.Message);
return ActionResult.Failure;
}
}
private static bool ReplaceSetting(ref JObject settingFile, string settingName, string settingValue, Session session)
{
try
{
session.Log(string.Format($"Updating Setting: {settingName}{Environment.NewLine}Value: {settingValue}{Environment.NewLine}"));
var token = settingFile.SelectToken(settingName);
(token.Parent as JProperty).Value = settingValue;
}
catch (Exception ex)
{
session.Log(ex.Message);
return false;
}
return true;
}