Umbraco 7 On Publish Event Handler

Publish a node, and execute some code

How to Build an On Publish Event Handler in Umbraco 7+

I am a huge fan of Umbraco. I have been using it and learning as much as possible for the past two years. I came into the game after version 7 was released, and one thing I noticed right away was that the official API documentation was rather lacking, especially when it comes to back-end development. So, that being the case, I have decided to write and post some useful articles on things I have learned and implemented with Umbraco 7+.

Visual Studio Umbraco project setup

So before I get into the code, I wanted to touch on my Visual Studio project setup. There is really no right or wrong way to do this, but I have found that there is very little mention of this type of stuff on the web, so here is what I typically do with new Umbraco projects. I start with a Blank Solution. You can find that by selecting File->New Project->Installed->Templates->Other Project Types->Visual Studio Solutions. This is like a blank wrapper for your application. Once this is created, you can right-click on the solution and add as many different types of projects as you need.

For the main application files, I create a blank ASP.NET Web Application project, usually saved in a folder called web, and install Umbraco via the Nuget Package Manager Console with the following command:

 PM> Install-Package UmbracoCms

For utility classes like the on publish event handler, I like to create a C# class library called lib.util. I have it saved in a folder called library, which I use to house other class libraries as well. Inside lib.util, I have a class file called OnPublishEventHandler.cs. For a class to hook into the Umbraco publish event API, it must inherit from the abstract class ApplicationEventHandler. The rest is pretty straight forward.

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;

namespace lib.util.Umbraco
{
    class OnPublishEventHandler : ApplicationEventHandler
    {
        // Constructor
        public OnPublishEventHandler()
        {
            // Register the onPublish event
            ContentService.Published += Go;
        }

        // Method to create relationship between Bio and a Resource 
        private void RelateBioToResource(IRelationService rs, int nodeId1, int nodeId2)
        {
            var rId = rs.GetRelationTypeById(3);
            var areRelated = rs.AreRelated(nodeId1, nodeId2, rId.Alias);

            if (!areRelated)
            {
                // Create the relation
                var relType = rId;
                var r = new Relation(nodeId1, nodeId2, relType);
                rs.Save(r);
            }
        }

        // Method to create relationship between Resource and a Business Issue
        private void RelateBusinessIssueToResource(IRelationService rs, int nodeId1, int nodeId2)
        {
            var rId = rs.GetRelationTypeById(4);
            var areRelated = rs.AreRelated(nodeId1, nodeId2, rId.Alias);

            if (!areRelated)
            {
                // Create the relation
                var relType = rId;
                var r = new Relation(nodeId1, nodeId2, relType);
                rs.Save(r);
            }
        }

        // Method to create relationship between Bio and a Business Issue
        private void RelateBioToBusinessIssue(IRelationService rs, int nodeId1, int nodeId2)
        {
            var rId = rs.GetRelationTypeById(5);
            var areRelated = rs.AreRelated(nodeId1, nodeId2, rId.Alias);

            if (!areRelated)
            {
                // Create the relation
                var relType = rId;
                var r = new Relation(nodeId1, nodeId2, relType);
                rs.Save(r);
            }
        }
        // When a node gets published, do something
        private void Go(IPublishingStrategy sender, PublishEventArgs<IContent> args)
        {
            foreach (var node in args.PublishedEntities)
            {
                if (node.ContentType.Alias == "Resource")
                {
                    // Get the ID of the node that was published
                    var id = node.Id;

                    // Get the authors related to the published node
                    var ra = node.GetValue("relatedPeople");

                    // Get the Business Issues related to the published node
                    var bi = node.GetValue("relatedBusinessIssues");

                    // Register the RelationService
                    var rs = ApplicationContext.Current.Services.RelationService;

                    // Make sure there is a related author
                    if (ra != null)
                    {
                        // In the case of multiple authors, split the string array
                        string[] b = ra.ToString().Split(",".ToCharArray(),
                                           StringSplitOptions.RemoveEmptyEntries);

                        // Check if all relations match the related people
                        // If not, delete the relation from the database
                        var ids = rs.GetByParentId(id);
                        // Only delete Bio to Resource Relationships
                        foreach (var c in ids.Where(r => r.RelationType.Id == 3)) 
                        {
                            var nodeId = c.ChildId;
                            bool flag = false; // Node ID not found
                            foreach (var temp in b)
                            {
                                var relType = rs;
                                if (temp == nodeId.ToString())
                                {
                                    flag = true;
                                }
                                if (flag == false)
                                {
                                    rs.Delete(c);
                                }
                            }
                        }

                        // To handle multiple authors
                        foreach (var temp in b)
                        {
                            var c = Convert.ToInt32(temp);
                            // Add relation to the database
                            RelateBioToResource(rs, id, c);
                        }
                    }
                    // If all relations from the bio to resource gets removed, 
                   // delete them from the database
                    if (ra == null)
                    {
                        // Check if all relations match the related bios
                        // If not, delete the relation from the database
                        var ids = rs.GetByParentId(id);
                        // Make sure a relationship(s) exists
                        if (ids.Where(r => r.RelationType.Id == 3) != null)
                        {
                            // Only delete Bio to Resource Relationships
                            foreach (var c in ids.Where(r => r.RelationType.Id == 3)) 
                            {
                                rs.Delete(c);
                            }
                        }
                    }
                    // Make sure there is a related business issue
                    if (bi != null)
                    {
                        // In the case of multiple business issues, split the string array
                        string[] b = bi.ToString().Split(",".ToCharArray(),
                                          StringSplitOptions.RemoveEmptyEntries);

                        // Check if all relations match the related business issues
                        // If not, delete the relation from the database
                        var ids = rs.GetByParentId(id);
                        
                        // Only delete Business Issue to Resource Relationships
                        foreach (var c in ids.Where(r => r.RelationType.Id == 4)) 
                        {
                            var nodeId = c.ChildId;
                            bool flag = false; // Node ID not found
                            foreach (var temp in b)
                            {
                                if (temp == nodeId.ToString())
                                {
                                    flag = true;
                                }
                                if (flag == false)
                                {
                                    rs.Delete(c);
                                }
                            }
                        }

                        // To handle multiple business issues
                        foreach (var temp in b)
                        {
                            var c = Convert.ToInt32(temp);
                            // Add relation to the database
                            RelateBusinessIssueToResource(rs, id, c);
                        }
                    }
                    // If all relations from the resource to business issues gets removed,
                    // delete them from the database
                    if (bi == null)
                    {
                        // Check if all relations match the related business issues
                        // If not, delete the relation from the database
                        var ids = rs.GetByParentId(id);
                        // Make sure a relationship(s) exists
                        if (ids.Where(r => r.RelationType.Id == 4) != null)
                        {
                            // Only delete Resource to Business Issue Relationships
                            foreach (var c in ids.Where(r => r.RelationType.Id == 4))
                            {
                                rs.Delete(c);
                            }
                        }
                    }
                }          
            }
        }
    }
}

I left some code in the private void method so you can see an example of something that can be done on the publish event. I will ellaborate more on this piece in another article, but here is the gist. This clients website had a large team of authors who create different types of content and I needed an easy way to relate content and authors, so I hooked in to the native Umbraco Relationship API.

If you have questions or comments, you can send me a message here. I will be posting more fun code snippets and hopefully some in-depth articles on other cool Umbraco topics soon. Word to your mom.

0 comment(s) in response to How to Build an On Publish Event Handler in Umbraco 7+

Have a comment?