umbraco / Umbraco-CMS

Umbraco is a free and open source .NET content management system helping you deliver delightful digital experiences.
https://umbraco.com
MIT License
4.42k stars 2.66k forks source link

Cached block list values when changing culture in Umbraco 11 #13568

Closed teeto closed 1 year ago

teeto commented 1 year ago

Which Umbraco version are you using? (Please write the exact version, example: 10.1.0)

11.0.0

Bug summary

I have an Umbraco authorized api controller that has to send menu options in various languages to another api. The menu options are stored using a Block list that have option items. Each option item has some properties some of the variant changing, as "Title". I have translated each option title and in umbraco it feels good. So in my code i iterate through the content cultures getting the block list for each available culture, but always get the same value. This is an example:


var content= this._umbracoHelper.Content(idContent);
foreach (var culture in content.Cultures.OrderByDescending(c=>c.Value.Culture.StartsWith("es")))
                {
                    string cultureLang = culture.Value.Culture;
                    var menuBL= content.Value<BlockListModel>("menu", culture: cultureLang);
                    if (menuBL!= null)
                    {
                        var test = menuBL
                            .Select(m => m.Content.Value<string>("title", culture: cultureLang))
                            .ToList();
                   //Here always get the titles in Spanish.

                    }
                }

If i change the code to get first the culture that startsWith("en") all the titles are gotten in English. So i think the property value converter for the BlockListModel is caching the result for that content. I have tried to get a new content item inside the foreach but i get the same results.

Specifics

No response

Steps to reproduce

Create a website with 2 cultures, ie spanish and english. English has a fallback to spanish, which is the default mandatory. Create an element type "Menu option" that has a "Title" of type string and select "vary by culture". Create a block list of element "Menu option". Create a content with a property of "Menu option" and fill it in both languages. Create an api controller with this code where idContent is the id of the content created.

Expected result / actual result

No response

kjac commented 1 year ago

Hi @teeto,

Try as I might I can't reproduce this issue. Here's my code, hopefully this will get you a bit further (for simplicity I have opted to create a normal API controller rather than an authorized one, but that should not make any difference):

using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Models.Blocks;
using Umbraco.Cms.Web.Common;
using Umbraco.Cms.Web.Common.Controllers;

namespace Issue13568;

public class Issue13568Controller : UmbracoApiController
{
    private readonly IUmbracoHelperAccessor _umbracoHelperAccessor;

    public Issue13568Controller(IUmbracoHelperAccessor umbracoHelperAccessor)
    {
        _umbracoHelperAccessor = umbracoHelperAccessor;
    }

    [HttpGet]
    public IActionResult MenuOptions(string culture)
    {
        if (_umbracoHelperAccessor.TryGetUmbracoHelper(out var umbracoHelper) == false)
        {
            return BadRequest("Could not get the Umbraco helper");
        }

        // grab the first content item at root level
        var content = umbracoHelper.ContentAtRoot().FirstOrDefault();
        if (content == null)
        {
            return NotFound($"Could not find any content at root level");
        }

        // grab the "menu" block list property of the content item in the  
        var blockList = content.Value<BlockListModel>("menu", culture: culture);
        if (blockList == null)
        {
            return NotFound($"Could not find any menu for culture: {culture}");
        }

        var menuItems = blockList.Select(item => item.Content.Value<string>("title", culture: culture)).ToArray();
        return Ok(menuItems);
    }
}

My backoffice looks like this:

image

...and in Danish:

image

When invoking the API at /umbraco/api/issue13568/menuoptions?culture=[culture] I get:

image

...and in Danish:

image

ℹ️ On a side note, you should consider is to disable the culture variance on the element type. It doesn't have to vary bu culture because it is used as an element type within another property (the block list) that does vary by culture. In other words, the individual elements have no culture variance no matter what - only the outer container does (the block list in this case).

I'm going to close this issue now. If you still need help with this, I would urge you to reach out at the forum (https://our.umbraco.com/forum/).

teeto commented 1 year ago

Thanks for your help, @kjac your example works and it is how i was using it, passing the culture as a parameter. But what i really need is not pass the culture as parameter and get all the available cultures in the same call to the api. If you see my example i iterate all the cultures available for the content and only the first iteration has the culture ok the others return the first culture because i guess it gets cached. About the culture variance, i know right now the entire blocklist varies by culture, but Umbraco is working on block level variance, which would be super dope, as right know the admins need to copy the entire blocklist and translate each item, and lots of non translatable content (like images) needs to be copied. So this way, i want to have it ready when that update comes.