Try our conversational search powered by Generative AI!

Add Category on PublishedContent event

Vote:
 

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();
            }
 
            _contentEvents.PublishedContent += contentEvents_PublishedContent;
        }
 
        public void contentEvents_PublishedContent(object sender, ContentEventArgs e)
        {
            if (e.Content is MySpecificPage)
            {
                var contentLoader = ServiceLocator.Current.GetInstance();
                var contentrepository = ServiceLocator.Current.GetInstance();
                var myspecificpage = contentLoader.Get(e.Content.ContentLink);
                if (myspecificpage != null)
                {
                    var clonedpage = myspecificpage.CreateWritableClone();
                    var categoryrepository = ServiceLocator.Current.GetInstance();
                    var categoryList = CreateCategoryList(myspecificpage.Category, categoryrepository);
 
                    var locator = ServiceLocator.Current.GetInstance();
                    var rootCategory = locator.GetRoot();
                    CategoryCollection childCategories = rootCategory.Categories;
                    var catlist = new List();
                    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 CreateCategoryList(CategoryList myspecificpagecategories, CategoryRepository categoryrepository)
        {
            var categoryList = new List();
            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();
            }
 
            _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
Vote:
 

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
Vote:
 

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
Vote:
 

Very nice, thanks alot duders! 

#176153
Mar 10, 2017 18:10
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.