Umbraco V8 – Bye bye ApplicationEventHandler, Hello Umbraco Components!

Hello all,
OK I wanted to get the ball rolling on trying to get some bits on Umbraco V8 out into the wild and for the tinkerers, hackers and early adopters to play & experiment.

So here is something NEW in Umbraco V8 that you most likely will be using a lot. If you ever used one of Umbraco Services event handlers such as ContentService.Saved or similar, then you would most likely set this up using a class that inherits ApplicationEventHandler.

Show me an example!

I will show a brief example of the old approach using ApplicationEventHandler and then doing the exact same with a shiny new Umbraco Component approach.

Old approach – ApplicationEventHandler

using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;

namespace MyProject.EventHandlers
{
    public class RegisterEvents : ApplicationEventHandler
    {
        protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            //Listen for when content is being saved
            ContentService.Saving += ContentService_Saving;     
        }
        
        /// <summary>
        /// Listen for when content is being saved, check if it is a new item and fill in some
        /// default data.
        /// </summary>
        private void ContentService_Saving(IContentService sender, SaveEventArgs e)
        {                
            foreach (var content in e.SavedEntities
                //Check if the content item type has a specific alias
                .Where(c => c.Alias.InvariantEquals("MyContentType"))
                //Check if it is a new item
                .Where(c => c.IsNewEntity()))
            {
                //check if the item has a property called 'richText'
                if (content.HasProperty("richText"))
                {
                    //get the rich text value
                    var val = c.GetValue("richText");
                    
                    //if there is a rich text value, set a default value in a 
                    // field called 'excerpt' that is the first
                    // 200 characters of the rich text value
                    c.SetValue("excerpt", val == null
                        ? string.Empty 
                        : string.Join("", val.StripHtml().StripNewLines().Take(200)));
                }
            }
        }
    }
}

New approach – Umbraco Components

using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Components;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;

namespace MyProject.Components
{
    /// <summary>
    /// All IUmbracoUserComponents run after all IUmbracoCoreComponent have run
    /// This way we can ensure Umbraco is all setup and stuff is available for us to use
    /// </summary>
    public class ExampleComponent : UmbracoComponentBase, IUmbracoUserComponent
    {
        public void Initialize()
        {
            ContentService.Saving += ContentService_Saving;
        }

        /// <summary>
        /// Listen for when content is being saved, check if it is a 
        /// new item and fill in some default data.
        /// </summary>
        private void ContentService_Saving(IContentService sender, SaveEventArgs e)
        {
            foreach (var content in e.SavedEntities
                //Check if the content item type has a specific alias
                .Where(c => c.ContentType.Alias.InvariantEquals("MyContentType"))
                //Check if it is a new item
                .Where(c => c.IsNewEntity()))
            {
                //check if the item has a property called 'richText'
                if (content.HasProperty("richText"))
                {
                    //get the rich text value
                    var val = content.GetValue("richText");

                    //if there is a rich text value, set a default value in a 
                    // field called 'excerpt' that is the first
                    // 200 characters of the rich text value
                    content.SetValue("excerpt", val == null
                        ? string.Empty
                        : string.Join("", val.StripHtml().StripNewLines().Take(200)));
                }
            }
        }
    }
}

You can see very little has changed to the code, where we inherit from UmbracoComponentBase and IUmbracoUserComponentinstead instead of ApplicationEventHandler.

Why has it changed?

I will try my best to explain this, after I chatted with the brains behind it aka Stephan. This is mostly to help with the future and to avoid some confusion.

because app event handler means… “handles events” and although it’s true, it’s misleading. a component is a part of the whole app, so you add components to “compose” your ideal application – your component can handle events if they want – it’s just a more general notion

What benefits does it have over the old approach?

Again after a quick chat with Stephan on trying to get to know the in’s & out’s of how this works.

For ex when you wanted to change how things where composed (register a new finder etc) you would have to remember to do it in the proper “event” – and people were always confused – now there’s the Composemethod explicitly for this usage – same for Initialize, more explicit + manages dependencies & injection

Also components can depend on each other and this ensures they run one after another, whereas ApplicationEventHandlers were in random order and are easy to enable/disable components, which could not be done with app handlers.

oh and components also terminate meaning they are notified when Umbraco stops

So an example that Stephan explained to me could be

so you create a component, and in Compose you tell Umbraco that it should use MyCache as a content cache. In Initialize you load your cache from wherever you want. In Terminate you flush changes to disk.

Further Examples

Here is an example of a component registering my own custom LastChanceFinder

using Umbraco.Core.Components;

namespace MyProject.Components
{
    /// <summary>
    /// All IUmbracoUserComponents run after all IUmbracoCoreComponent have run
    /// This way we can ensure Umbraco is all setup and stuff is available for us to use
    /// </summary>
    public class MyLastChanceFinderComponent : UmbracoComponentBase, IUmbracoUserComponent
    {
        public override void Compose(Composition composition)
        {
            base.Compose(composition);
            composition.SetContentLastChanceFinder();
        }
    }
}

So that’s it for now and I will share more insights into Umbraco V8 when I can or that I know that code for a piece of functionality is unlikely to change after checking with the brains of the project aka Stephan or Shannon ๐Ÿ™‚

Thanks again Stephan for the 101 questions I have had on this!

Until next time, happy hacking & exploring !

Advertisements

I attended the Umbraco Examine Course & you won’t believe what happened next

If you were at this year annual Umbraco developer conference CodeGarden, you may have seen a lightning talk with a click-bait title in the scheduled and then it magically disappeared like one of Damiaan’s magic tricks

So you may be wondering what the hell happened to it?!

I will be honest & frank with you, during CodeGarden I was having a crap time on the inside whilst I battled dealing with the large crowds with depression & anxiety and was using drink as a coping mechanism to try suppress my emotions.

I woke up on day two of CodeGarden in a mess physically with a crap hangover and mentally with the exhaustion of feelings. After a chat with my lovely bosses at the HQ, who always ensure we are looked after. It was decided it was best I jump on the first plane and get home as soon as possible for rest, recovery & to sort myself out.ย Unfortunately I have been in a similar place before and I did not want the same state ofย  psychosis and being back in hospital.ย 

So I wanted to share this story, to try and help reduce the stigma and help others who may be experiencing similar problems to let them know they are not alone and that it’s super important to look after yourself and talk to someone, as Ravi mentions in his lightning talk.

OK i’ll wrap up that short summary there…

Enough of that, just show me the talk; Warren!

Without further a do, I present to you the talk that I didn’t give from my kitchen, so if my talk is a terrible mess I’ve decided I am going to start doing a cooking YouTube channel ๐Ÿ˜›

Slides

Are you one of those people who like to refer to slides, if so I got your back and you can download and view them here.

Questions?

Watched or read through the slides and have some questions, then leave a comment on this post or send me a message on twitter @warrenbuckley