Skip to content

Not compatible with the Umbraco Content Delivery API #96

Open
@jessicaw-iology

Description

@jessicaw-iology

Which exact Umbraco version are you using? For example: 8.7.0 - don't just write v8 or v9

13.5.2

Bug summary

Your implementation of PropertyValueConverterBase doesn't also implement IDeliveryApiPropertyValueConverter. I had to deregister yours in a composer and register a custom one.
Therefore UmbNav out of the box is incompatible with the Umbraco Content Delivery API.

Specifics

The value converter I used after I deregistered yours (I could have just extended yours if we used Serilogger but we don't so this made more sense for us):

public class CustomUmbNavValueConverter : PropertyValueConverterBase, IDeliveryApiPropertyValueConverter
{
    private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
    private readonly IApiContentRouteBuilder _apiContentRouteBuilder;
    private readonly ILogger<CustomUmbNavValueConverter> _logger;
    private readonly IUmbNavMenuBuilderService _umbNavMenuBuilderService;

    public CustomUmbNavValueConverter(
        IPublishedSnapshotAccessor publishedSnapshotAccessor,
        IApiContentRouteBuilder apiContentRouteBuilder,
        ILogger<CustomUmbNavValueConverter> logger,
        IUmbNavMenuBuilderService umbNavMenuBuilderService)
    {
        _publishedSnapshotAccessor = publishedSnapshotAccessor;
        _apiContentRouteBuilder = apiContentRouteBuilder;
        _logger = logger;
        _umbNavMenuBuilderService = umbNavMenuBuilderService;
    }

    public override bool IsConverter(IPublishedPropertyType propertyType)
        => propertyType.EditorAlias.Equals("AaronSadler.UmbNav");

    public override Type GetPropertyValueType(IPublishedPropertyType propertyType)
        => typeof(IEnumerable<UmbNavItem>);

    public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType)
        => PropertyCacheLevel.Elements;

    public PropertyCacheLevel GetDeliveryApiPropertyCacheLevelForExpansion(IPublishedPropertyType propertyType)
        => PropertyCacheLevel.Snapshot;

    public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType)
        => typeof(IEnumerable<UmbNavItem>);

    public override object? ConvertIntermediateToObject(
        IPublishedElement owner,
        IPublishedPropertyType propertyType,
        PropertyCacheLevel referenceCacheLevel,
        object? inter,
        bool preview)
    {
        if (inter is null)
        {
            _logger.LogWarning("No intermediate value found for property {PropertyAlias}.", propertyType.Alias);
            return Enumerable.Empty<UmbNavItem>();
        }

        try
        {
            var items = JsonConvert.DeserializeObject<IEnumerable<UmbNavItem>>(inter.ToString() ?? string.Empty);
            if (items == null)
            {
                _logger.LogWarning("Failed to deserialize UmbNav items for property {PropertyAlias}.", propertyType.Alias);
                return Enumerable.Empty<UmbNavItem>();
            }

            // Build the menu using the UmbNavMenuBuilderService
            var configuration = propertyType.DataType.ConfigurationAs<UmbNavConfiguration>();
            if (configuration != null)
            {
                return _umbNavMenuBuilderService.BuildMenu(
                    items,
                    0,
                    configuration.RemoveNaviHideItems,
                    configuration.HideNoopener,
                    configuration.HideNoreferrer,
                    configuration.HideIncludeChildren,
                    configuration.AllowMenuItemDescriptions);
            }

            return items;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error converting UmbNav intermediate value for property {PropertyAlias}.", propertyType.Alias);
            return Enumerable.Empty<UmbNavItem>();
        }
    }

    public object? ConvertIntermediateToDeliveryApiObject(
        IPublishedElement owner,
        IPublishedPropertyType propertyType,
        PropertyCacheLevel referenceCacheLevel,
        object? inter,
        bool preview,
        bool expanding)
    {
        if (inter is null)
        {
            _logger.LogWarning("No intermediate value found for Delivery API conversion on property {PropertyAlias}.", propertyType.Alias);
            return null;
        }

        try
        {
            var items = JsonConvert.DeserializeObject<IEnumerable<UmbNavItem>>(inter.ToString() ?? string.Empty);
            if (items == null)
            {
                _logger.LogWarning("Failed to deserialize UmbNav items for Delivery API on property {PropertyAlias}.", propertyType.Alias);
                return null;
            }

            return items;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error converting UmbNav intermediate value for Delivery API on property {PropertyAlias}.", propertyType.Alias);
            return null;
        }
    }
}

