Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not compatible with the Umbraco Content Delivery API #96

Open
jessicaw-iology opened this issue Nov 26, 2024 · 3 comments
Open

Not compatible with the Umbraco Content Delivery API #96

jessicaw-iology opened this issue Nov 26, 2024 · 3 comments

Comments

@jessicaw-iology
Copy link

jessicaw-iology commented Nov 26, 2024

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

@AaronSadlerUK
Copy link
Owner

Hi @jessicaw-iology

I have not used the delivery API yet.

Did the code you provided work?

Would you be able to provide a PR and I'll test when I get a chance, I'm currently in the process of moving house so I'm not sure when that will be.

@jessicaw-iology
Copy link
Author

jessicaw-iology commented Nov 26, 2024 via email

@jessicaw-iology
Copy link
Author

jessicaw-iology commented Jan 11, 2025

@AaronSadlerUK Apologies that it's taken me so long to get around to working on this. I just started working on this today and I am bumping into numerous issues. I'm not sure how to handle the fact that the Content Delivery API only exists on v12 and up. Do you have any guidance or would you ever want to get on a video chat to work this out together?
image

Update: I'm going to try some preprocessor directives to target .NET8 for different code and see what happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants