How to update DraftBlockFieldData?

I am trying to update a Block’s field value from an API Controller. I have succeded to update the production data (Blocks.BlockFieldData-table) but the changes are not visible in Backoffice. I understand Backoffice is working with Blocks.DraftBlockFieldData-table and data is copied to Blocks.BlockFieldData-table at publish.

Q: How do I update the DraftBlockFieldData?

According to this answer, the equivalent problem for DraftPageFieldData is soloved with implementing IReadOnly on the MultifieldItem object. I did try this, but without success. Not sure if my implementation is enough.

Function:

protected override void ProcessBlock(BlockStyle item)
{
    var block = _blockService.Get(item.Id).MakeWritableClone();
    var styleList = new List<MultiFieldItem>();
    var multiFieldItem = new MultiFieldItem();

    multiFieldItem.Fields.AddOrUpdateValue(CustomBlockFieldNameConstants.StartColumnX, "*", item.XStart);
    multiFieldItem.Fields.AddOrUpdateValue(CustomBlockFieldNameConstants.EndColumnX, "*", item.XEnd);

    styleList.Add(multiFieldItem);
    block.Fields.AddOrUpdateValue(CustomBlockFieldNameConstants.StyleXLarge, "*", styleList);
    
    using (Solution.Instance.SystemToken.Use())
    {
        _blockService.Update(block);
    }
}

Object equivalent to CustomBlockFieldNameConstants.StyleXLarge:

public class BlockStyle: IAutoMapperConfiguration, IViewModel, IReadOnly
{
    public string StartColumnX { get; set; }
    public string EndColumnX { get; set; }

    public bool IsReadOnly => false;

    public void MakeReadOnly()
    { }

    public object MakeWritableClone()
    {
        return null;
    }

    [UsedImplicitly]
    void IAutoMapperConfiguration.Configure(IMapperConfigurationExpression cfg)
    {
        cfg.CreateMap<MultiFieldItem, BlockStyle>()
            .ForMember(x => x.StartColumnX,
                m => m.MapFrom(c => c.Fields.GetValue<string>(CustomBlockFieldNameConstants.StartColumnX)))
            .ForMember(x => x.EndColumnX,
                m => m.MapFrom(c => c.Fields.GetValue<string>(CustomBlockFieldNameConstants.EndColumnX)));
    }
}

Litium version: 7.3.1-patch-1911150957

To update draft data, you should use DraftBlockService instead, to get a DraftBlock and again use that service to update the DraftBlock.

If you are uncertain about the IReadOnly implementation, I would suggest to try updating the built-in field type, short text for example, to make sure you use the right service to update draft data. Then when it works, try with your custom field.