Moving from Umbraco 7 to 10 -- how do you use IPublishedContent.Url()?
z
As per the title. I am migrating v7 code to v10. The old code uses myPublishedContent.Url which no longer exists. It looks like I need to use the .Url() method now, but I am not sure what properties I'm supposed to pass into it. I am trying to do something like this:
var englishHomePage = currentContextContent?.GetById(_config.Value.ContentUids.HomePages.English);
string englishHomePageUrl = englishHomePage.Url()
actually, looks like I just need to inject IPublishedUrlProvider and pass the instance in?
m
using Umbraco.Extensions will also give you the "friendly" version that means you don't need to add the provider
z
Matt - am I missing something? I have both Umbraco.Extensions and Umbraco.Cms.Core.Extensions referenced, but Intellisense is telling me the IPublishedUrlProvider is required.
m
If you build does it fail? Intellisense sometimes breaks
z
I'll check that out and come back, lots of bits to isolate before it'll build. Embarrassing if it's just that!
@Matt Wise - I still have the same issue, but I think I've bumped into it another way via a different method. Is the problem, Extensions can only be used within views? I am now trying to do something like this:
Copy code
public IViewComponentResult InvokeAsync()
    {
        var currentPage = _umbracoContextAccessor
            ?.GetRequiredUmbracoContext()
            ?.PublishedRequest
            ?.PublishedContent;

        var homePage = currentPage?.AncestorOrSelf("home");

        FooterViewModel footerViewModel = new()
        {
            FooterLinks = homePage?.Value<IEnumerable<Link>>("footerLinks")
        };

        return View(footerViewModel);
    }
However, like the Url method defined in Umbraco.Extensions, the Umbraco.Extensions Value method can not be found if using outside of a view. If I pull code into the view, it works:
Copy code
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<FooterViewModel>
@{
    var currentPage = Umbraco.AssignedContentItem;
    var homePage = currentPage.AncestorOrSelf("home");
    var footerLinks = homePage?.Value<IEnumerable<Link>>("footerLinks") ?? null!;
    
    // footerLinks is populated here. 
   
}
My first example within a service/helper, this example is on a view component.
a
If you have an IPublishedContent object, you should be able to get the .Url anywhere basiocally
Btw I can very much recommend using ModelsBuilder, so you dont have to type nasty stuff like
homePage?.Value<IEnumerable<Link>>("footerLinks")
and just type
homepage.FooterLinks
🙂
Typed is just so much easier and readable.
Also, im not sure what you're trying to achieve currently :/
z
Thanks - I did end up using ModelsBuilder, just referencing old code that I am slowly converting. Not really trying to achieve anything, just trying to port the old code over. I just realised "nice" .Url .Value methods from Umbraco.Extensions never seem to work outside of the View.
a
@ZimmertyZim Im just checking this, and I just use
.Url()
in my controllers if I need the Url from an IpublishedContent
So why the difference between
.Url
and
.Url()
, no idea 😄
a
.Url()
has some optional parameters - eg. for specifying which culture you want the URL for. You can only do that with a method - not with a property. I think that is the reason behind the change.
z
back on this, can someone confirm if Umbraco.Extensions doesn't work outside of a View? Still porting old code, I am tyring to do convert this, which is defined at the top of a partial view:
Copy code
IEnumerable<IPublishedContent> navigationPages = homePage.Children(x => x.IsVisible() && x.DocumentTypeAlias != "home" && !x.GetPropertyValue<bool>("hideFromNavigation"));
the new code being this, this is defined in a ViewComponent:
Copy code
//_variationContextAccessor and _publishedValueFallback are injected
   var naviagtionPages = homePage
            ?.Children(_variationContextAccessor, x => x.IsVisible(_publishedValueFallback) && !x.HasValue("hideFromTopNavigation"));
As far as I understand,
_publiushedValueFallback
and
_variationContentAccesor
shouldn't be needed due to Umbraco.Extensions? I am aware that I should be using the Models Builder, just not sure how to do it in his scenario when looking at multiple content types.
I understand it's gone a bit off topic, but it all eems to tie back to being able to use the nice extension methods
a
Theoretically the correct approach for dependency injection is to pass two dependencies on to the extension methods. This is why the extension methods are implemented as they are. But they can also be a bit cumbersome to use this way, so to help with migrations (among other things), Umbraco has some friendly version of those extension methods, which when doesn't require a
_variationContextAccessor
or a
_publishedValueFallback
. I think you find the friendly extension methods by importing the
Umbraco.Extensions
namespace.
z
right, that's my understanding as well. I am importing that namespace, but the I am still being asked for the dependencies, it's as if Intellisense/VS just ignores Umbraco.Extension, but it works fine if I add the code to the view
Copy code
using Microsoft.AspNetCore.Mvc;

using MyApplication.Models;
using MyApplication.Web.Models.ViewModels;

using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;

namespace MyApplication.Web.ViewComponents.SiteLayout;

[ViewComponent(Name = "TopNavigation")]
public class TopNavigationViewComponent : ViewComponent
{

    private readonly IUmbracoContextAccessor _umbracoContextAccessor;
    private readonly IVariationContextAccessor _variationContextAccessor;
    private readonly IPublishedValueFallback _publishedValueFallback;

    public TopNavigationViewComponent(
        IUmbracoContextAccessor umbracoContextAccessor,
        IVariationContextAccessor variationContextAccessor,
        IPublishedValueFallback publishedValueFallback
        )
    {
        _umbracoContextAccessor = umbracoContextAccessor;
        _variationContextAccessor = variationContextAccessor;
        _publishedValueFallback = publishedValueFallback;
    }

    public IViewComponentResult Invoke()
    {
        var currentPage = _umbracoContextAccessor
            ?.GetRequiredUmbracoContext()
            ?.PublishedRequest
            ?.PublishedContent;

        var homePage = Helpers.Site.GetHomeNode(currentPage ?? null!) as Home;

        var naviagtionPages = homePage
              ?.Children(_variationContextAccessor, x => x.IsVisible(_publishedValueFallback) && !x.HasValue("hideFromTopNavigation") && x.GetType() != typeof(Home));
        
        TopNavigationViewModel topNavigationViewModel = new()
        {
            NavigationPages = naviagtionPages
        };

        return View("/Views/Shared/Components/SiteLayout/TopNavigation.cshtml", topNavigationViewModel);
    }
}
a non trimmed down verison so you can see using and dependencies
would you expect Umbraco.Extensions to work here?
3 Views