Add Category on PublishedContent event

Hi,

My page has a bunch of categories that are very specific, and I'd like to categorize them programatically by adding an category when they are published, depending on what category the editor has selected. In this specific case the editor has selected the page to have the category "Air Max" and I want to add the category called "Shoes" to the page when the editor publishes. So i've made an IInitializableModule that I cant get to work. The big issue is the CreateWriteableClone part on the PublishedContent event, take a look;

namespace MyWebsite.Business.Initialization
{
    [InitializableModule]
    [ModuleDependency(typeof(global::EPiServer.Web.InitializationModule))]
    public class PublishedContentCategoryInitialization : IInitializableModule
    {
        private IContentEvents _contentEvents;
        public void Initialize(InitializationEngine context)
        {
            if (_contentEvents == null)
            {
                _contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
            }
 
            _contentEvents.PublishedContent += contentEvents_PublishedContent;
        }
 
        public void contentEvents_PublishedContent(object sender, ContentEventArgs e)
        {
            if (e.Content is MySpecificPage)
            {
                var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
                var contentrepository = ServiceLocator.Current.GetInstance<IContentRepository>();
                var myspecificpage = contentLoader.Get<MySpecificPage>(e.Content.ContentLink);
                if (myspecificpage != null)
                {
                    var clonedpage = myspecificpage.CreateWritableClone();
                    var categoryrepository = ServiceLocator.Current.GetInstance<CategoryRepository>();
                    var categoryList = CreateCategoryList(myspecificpage.Category, categoryrepository);
 
                    var locator = ServiceLocator.Current.GetInstance<CategoryRepository>();
                    var rootCategory = locator.GetRoot();
                    CategoryCollection childCategories = rootCategory.Categories;
                    var catlist = new List<Category>();
                    foreach (Category category in childCategories)
                    {
                        catlist.Add(category);
                    }
 
                    if (categoryList.Any(x => x.LocalizedDescription == "Air Max"))
                    {
                        var shoecategory = categoryrepository.Get("Shoes");
                        page.Category.Add(shoecategory.ID);
                    }

                  contentrepository.Save(page, SaveAction.Publish, AccessLevel.NoAccess);
                }
            }
        }
 
        private List<Category> CreateCategoryList(CategoryList myspecificpagecategories, CategoryRepository categoryrepository)
        {
            var categoryList = new List<Category>();
            foreach (int catId in myspecificpagecategories)
            {
                Category category = categoryrepository.Get(catId);
                categoryList.Add(category);
            }
 
            return categoryList;
        }
 
        public void Preload(string[] parameters) { }
 
        public void Uninitialize(InitializationEngine context)
        {
            if (_contentEvents == null)
            {
                _contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
            }
 
            _contentEvents.PublishedContent -= contentEvents_PublishedContent;
        }
    }
}

The Category gets added, but I always end up in an infinite loop of publishing and publishing and publishing.. Has anyone solved this issue in a better way, like adding a category to a page programatically on publish? Im running latest version of EPi btw. 

Thanks!

#176100 Mar 09, 2017 21:04
  • Member since: 2013

    You should use Publishing event and not published. And if I understand the code correctly you are getting the page again from the DB which is not needed e.Content is writable so just cast it to a new var

    var myspesificpage = e.Content as MySpesificPage;

    if you do like that, then every change you do to "myspesificpage" will be saved and you don't need the "contentrepository.Save" (which will then again call the publishing/published event)

    namespace MyWebsite.Business.Initialization
    {
        [InitializableModule]
        [ModuleDependency(typeof(global::EPiServer.Web.InitializationModule))]
        public class PublishedContentCategoryInitialization : IInitializableModule
        {
            private IContentEvents _contentEvents;
            public void Initialize(InitializationEngine context)
            {
                if (_contentEvents == null)
                {
                    _contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
                }
    
                _contentEvents.PublishingContent += contentEvents_PublishingContent;
            }
    
            public void contentEvents_PublishingContent(object sender, ContentEventArgs e)
            {
                var myspecificpage = e.Content as MySpecificPage;
                if (myspecificpage != null)
                {
                    var categoryrepository = ServiceLocator.Current.GetInstance<CategoryRepository>();
                    var categoryList = CreateCategoryList(myspecificpage.Category, categoryrepository);
    
                    var rootCategory = categoryrepository.GetRoot();
                    CategoryCollection childCategories = rootCategory.Categories;
                    var catlist = new List<Category>();
                    foreach (Category category in childCategories)
                    {
                        catlist.Add(category);
                    }
    
                    if (categoryList.Any(x => x.LocalizedDescription == "Air Max"))
                    {
                        var shoecategory = categoryrepository.Get("Shoes");
                        myspecificpage.Category.Add(shoecategory.ID);
                    }
                }
            }
    
            private List<Category> CreateCategoryList(CategoryList myspecificpagecategories, CategoryRepository categoryrepository)
            {
                var categoryList = new List<Category>();
                foreach (int catId in myspecificpagecategories)
                {
                    Category category = categoryrepository.Get(catId);
                    categoryList.Add(category);
                }
    
                return categoryList;
            }
    
            public void Preload(string[] parameters) { }
    
            public void Uninitialize(InitializationEngine context)
            {
                if (_contentEvents == null)
                {
                    _contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
                }
    
                _contentEvents.PublishingContent -= contentEvents_PublishingContent;
            }
        }
    }

    Code is not testet so can't promise anything :)

    #176115 Edited, Mar 10, 2017 9:08
  • Member since: 2004

    As mentioned above, be really carefull when you use PublishedContent, it can very easy cause an infinite loop. PublishingContent is the way to go.

    #176132 Mar 10, 2017 10:36
  • Very nice, thanks alot duders! 

    #176153 Mar 10, 2017 18:10