Steps to reproduce

Set up the umbraco content delivery api
Create a Doc Type that uses navigation
Create content using that doc type
Try to return that content via the content delivery api

Expected result / actual result

I expected to receive usable content
What I got instead was an alternating experience between a 500 error and content stuck in a recursive loop (the json ignore attribute on content in class UmbNavItem is not recognized by the content delivery api because your class, UmbNavValueConverter only extends PropertyValueConverterBase but does not also implement IDeliveryApiPropertyValueConverter)
I do not know why sometimes I got the 500 error and sometimes I got the content stuck in a recursive loop but here's an example of one of the times I got content:

"headerNavigation":[{"udi":{"guid":"4edaad94-029e-43d3-ba74-75cffea28c7a","isRoot":false,"uriValue":"umb://document/4edaad94029e43d3ba7475cffea28c7a","entityType":"document"},"key":"4edaad94-029e-43d3-ba74-75cffea28c7a","name":"Home","title":"Home","description":null,"target":null,"noopener":null,"noreferrer":null,"anchor":null,"children":[],"parent":null,"content":{"id":1128,"name":"Home","urlSegment":"home","sortOrder":0,"level":1,"path":"-1,1128","templateId":null,"creatorId":1,"createDate":"2024-11-05T19:37:14.247Z","writerId":1,"updateDate":"2024-11-25T10:55:56.04Z","cultures":{"":{"culture":"","name":"Home","urlSegment":"home","date":"2024-11-05T19:37:14.247Z"}},"itemType":"Content","parent":null,"children":[{"id":1145,"name":"Test Page","urlSegment":"test-page","sortOrder":0,"level":2,"path":"-1,1128,1145","templateId":null,"creatorId":1,"createDate":"2024-11-25T10:39:20.907Z","writerId":1,"updateDate":"2024-11-25T10:39:20.907Z","cultures":{"":{"culture":"","name":"Test Page","urlSegment":"test-page","date":"2024-11-25T10:39:20.907Z"}},"itemType":"Content","parent":{"id":1128,"name":"Home","urlSegment":"home","sortOrder":0,"level":1,"path":"-1,1128","templateId":null,"creatorId":1,"createDate":"2024-11-05T19:37:14.247Z","writerId":1,"updateDate":"2024-11-25T10:55:56.04Z","cultures":{"":{"culture":"","name":"Home","urlSegment":"home","date":"2024-11-05T19:37:14.247Z"}},"itemType":"Content","parent":null,"children":[{"id":1145,"name":"Test Page","urlSegment":"test-page","sortOrder":0,"level":2,"path":"-1,1128,1145","templateId":null,"creatorId":1,"createDate":"2024-11-25T10:39:20.907Z","writerId":1,"updateDate":"2024-11-25T10:39:20.907Z","cultures":{"":{"culture":"","name":"Test Page","urlSegment":"test-page","date":"2024-11-25T10:39:20.907Z"}},"itemType":"Content","parent":{"id":1128,"name":"Home","urlSegment":"home","sortOrder":0,"level":1,"path":"-1,1128","templateId":null,"creatorId":1,"createDate":"2024-11-05T19:37:14.247Z","writerId":1,"updateDate":"2024-11-25T10:55:56.04Z","cultures":{"":{"culture":"","name":"Home","urlSegment":"home","date":"2024-11-05T19:37:14.247Z"}},"itemType":"Content","parent":null,"children":[{"id":1145,"name":"Test Page","urlSegment":"test-page","sortOrder":0,"level":2,"path":"-1,1128,1145","templateId":null,"creatorId":1,"createDate":"2024-11-25T10:39:20.907Z","writerId":1,"updateDate":"2024-11-25T10:39:20.907Z","cultures":{"":{"culture":"","name":"Test Page","urlSegment":"test-page","date":"2024-11-25T10:39:20.907Z"}},"itemType":"Content","parent":{"id":1128,"name":"Home","urlSegment":"home","sortOrder":0,"level":1,"path":"-1,1128","templateId":null,"creatorId":1,"createDate":"2024-11-05T19:37:14.247Z","writerId":1,"updateDate":"2024-11-25T10:55:56.04Z","cultures":{"":{"culture":"","name":"Home","urlSegment":"home","date":"2024-11-05T19:37:14.247Z"}},"itemType":"Content","parent":null,"children":[{"id":1145,"name":"Test Page","urlSegment":"test-page","sortOrder":0,"level":2,"path":"-1,1128,1145","templateId":null,"creatorId":1,"createDate":"2024-11-25T10:39:20.907Z","writerId":1,"updateDate":"2024-11-25T10:39:20.907Z","cultures":{"":{"culture":"","name":"Test Page","urlSegment":"test-page","date":"2024-11-25T10:39:20.907Z"}},"itemType":"Content","parent":{"id":1128,"name":"Home","urlSegment":"home","sortOrder":0,"level":1,"path":"-1,1128","templateId":null,"creatorId":1,"createDate":"2024-11-05T19:37:14.247Z","writerId":1,"updateDate":"2024-11-25T10:55:56.04Z","cultures":{"":{"culture":"","name":"Home","urlSegment":"home","date":"2024-11-05T19:37:14.247Z"}},"itemType":"Content","parent":null,"children":[{"id":1145,"name":"Test Page","urlSegment":"test-page","sortOrder":0,"level":2,"path":"-1,1128,1145","templateId":null,"creatorId":1,"createDate":"2024-11-25T10:39:20.907Z","writerId":1,"updateDate":"2024-11-25T10:39:20.907Z","cultures":{"":{"culture":"","name":"Test Page","urlSegment":"test-page","date":"2024-11-25T10:39:20.907Z"}},"itemType":"Content","parent":{"id":1128,"name":"Home","urlSegment":"home","sortOrder":0,"level":1,"path":"-1,1128","templateId":null,"creatorId":1,"createDate":"2024-11-05T19:37:14.247Z","writerId":1,"updateDate":"2024-11-25T10:55:56.04Z","cultures":{"":{"culture":"","name":"Home","urlSegment":"home","date":"2024-11-05T19:37:14.247Z"}},"itemType":"Content","parent":null,"children":[{"id":1145,"name":"Test Page","urlSegment":"test-page","sortOrder":0,"level":2,"path":"-1,1128,1145","templateId":null,"creatorId":1,"createDate":"2024-11-25T10:39:20.907Z","writerId":1,"updateDate":"2024-11-25T10:39:20.907Z","cultures":{"":{"culture":"","name":"Test Page","urlSegment":"test-page","date":"2024-11-25T10:39:20.907Z"}},"itemType":"Content","parent":{"id":1128,"name":"Home","urlSegment":"home","sortOrder":0,"level":1,"path":"-1,1128","templateId":null,"creatorId":1,"createDate":"2024-11-05T19:37:14.247Z","writerId":1,"updateDate":"2024-11-25T10:55:56.04Z","cultures":{"":{"culture":"","name":"Home","urlSegment":"home","date":"2024-11-05T19:37:14.247Z"}},"itemType":"Content","parent":null,"children":[{"id":1145,"name":"Test Page","urlSegment":"test-page","sortOrder":0,"level":2,"path":"-1,1128,1145","templateId":null,"creatorId":1,"createDate":"2024-11-25T10:39:20.907Z","writerId":1,"updateDate":"2024-11-25T10:39:20.907Z","cultures":{"":{"culture":"","name":"Test Page","urlSegment":"test-page","date":"2024-11-25T10:39:20.907Z"}},"itemType":"Content","parent":{"id":1128,"name":"Home","urlSegment":"home","sortOrder":0,"level":1,"path":"-1,1128","templateId":null,"creatorId":1,"createDate":"2024-11-05T19:37:14.247Z","writerId":1,"updateDate":"2024-11-25T10:55:56.04Z","cultures":{"":{"culture":"","name":"Home","urlSegment":"home","date":"2024-11-05T19:37:14.247Z"}},"itemType":"Content","parent":null,"children":[{"id":1145,"name":"Test Page","urlSegment":"test-page","sortOrder":0,"level":2,"path":"-1,1128,1145","templateId":null,"creatorId":1,"createDate":"2024-11-25T10:39:20.907Z","writerId":1,"updateDate":"2024-11-25T10:39:20.907Z","cultures":{"":{"culture":"","name":"Test Page","urlSegment":"test-page","date":"2024-11-25T10:39:20.907Z"}}

There's no end to this because it was stuck in a recursive loop

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions