Copied to clipboard

Flag this post as spam?

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


  • Darren Hunter 140 posts 232 karma points
    Jul 24, 2023 @ 14:01
    Darren Hunter
    0

    Umbraco 10 Multiple Sites

    Hi,

    I am trying to build a controller that needs to work on a Multi Site implementation of Umbraco.

    In a controller how would I get the active Node.

    Thanks.

    I have tried this

    UmbracoHelper helper = new UmbracoHelper(_CultureDictionaryFactory, _UmbracoComponentRenderer, _publishedContentQuery);

    var homeNodes = helper.ContentAtRoot(); var homeNode = helper.ContentAtRoot().FirstOrDefault();

    and this

    var urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext); var url = urlHelper.ActionContext.HttpContext.Request.GetDisplayUrl(); var uri = new Uri(url); string urlIWant = uri.GetLeftPart(UriPartial.Authority);

            using (UmbracoContextReference umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext())
            {
                var rootNodes = umbracoContextReference.UmbracoContext.Content.GetAtRoot();
    
    
    
                var s = "";
    
            }
    

    I need to be able to get the active node. Not all the nodes.

  • Marc Goodson 2155 posts 14408 karma points MVP 9x c-trib
    Jul 25, 2023 @ 08:06
    Marc Goodson
    0

    Hi Darren

    I may be misunderstanding, depending on what kind of controller you are in.

    If your controller inherits from one of the base Umbraco types, eg SurfaceController,RenderController then you'd have access via the 'CurrentPage' property to the current page...

    var currentPage = CurrentPage;
    

    https://github.com/umbraco/Umbraco-CMS/blob/05b89999afb65caf7e8dd7f17d34edbaa10cc842/src/Umbraco.Web.Website/Controllers/SurfaceController.cs#L40

    If you are in a view and have access to the UmbracoHelper class via the 'Umbraco' gateway then

    @Umbraco.AssignedContentItem 
    

    will get you the current page...

    and if it is in the context of a http request then you should be able to inject IUmbracoContextAccessor into your class and then get the current page via the PublishedRequest's PublishedContent:

    _umbracoContextAccessor.TryGetUmbracoContext(out var context);
    context.PublishedRequest.PublishedContent
    

    The other trick worth knowing if you are working with multiple sites and trying to get a reference to the homepage for the current site, is that every Umbraco IPublishedContent item, (eg the model for the page you are currently on, has a 'Path' property, and that Path, is a comma delimited list of content ids, going from the current page all the way up the umbraco content tree to the top... so that can be a quick way to find out 'which site' you are in, depending on what the toppermost Id is...

    regards

    marc

  • Darren Hunter 140 posts 232 karma points
    Jul 25, 2023 @ 08:14
    Darren Hunter
    0

    enter image description here

    I am getting the same issue as I was seeing yesterday using that method. This controls not attached to a page or a model. I am trying to build a generic sitemap.dll that can be used on a single or multi site configuration.

    At the moment I am looking at adding a section to the config file and using a URL lookup as that seems to be the only way of doing it.

  • Marc Goodson 2155 posts 14408 karma points MVP 9x c-trib
    Jul 25, 2023 @ 08:30
    Marc Goodson
    0

    Hi Darren

    It's because the extension of the file you are routing to sitemap.xml is not considered to be of a type that Umbraco knows about, therefore the request has no Umbraco Context associated with it, hence everything is null.

    But you can 'tell' Umbraco that you do want it to be treated like an Umbraco request... by doing this in your startup.cs

    services.Configure<UmbracoRequestOptions>(options => options.HandleAsServerSideRequest = httpRequest => httpRequest.Path.StartsWithSegments("/sitemap.xml") || httpRequest.Path.StartsWithSegments("/sitemap_index.xml"));
    

    Some info here:

    https://docs.umbraco.com/umbraco-cms/implementation/services#handle-routes-as-server-side-requests

    regards

    Marc

  • Darren Hunter 140 posts 232 karma points
    Jul 25, 2023 @ 13:38
    Darren Hunter
    0

    That did not work for now I am doing it based on URL, using a Json with a list of ULR and Top Node IDs, to get the top node for the selected site.

    It a pain doing it this way but for now that the only work around I could work out as at the point where my control is been called it inside the sub system and I do not have any page content.

  • Marc Goodson 2155 posts 14408 karma points MVP 9x c-trib
    Jul 25, 2023 @ 16:52
    Marc Goodson
    0

    Hi Darren

    I have this working on a V10 site, I found the issue originally on V9:

    Here was the fix:

    https://github.com/umbraco/Umbraco-CMS/pull/12088

    So puzzled this isn't working for you!

    Which version are you running, we should raise it as a bug if this has reverted!

    This is my Controller:

        public class SitemapXmlController : UmbracoPageController, IVirtualPageController
        {
            private ISiteService _siteService;
            private IOptions<SiteSettingsOptions> _siteSettings;
            private ISitemapService _sitemapService;
    
            public SitemapXmlController(ILogger<SitemapXmlController> logger,
                ICompositeViewEngine compositeViewEngine,
                ISiteService siteService,
                            IOptions<SiteSettingsOptions> siteSettings,
                ISitemapService sitemapService)
            : base(logger, compositeViewEngine)
            {
                _siteService = siteService;
                _siteSettings = siteSettings;
                _sitemapService = sitemapService;
            }
    
            public IPublishedContent FindContent(ActionExecutingContext actionExecutingContext)
            {
                var siteSettings = _siteSettings.Value;
                return _siteService.GetSiteHomepage();
            }
    
            #region Private Methods
    
            public IActionResult XmlSitemap()
            {
                var sitemap = string.Empty;
    
                if (CurrentPage != null)
                {
                    var xmlSitemap = new SiteMap();
                    xmlSitemap = _sitemapService.BuildXMLSitemapModel(CurrentPage);
    
                    sitemap = xmlSitemap.ToXml();
                }
                return Content(sitemap, "application/xml");
    
            }
            #endregion
        }
    }
    

    You can see I use IVirtualPageController to map the specific Umbraco item to the request, by implementing 'FindContent', it's in the FindContent where you would locate your homepage based on the request context in the ActionExecutingContext object.

    And then I Map the Custom Route:

    public static IUmbracoEndpointBuilderContext MapCustomRoutes(this IUmbracoEndpointBuilderContext app)
        {
            app.EndpointRouteBuilder.MapControllerRoute(
                "sitemap",
                "/sitemap.xml",
                new { Controller = "SitemapXml", Action = "XmlSiteMap" });
            return app;
        }
    

    and finally the telling Umbraco to use Sitemap.xml as a serverside request:

    services.Configure<UmbracoRequestOptions>(options => options.HandleAsServerSideRequest = httpRequest => httpRequest.Path.StartsWithSegments("/sitemap.xml") || httpRequest.Path.StartsWithSegments("/sitemap_index.xml"));
    

    Do you have all three pieces of the puzzle?

    regards

    Marc

  • Darren Hunter 140 posts 232 karma points
    Jul 26, 2023 @ 07:30
    Darren Hunter
    0

    Latest V10 as of this post.

  • Marc Goodson 2155 posts 14408 karma points MVP 9x c-trib
    Jul 26, 2023 @ 08:40
    Marc Goodson
    0

    Hi Darren

    So with your registering of the /sitemap.xml as a serverside request.

    If you put a breakpoint inside your 'FindContent' method.

    Does it get hit?

    can you read the properties of ActionExecutingContext ok?

    (will be upgrading this site to latest V10 at end of month, so will probably find out if it's been broken).

    regards

    Marc

  • Darren Hunter 140 posts 232 karma points
    Jul 26, 2023 @ 09:13
    Darren Hunter
    0

    This is what in startup at the moment.

    _service.Configure

  • Marc Goodson 2155 posts 14408 karma points MVP 9x c-trib
    Jul 26, 2023 @ 09:29
    Marc Goodson
    0

    Hi Darren

    Looking at the snippet you posted before (I can't see what type of Controller you are using)

    You seem to be trying to get the PublishedContent inside the buildSitemap() method

    But when you implement IVirtualPageController you have to implement a FindContent method, and that's where you will be getting the context of the IPublishedContent item based on the request

    Then inside your buildSitemap() you'd be able to get the IPublishedContent by using 'CurrentPage' - the FindContent method will set the CurrentPage for the request to the sitemap.

    regards

    Marc

  • Darren Hunter 140 posts 232 karma points
    Jul 26, 2023 @ 09:31
    Darren Hunter
    0

    Thank you for your help.

Please Sign in or register to post replies

Write your reply to:

Draft