Skip to content

Instantly share code, notes, and snippets.

@DanDiplo
Last active July 26, 2024 05:58
Show Gist options
  • Save DanDiplo/1e8e4dcd93bcc29115ef16c62e3d090a to your computer and use it in GitHub Desktop.
Save DanDiplo/1e8e4dcd93bcc29115ef16c62e3d090a to your computer and use it in GitHub Desktop.
Create Blocklist JSON programmatically in Umbraco
/// <summary>
/// Helper service for creating JSON necessary for creating block list items programatically using Umbraco <see cref="ContentService"/>
/// </summary>
/// <remarks>
/// Based of this: https://github.com/umbraco/UmbracoDocs/blob/e64ec0e5b28b4e5a37b7865691621e45dd82701f/Getting-Started/Backoffice/Property-Editors/Built-in-Property-Editors/Block-List-Editor/index.md
/// It's intended for simple content
/// </remarks>
public class BlockListCreatorService
{
/// <summary>
/// Creates the Block List JSON from the passed in collection of items. Each item needs to have the <see cref="JsonPropertyAttribute"/> that corresponds to the property alias of the element doc type it is based on
/// </summary>
/// <typeparam name="T">The type of your item</typeparam>
/// <param name="items">The collection of items to create</param>
/// <param name="contentTypeKey">The GUID for the element type (tip: you can look this up in God Mode!)</param>
/// <param name="settingsData">Optional settings data - defaults to empty settings</param>
/// <returns>JSON suitable for Block List</returns>
/// <exception cref="ArgumentNullException">Raised if items are null</exception>
public string GetBlockListJsonFor<T>(IEnumerable<T> items, Guid contentTypeKey, List<Dictionary<string, string>> settingsData = null) where T : class
{
if (items == null)
{
throw new ArgumentNullException(nameof(items));
}
Blocklist blocklistNew = new Blocklist(); //initialize our new empty model to mimic proper JSON structure
var contentList = new List<Dictionary<string, string>>(); //initialize empty list where we will add our content items
var dictionaryUdi = new List<Dictionary<string, string>>(); // this contains content UDIs
foreach (var item in items)
{
var udi = new GuidUdi("element", Guid.NewGuid()).ToString();
PropertyInfo[] props = item.GetType().GetProperties();
var propertyValues = new Dictionary<string, string>()
{
{ "contentTypeKey", contentTypeKey.ToString() },
{ "udi", udi.ToString() }
};
foreach (PropertyInfo prop in props)
{
object[] attrs = prop.GetCustomAttributes(true);
foreach (object attr in attrs)
{
if (attr is JsonPropertyAttribute attribute)
{
propertyValues.Add(attribute.PropertyName, prop.GetValue(item)?.ToString() ?? string.Empty);
}
}
}
contentList.Add(propertyValues);
dictionaryUdi.Add(new Dictionary<string, string> { { "contentUdi", udi } });
}
blocklistNew.Layout = new BlockListUdi(dictionaryUdi);
blocklistNew.ContentData = contentList; //contentData is a list of our object
blocklistNew.SettingsData = settingsData ?? new List<Dictionary<string, string>>();
return JsonConvert.SerializeObject(blocklistNew);
}
internal class Blocklist //this class is to mock the correct JSON structure when the object is serialized
{
[JsonProperty("layout")]
public BlockListUdi Layout { get; set; }
[JsonProperty("contentData")]
public List<Dictionary<string, string>> ContentData { get; set; }
[JsonProperty("settingsData")]
public List<Dictionary<string, string>> SettingsData { get; set; }
}
internal class BlockListUdi //this is a subclass which corresponds to the "Umbraco.BlockList" section in JSON
{
[JsonProperty("Umbraco.BlockList")] //we mock the Umbraco.BlockList name with JsonPropertyAttribute to match the requested JSON structure
public List<Dictionary<string, string>> ContentUdi { get; set; }
public BlockListUdi(List<Dictionary<string, string>> items)
{
this.ContentUdi = items;
}
}
}
// Below is an example class that represents a Block List item. It's for a block list of Location items.
// The [JsonProperty] for each item should correspond to your property alias of the corresponding element you are creating.
public class Location
{
[JsonProperty("displayName")]
public string Name { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("address1")]
public string Address1 { get; set; }
[JsonProperty("address2")]
public string Address2 { get; set; }
[JsonProperty("city")]
public string City { get; set; }
[JsonProperty("postCode")]
public string PostCode { get; set; }
}
// You would then create a List of Locations ie. List<Location> locations = new List<Location>() and populate the data. You would then get your JSON back as:
var json = blockListCreatorService.GetBlockListJsonFor(locations, new Guid("07cc06f6-8f16-4a7f-90b9-b04c59bcdf97"));
// The GUID corresponds to the GUID of your block list element in Umbraco. Tip: You can use my God Mode package to find out the Guid easily - https://www.nuget.org/packages/Diplo.GodMode/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment