As some of you are now aware, adding custom style formats to Umbraco 9+ is somewhat cumbersome as rather than accepting nicely formatted json it is expecting a string which requires the double quotes to be escaped and therfore makes it difficult to maintain.
I have come up with a solution to maintain it automatically. I keep a copy of the style_formats section in it's own .json file in the application root folder.
In the startup.cs I check to see if this file exists and if it does, I load the content, minify the json and then write the minified string back to the appsetting.json. Writing the minified json using the serializer automatically escapes the double quotes in the value.
Startup.cs changes
public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config)
{
_env = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment));
_config = config ?? throw new ArgumentNullException(nameof(config));
UpdateStyleFormats();
}
private void UpdateStyleFormats()
{
//does the json file exist?
//if yes, minify it, escape the " and set the value in appsettings.json
if (File.Exists("RTE_style_formats.json"))
{
object obj = JsonConvert.DeserializeObject(File.ReadAllText("RTE_style_formats.json"));
var jsonString = JsonConvert.SerializeObject(obj, Formatting.None);
var settingsUpdater = new AppSettingsUpdater();
settingsUpdater.UpdateAppSetting("Umbraco:CMS:RichTextEditor:CustomConfig:style_formats", jsonString);
}
}
AppSettingsUpdater Class
using System.Text;
using System.Text.Json;
namespace MediaWiz.Core.Extensions
{
public class AppSettingsUpdater
{
private const string EmptyJson = "{}";
/// <summary>
/// This method will update the value for a given key in the json file
/// </summary>
/// <param name="file">Name of the json file to edit</param>
/// <param name="key">Name of the json key</param>
/// <param name="value">New value for the setting</param>
/// <exception cref="ArgumentException"></exception>
public void UpdateAppSetting(string key, object value)
{
if (key == null)
{
throw new ArgumentException("Json property key cannot be null", nameof(key));
}
string settinsgFileName = "appsettings.json";
var config = File.ReadAllText(settinsgFileName);
var updatedConfigDict = UpdateJson(key, value, config);
// After receiving the dictionary with updated key value pair, we serialize it back into json.
var updatedJson = JsonSerializer.Serialize(updatedConfigDict, new JsonSerializerOptions { WriteIndented = true });
// serializing the json escaped the + signs!! so let's put them back
File.WriteAllText(settinsgFileName, updatedJson.Replace(@"\u002B","+"),Encoding.UTF8);
}
/// <summary>
/// This method will recursively read json segments separated by semicolon (firstObject:nestedObject:someProperty)
/// until it reaches the desired property that needs to be updated,
/// it will update the property and return json document represented by dictonary of dictionaries of dictionaries and so on.
/// This dictionary structure can be easily serialized back into json
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="jsonSegment"></param>
/// <returns></returns>
private Dictionary<string, object> UpdateJson(string key, object value, string jsonSegment)
{
const char keySeparator = ':';
var config = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonSegment);
var keyParts = key.Split(keySeparator);
var isKeyNested = keyParts.Length > 1;
if (isKeyNested)
{
var firstKeyPart = keyParts[0];
var remainingKey = string.Join(keySeparator, keyParts.Skip(1));
// If the key does not exist already, we will create a new key and append it to the json
var newJsonSegment = config.ContainsKey(firstKeyPart) && config[firstKeyPart] != null
? config[firstKeyPart].ToString()
: EmptyJson;
config[firstKeyPart] = UpdateJson(remainingKey, value, newJsonSegment);
}
else
{
config[key] = value;
}
return config;
}
}
}
In this article I will explain how to configure the TinyMCE rich text editor in Umbraco v14
This is my dive into the new Umbraco 14 backoffice to create a Member EntityAction in order to send an email to the selected member.
Previously known as Tree Actions, Entity Actions is a feature that provides a generic place for secondary or additional functionality for an entity type. An entity type can be a media, document and so on.
In this blog post I explain how to implement an email validation flow for Member registration.