Work with Blocklist Properties using the Umbraco Content Service - v12
From an UmbracoAuthorizedApiController I would like to use an Umbraco service Api (ContentService) to manipulate property data contained in BlockList components. So far, while non-BlockList properties are available using the ContentService, all Blocklist properties are not. This snippet will write all non-BlockList properties but omits the BlockList ones
var contentType = _contentTypeService.Get("blogPost");
var contentOfType = _contentService.GetPagedOfType(contentType.Id, 0, int.MaxValue, out long totalArchive, null);
foreach (var content in contentOfType)
{
foreach(var property in content.Properties)
Debug.WriteLine($"Content Property Alias: {property.Alias}");
...
I've found plenty of docs covering how to create a BlockList and already use custom BlockList views with
Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockListItem>
but I'm stuck on this one.
Feel like I'm missing something obvious...tips or pointers much appreciated!
The solution I ended up with was not at all what I had originally envisioned. While I do use the ContentService to get the content, the actual updates are done using more generic methods and serializing/deserializing Json. For what it's worth, here is what is working for me to get BlockList content, do some simple find and replace, then update and save the BlockList content. I've added a way to handle both single content and nested content (eg, Lists of BlockList content). I'm sure that can be refactored to be cleaner.
I am more than open to a better way to do this!
private readonly IContentService _contentService;
...
public FindAndReplaceApiController(IContentService contentService)
{
_contentService = contentService;
}
...
// your content id
var content = _contentService.GetById(0000);
// the property alias for the BlockList content from the Document Type
var rawJsonBlock = content.GetValue("content").ToString();
// the entire BlockList Json block
BlockValue blockValue = JsonConvert.DeserializeObject<BlockValue>(rawJsonBlock);
// Note: using System.Text.Json throws exceptions when deserializing OR returns an empty object, I don't know why
foreach (var column in blockValue.ContentData)
{
foreach (var columnProperty in column.RawPropertyValues)
{
// the Value is a text string, unless it's a BlockList, in which case it's a Json object
var block = columnProperty.Value;
if (block == null) continue;
// check if the Value is a BlockList, for repeating BlockList items
if (block.ToString().Contains("Umbraco.BlockList", StringComparison.InvariantCultureIgnoreCase))
{
// if it is, we can deserialize it to a BlockValue since we have nested content
var innerBlock = JsonConvert.DeserializeObject<BlockValue>(columnProperty.Value.ToString());
foreach (var innerBlockValue in innerBlock.ContentData)
{
foreach(var blockProperty in innerBlockValue.RawPropertyValues)
{
Debug.WriteLine($"Inner Block Value: {blockProperty.Value}");
if (blockProperty.Value.ToString().Contains("some old value", StringComparison.InvariantCultureIgnoreCase))
{
// replace the old with the new!
innerBlockValue.RawPropertyValues[blockProperty.Key] = blockProperty.Value.ToString()
.Replace("some old value"
, "some new value"
, StringComparison.InvariantCultureIgnoreCase);
// serialize the updated value to Json for storage
column.RawPropertyValues[columnProperty.Key] = JsonConvert.SerializeObject(innerBlock);
content.Properties["content"].SetValue(JsonConvert.SerializeObject(blockValue));
}
}
}
}
else
{
// in this case, the block content is not nested
Debug.WriteLine($"Top Level Block Value: {block}");
if(block.ToString().Contains("some old value", StringComparison.InvariantCultureIgnoreCase))
{
// update the block object directly
block = block.ToString().Replace("some old value", "some new value", StringComparison.InvariantCultureIgnoreCase);
// serialize the updated value to Json for storage
column.RawPropertyValues[columnProperty.Key] = block;
content.Properties["content"].SetValue(JsonConvert.SerializeObject(blockValue));
}
}
}
}
if (content.IsDirty())
{
// save the updates, if any
_contentService.SaveAndPublish(content);
}
...
Work with Blocklist Properties using the Umbraco Content Service - v12
From an
UmbracoAuthorizedApiController
I would like to use an Umbraco service Api (ContentService
) to manipulate property data contained in BlockList components. So far, while non-BlockList properties are available using the ContentService, all Blocklist properties are not. This snippet will write all non-BlockList properties but omits the BlockList onesI've found plenty of docs covering how to create a BlockList and already use custom BlockList views with
Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockListItem>
but I'm stuck on this one.Feel like I'm missing something obvious...tips or pointers much appreciated!
The solution I ended up with was not at all what I had originally envisioned. While I do use the
ContentService
to get the content, the actual updates are done using more generic methods and serializing/deserializing Json. For what it's worth, here is what is working for me to getBlockList
content, do some simple find and replace, then update and save theBlockList
content. I've added a way to handle both single content and nested content (eg, Lists of BlockList content). I'm sure that can be refactored to be cleaner.I am more than open to a better way to do this!
is working on a reply...