Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jan A 63 posts 268 karma points
    Feb 07, 2023 @ 14:01
    Jan A
    0

    GetValue on property from Content returns null from UmbracoPageController / IVirtualController

    I have a route setup to intercept an url pattern and call a UmbracoPageController (also IVirtualController) From there I identify a published node, get some data from a database and generate the template. Works fine.

    But that template/page use a layout, from where I get a settings node and get the property for my top menu.

    When I debug the node Id is 1074 And if I call this umbracoHelper.Content(1074).GetProperty(PropertyAlias.HeaderMenu).GetValue() I will get null returned

    From a normal page I get the menu.

    If I only call umbracoHelper.Content(1074) I will get the settings node, and GetProperty return the same

    umbracoHelper.Content(1074).GetProperty(PropertyAlias.HeaderMenu)
    "headerMenu" ("AaronSadler.UmbNav")
        Alias: "headerMenu"
        PropertyType: "headerMenu" ("AaronSadler.UmbNav")
        ReferenceCacheLevel: Element
    

    But when I call GetValue it will not work. I have a hard time figuring out why?

  • Jan A 63 posts 268 karma points
    Feb 14, 2023 @ 08:14
    Jan A
    0

    Since I don't get any answers I try to provide some more info and code.

    Basically it is a matter that the AssignedContentItem is not set, but I can't figure out a way around this or to set it.

    Here's the code

    I hijack the route by this code

    u.EndpointRouteBuilder.MapControllerRoute(
    "Category view",
    "/category/{shortname}",
    new { Controller = "Category", Action = "Category" });
    

    Then I have a CategoryController

    public class CategoryController : UmbracoPageController, IVirtualPageController
    {
       public IPublishedContent? FindContent(ActionExecutingContext actionExecutingContext)
        {
            if (_umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
            {
                var categoryRoot = umbracoContext.Content.GetById(1083); // todo: hämta listnamn
                if (categoryRoot != null)
                {
                    return categoryRoot;
                }
            }
    
            return null;
        } 
    
        public IActionResult Category(string shortname)
        {
            // retrieve data from db etc
            var viewmodel = new MyViewModel();
            return View(viewmodel);
        }
    }
    

    The view then inherits an master template that have the following line

     @(await Component.InvokeAsync("TopNavigation", new { selected = Model.Selected }))
    

    The TopNavigation component looks something like this

    [ViewComponent(Name = "TopNavigation")]
    public class TopNavigationViewComponent : ViewComponent
    {
        private readonly INavigationService navigationService;
    
        public TopNavigationViewComponent(INavigationService navigationService)
        {
            this.navigationService = navigationService;
        }
    
        public IViewComponentResult Invoke(int selected)
        {
            var model = new TopNavigationViewModel()
            {
                Items = this.navigationService.GetTopNavigation(),
            };
            return View(model);
        }
    
    }
    

    The Navigation Service

    public class NavigationService : INavigationService
    {
        private readonly UmbracoHelper umbracoHelper;
        private readonly ISiteSettings siteSettings;
    
        public NavigationService(UmbracoHelper umbracoHelper, ISiteSettings siteSettings)
        {
            this.umbracoHelper = umbracoHelper;
            this.siteSettings = siteSettings;
        }
    
        public List<IPublishedContent> GetSubNavigation(int currentId)
        {
            var currentPage = this.umbracoHelper.Content(currentId);
            var parentOrSelf = currentPage.AncestorOrSelf(2);
            return parentOrSelf.Children?.ToList();
        }
    
        public IEnumerable<UmbNavItem> GetTopNavigation()
        {
            var menu = this.siteSettings.Menu;
            return menu;
        }
    }
    

    And last the site settings. Here I have tried to use IUmbracoContextFactory to retrieve the data without luck. It's the following line

    this.settings.GetProperty(PropertyAlias.HeaderMenu).GetValue() as IEnumerable<UmbNavItem>
    

    that seems to don't have an umbraco context. I thought that using FindContent in IVirtualPageController was used to set the current node, but I suppose it does'nt?

    public class SiteSettings : ISiteSettings
    {
        private readonly UmbracoHelper umbracoHelper;
        private readonly IUmbracoContextFactory umbracoContextFactory;
        private readonly IContentService contentService;
    
        public SiteSettings(UmbracoHelper umbracoHelper, IUmbracoContextFactory umbracoContextFactory, IContentService contentService)
        {
            this.umbracoHelper = umbracoHelper;
            this.umbracoContextFactory = umbracoContextFactory;
            this.contentService = contentService;
        }
    
        private IPublishedContent home => this.umbracoHelper.ContentAtXPath($"//{ContentTypeAlias.Home}")?.FirstOrDefault();
        private IPublishedContent settings  => this.umbracoHelper.ContentAtXPath($"//{ContentTypeAlias.SiteSettings}")?.FirstOrDefault();
    
        public string SiteName => this.home.Name;
    
        public IEnumerable<UmbNavItem> Menu => this.settings.GetProperty(PropertyAlias.HeaderMenu).GetValue() as IEnumerable<UmbNavItem>;
    
    }
    

    So what is the way to accually get the IPublishedContent from that settings when umbracoHelper does not have a Current?

    Calling this will return that Current is null, but only when my custom route is used

    this.settings.GetProperty(PropertyAlias.HeaderMenu).GetValue() as IEnumerable<UmbNavItem>
    Count = 0
        Current: null
        Results View: Expanding the Results View will enumerate the IEnumerable
    

    And I think it's because of AssignedContentItem is not set

    umbracoHelper.AssignedContentItem
    'umbracoHelper.AssignedContentItem' threw an exception of type 
    'System.InvalidOperationException'
    Data: {System.Collections.ListDictionaryInternal}
    HResult: -2146233079
    HelpLink: null
    InnerException: null
    Message: "Cannot return the IPublishedContent because the UmbracoHelper was not constructed with an IPublishedContent."
    Source: "Umbraco.Web.Common"
    StackTrace: "   at Umbraco.Cms.Web.Common.UmbracoHelper.get_AssignedContentItem()"
    TargetSite: {Umbraco.Cms.Core.Models.PublishedContent.IPublishedContent get_AssignedContentItem()}
    
  • Jan A 63 posts 268 karma points
    Feb 14, 2023 @ 10:58
    Jan A
    0

    Ok, more test have been done. I found that HasValue returns true, and if I inspect the value of the property it has a private sourcevalue of

    [{"udi":"umb://document/0dea73210cd349c492846538f436bb33","key":"0dea7321-0cd3-49c4-9284-6538f436bb33","name":"Om oss","description":"/om-oss/","title":"Om oss","url":"/om-oss/","children":[],"icon":"icon-umb-content color-blue","published":true,"naviHide":false,"culture":null,"itemType":"link","id":1075,"collapsed":true},{"udi":"umb://document/bdec7357fd824e36bb112bf0a490614b","key":"bdec7357-fd82-4e36-bb11-2bf0a490614b","name":"Min sida","description":"/min-sida/","url":"/min-sida/","children":[],"icon":"icon-umb-content color-blue","published":true,"naviHide":false,"culture":null,"itemType":"link","id":1080,"collapsed":true}]
    

    So what I did was I created a simple text field in the settings, and I could retrieve that without problem. So it turns out it's not about the context, but about the property somehow.

    The property is of type "AaronSadler.UmbNav" so I guess I may have to look up that implementation?

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies