Copied to clipboard

Flag this post as spam?

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


  • Martin Rud 261 posts 1022 karma points c-trib
    Aug 11, 2020 @ 10:05
    Martin Rud
    0

    How to get document url from ContentService.Published?

    I have created a .cs file (in App_Code) to watch for sending the url of published nodes to an external service.

    I have come some of the way but don´t now the last part (see the "???").

    I had hoped I could do it with content.Url, but that throws an error.

    using System.Linq;
    using Umbraco.Core;
    using Umbraco.Web;
    using Umbraco.Core.Composing;
    using Umbraco.Core.Events;
    using Umbraco.Core.Models;
    using Umbraco.Core.Services;
    using Umbraco.Core.Services.Implement;
    
    using System;
    using System.Net;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Net.Http.Headers;
    
    namespace OnDocEvents.Components
    {
        [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
        public class MyComposer : IUserComposer
        {
            public void Compose(Composition composition)
            {
                composition.Components().Append<DocEvents>();
            }
        }
    
        public class DocEvents : IComponent
        {
            private IUmbracoContextFactory _umbracoContext;
    
            public void PublishedComponent(IUmbracoContextFactory umbracoContext)
            {
                _umbracoContext = umbracoContext;
            }
    
            public void Initialize()
            {          
                ContentService.Published += ContentService_Published;
            }
    
            public void Terminate()
            {
                ContentService.Published -= ContentService_Published;
            }
    
            private void ContentService_Published(IContentService sender, ContentPublishedEventArgs e)
            {
                using (UmbracoContextReference contextReference = _umbracoContext.EnsureUmbracoContext())
                {
                    UmbracoContext context = contextReference.UmbracoContext;
                    var content = context.Content.GetById(e.PublishedEntities.First().Id);
    
                    string url = ???;
                }
            }
        }
    }
    
  • James Carter 3 posts 115 karma points
    Aug 11, 2020 @ 13:42
    James Carter
    0

    Hey Martin,

    What error are you receiving when trying to access the Url? I'm guessing your UmbracoContext is in an invalid state.

    It's not a well documented topic but in order to guarantee a valid UmbracoContext outside of a Request scope you must wrap your IUmbracoFactory call in an IScopeProvider call to setup a valid scope.

    I recently fell into a similar issue when handling an Examine Index event and found this answer

    TLDR: try this:

    using (_scopeProvider.CreateScope(autoComplete: true))
    {
         using (UmbracoContextReference contextReference = _umbracoContext.EnsureUmbracoContext())
         {
             UmbracoContext context = contextReference.UmbracoContext;
             var content = context.Content.GetById(e.PublishedEntities.First().Id);
    
             string url = content.Url;
          }
    }
    
  • Martin Rud 261 posts 1022 karma points c-trib
    Aug 12, 2020 @ 07:24
    Martin Rud
    0

    Hi James,

    Thanks. That sounds right. :)

    I get the below error now and need to reference some namespace, but don´t now which.

    Compiler Error Message: CS0103: The name '_scopeProvider' does not exist in the current context
    
    Source Error:
    
    
    Line 101:        {
    Line 102:
    Line 103:            using (_scopeProvider.CreateScope(autoComplete: true))
    Line 104:{
    Line 105:            using (UmbracoContextReference contextReference = _umbracoContext.EnsureUmbracoContext())
    
  • James Carter 3 posts 115 karma points
    Aug 12, 2020 @ 07:46
    James Carter
    101

    Hi Martin,

    You'll need to inject an IScopeProvider into the constructor of your class, along with an IUmbracoFactory. This is achieved using Dependency Injection. The docs are pretty good at explaining what's going on, read here.

    I've taken the liberty of refactoring your code a little to get it working:

    using System.Linq;
    using Umbraco.Core;
    using Umbraco.Core.Composing;
    using Umbraco.Core.Events;
    using Umbraco.Core.Scoping;
    using Umbraco.Core.Services;
    using Umbraco.Core.Services.Implement;
    using Umbraco.Web;
    
    namespace OnDocEvents.Components
    {
        [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
        public class MyComposer : IUserComposer
        {
           public void Compose(Composition composition)
            {
            composition.Components().Append<DocEvents>();
            }
        }
    
        public class DocEvents : IComponent
        {
            private readonly IUmbracoContextFactory _umbracoContext;
            private readonly IScopeProvider _scopeProvider;
    
            public DocEvents(IUmbracoContextFactory umbracoContext, IScopeProvider scopeProvider)
            {
                _umbracoContext = umbracoContext;
                _scopeProvider = scopeProvider;
            }
    
            public void Initialize()
            {
                ContentService.Published += ContentService_Published;
            }
    
            public void Terminate()
            {
                ContentService.Published -= ContentService_Published;
            }
    
            private void ContentService_Published(IContentService sender, ContentPublishedEventArgs e)
            {
                var node = e.PublishedEntities.FirstOrDefault();
    
                if(node == null)
                {
                    return;
                }
    
                using (_scopeProvider.CreateScope(autoComplete: true))
                {
                    using (var contextReference = _umbracoContext.EnsureUmbracoContext())
                    {
                        var context = contextReference.UmbracoContext;
                        var content = context.Content.GetById(node.Id);
    
                        var url = content.Url;
                    }
                }
            }
         }
    }
    
  • Martin Rud 261 posts 1022 karma points c-trib
    Aug 12, 2020 @ 08:21
    Martin Rud
    0

    Cool! Thank you, James! :)

    Your refactored code above works like a charm. :)

  • 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