Composition + Multi URL Picker - Rendering Footer ...
# help-with-umbraco
w
I've created a composition for footer properties and assigned the Multi URL Picker property to it. This composition is only applied to the HOMEPAGE. I want to be able to render the links in the master template using a partial for the footer HTML - what is the way to go about doing this? https://prnt.sc/vz9LZoBAZH-F https://prnt.sc/_oQmUb3iR75T
In my partial view (footerLinks.cshtml) I have;
Copy code
@{
    // Access the homepage content
    var homePage = Model.Content.Site().Root();
    var multiUrlLinks = homePage.GetPropertyValue<IEnumerable<IPublishedElement>>("footerLink");
}

<nav>
    <ul>
        @foreach (var link in multiUrlLinks)
        {
            var url = link.GetPropertyValue<string>("url");
            var target = link.GetPropertyValue<string>("target");
            var text = link.GetPropertyValue<string>("text");

            <li><a href="@url" target="@target">@text</a></li>
        }
    </ul>
</nav>
But it throws the following error;
System.Web.HttpCompileException: 'D:\sites\PrincipleNetworks.Web\Views\Partials\footerLinks.cshtml(7): error CS1061: 'IPublishedContent' does not contain a definition for 'Content' and no accessible extension method 'Content' accepting a first argument of type 'IPublishedContent' could be found (are you missing a using directive or an assembly reference?)'
I've even tried the following;
Copy code
@using Umbraco.Web.Models
@inherits UmbracoViewPage
    
@{
    var homePage = Model.AncestorOrSelf<Home>();
    var footerLinks = homePage.Value<IEnumerable<IPublishedElement>>("footerLinks");
}

<nav>
    <ul>
        @foreach (var item in footerLinks)
        {
            var link = item.Value<Link>("link");
            <li class="list-inline-item">
                <a href="@link.Url" target="@link.Target">
                    Link title here. 
                </a>
            </li>
        }
    </ul>
</nav>
> System.NullReferenceException: 'Object reference not set to an instance of an object.' > > footerLinks was null.
j
This should work, it looks like you are using the wrong alias when getting the footer links:
var footerLinks = homePage.Value<IEnumerable<IPublishedElement>>("footerLinks");
, from your screen shots it looks like the property is called "Footer link", which would automatically become the alias footerLink. So you should start by double checking your alias, and maybe also consider switching to using modelsbuilder to avoid problems like this 🙂
Also just FYI - what most people end up doing is adding a "Settings/Site" node where they store global information like footer, menu, google tag manager, etc. Then leave the homepage node for just things specific to that.
w
@Jemayn I've made some changes to the code;
Copy code
@using Umbraco.Web.Models
@inherits UmbracoViewPage
    
@{
    var homePage = Model.AncestorOrSelf<Home>();
    var footerLinks = homePage.Value<IEnumerable<IPublishedElement>>("footerLink");

}

<nav>
    <ul>
        @foreach (var item in footerLinks)
        {
            var url = item.Value<string>("url");
            var target = item.Value<string>("target");
            var text = item.Value<string>("text");

            <li class="list-inline-item">
               <a href="@url" target="@target">@text</a>
            </li>
        }
    </ul>
</nav>
System.NullReferenceException: 'Object reference not set to an instance of an object.' footerLinks was null.
j
There are several points along the code that can cause this to be null, you will probably have to check them one by one.. 1. homePage may be null 2. footerLink may be the wrong alias - you can check on the document type what the right one is 3. The footerLink property may not be castable to IEnumerable
Actually looking at it, the picker should be returning IEnumerable as it is content pages and not fx content blocks in a blocklist
w
1) homePage returns
Umbraco.Web.PublishedModels.Home
2) footerLink is the correct alias of the property. I've changed it to
footerLinkItem
to see if that makes a difference. https://prnt.sc/kdfQ_lyJJ4Gr 3) You are correct, it needs to be IPublishedContent as I'm no longer working with blocks. 🙂 I'm still getting the error. footerLinks was null. @Jemayn
j
You can try to remove the type part of the footerLinks part, just to see if it returns anything like the homePage did: var footerLinks = homePage.Value("whateverTheCorrectAliasIsHere");
If it returns anything other than null then it is because IEnumerable is still the wrong type cast
w
Done that and get the following;
System.Web.HttpCompileException: 'D:\sites\PrincipleNetworks.Web\Views\Partials\footerLinks.cshtml(13): error CS1579: foreach statement cannot operate on variables of type 'object' because 'object
so if I do @footerLinks with footerLinkItem as the alias it retuns; System.Collections.Generic.List`1[Umbraco.Web.Models.Link]
How would you go about getting a page URL by ID in Umbraco?
j
so the type is IEnumerable then
w
Makes sense now. So this rightly will throw a compilation error: https://gyazo.com/5b9897d8984eb0dddd20f3cde9bd483b
w
Legend! @Jemayn
The last time I used Umbraco was Umbraco 6 and that was many years ago.
Finding it a little overwhelming but getting to grips with it slowly. I'd definitely build more sites with Umbraco.
j
Np 🙂 Yea lots have changed then 😄
w
I'm not sure what's happened but since deploying the changes to the live server the footer links have stopped working. @Jemayn System.NullReferenceException: 'Object reference not set to an instance of an object.'
var footerLinks = homePage.Value<IEnumerable<Link>>("footerLinkItem");
footerLinks returns:
System.Collections.Generic.List1[Umbraco.Web.Models.Link]
j
homePage is null, you should do a null check before trying to get the links. It looks like the "Home" model doesn't exist?
w
@homePage returns; Umbraco.Web.PublishedModels.Home
I've done;
Copy code
@if(homePage != null)
{
    <p>Homepage is not null.</p>
}
And that is getting rendered.
the links are being rendered in the footer, when you click on the link, that is when it throws the error.
Could it be that the pages are outside of the home node under the Content tab hence why it is throwing an error? @Jemayn - it's the only reason why i think it is breaking. I don't mind getting the page link URL by Id as it's a basic footer and don't ever see it changing much. How would I get the page URL by node Id? I can't seem to find it in the docs.
j
Yea if it's a node which is not a descendant of home then it would fail. To get by id you can do something like this:
Copy code
csharp
var node = Umbraco.Content(nodeId);
var nodeUrl = node?.Url();
If you only have one homepage you could instead replace
var homePage = Model.AncestorOrSelf<Home>();
with:
Copy code
csharp
var rootNodes = Umbraco.ContentAtRoot();
IPublishedContent homepage;

foreach (var rootNode in rootNodes)
{
    var homeNode = rootNode.DescendantOfType(Home.ModelTypeAlias);
    if(homeNode is null) continue;

    homepage = homeNode;
}
Then it will loop through your root nodes and find the homepage then set it so you can use it no matter if it is an ancestor or not.. Depending on your node structure there may be better more performant ways to do this.
w
I've just decided to move the legal pages with the template type of legal under the home node and then used visibility to hide this from the main menu and that now works. Finally got there in the end, might not be the ideal way but it works.
6 Views